Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************************************************************
- *
- * MIT License
- *
- * Copyright (c) 2018 Benjamin Collins (kion @ dashgl.com)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- *****************************************************************************/
- THREE.DashExporter = function() {
- this.influence = false;
- this.groupflags = {
- uv0 : false,
- uv1 : false,
- normal : false,
- vcolor : false
- };
- this.bones = [];
- this.vertices = [];
- this.textures = [];
- this.materials = [];
- this.groups = [];
- this.anims = [];
- this.blocks = [];
- }
- THREE.DashExporter.prototype = {
- constructor : THREE.DashExporter,
- parse : function(mesh) {
- // Get Bones
- this.getBones(mesh.skeleton);
- // Get Vertices
- this.getVertices(mesh.geometry);
- // Get Textures
- this.getTextures(mesh.material);
- // Get Materials
- this.getMaterials(mesh.material);
- // Get Face groups
- this.getGroups(mesh.geometry);
- // Get Animations
- this.getAnims(mesh.geometry);
- // write blocks
- this.writeBones();
- // Write vertices
- this.writeVertices();
- // Write Textures
- this.writeTextures();
- // Write Materials
- this.writeMaterials();
- // Write Face Groups
- this.writeFaceGroups();
- // Write Header
- this.writeHeader();
- // Write blob to zip (for testing)
- return this.writeBlob();
- },
- getBones : function(skeleton) {
- if(!skeleton) {
- return;
- }
- // Populate bones
- for(let i = 0; i < skeleton.bones.length; i++) {
- let bone = {
- id : i,
- elements : skeleton.bones[i].matrix.elements
- };
- if(i === 0) {
- bone.parent = -1;
- } else {
- bone.parent = skeleton.bones[i].parent.name
- }
- this.bones.push(bone);
- }
- },
- getVertices : function(geometry) {
- // If bones exist, check for number of influence
- if(this.bones.length) {
- this.influence = true;
- }
- // Read all of the vertices
- for(let i = 0; i < geometry.vertices.length; i++) {
- let vertex = {
- pos : {
- x : geometry.vertices[i].x,
- y : geometry.vertices[i].y,
- z : geometry.vertices[i].z
- }
- };
- if(this.influence) {
- vertex.indice = {
- x : geometry.skinIndices[i].x,
- y : geometry.skinIndices[i].y,
- z : geometry.skinIndices[i].z,
- w : geometry.skinIndices[i].w
- }
- vertex.weight = {
- x : geometry.skinWeights[i].x,
- y : geometry.skinWeights[i].y,
- z : geometry.skinWeights[i].z,
- w : geometry.skinWeights[i].w
- }
- }
- this.vertices.push(vertex);
- }
- },
- getTextures : function(material) {
- // Check if single material is used
- if(!Array.isArray(material)) {
- material = [material];
- }
- // Get texture for each material
- for(let i = 0; i < material.length; i++) {
- if(!material[i].map) {
- continue;
- }
- let uuid = material[i].map.uuid;
- let found = false;
- for(let k = 0; k < this.textures.length; k++) {
- if(this.textures[k].uuid !== uuid) {
- continue;
- }
- found = true;
- break;
- }
- if(found) {
- continue;
- }
- this.textures.push({
- uuid : uuid,
- img : material[i].map.image
- });
- }
- },
- getMaterials : function(material) {
- // Check if single material is used
- if(!Array.isArray(material)) {
- material = [material];
- }
- // Get texture for each material
- for(let i = 0; i < material.length; i++) {
- // Default Diffuse
- let mat = {
- diffuse : {
- r : material[i].color.r,
- g : material[i].color.g,
- b : material[i].color.b
- }
- };
- // If texture, set index reference
- if(material[i].map) {
- let uuid = material[i].map.uuid;
- for(let k = 0; k < this.textures.length; k++) {
- if(this.textures[k].uuid !== uuid) {
- continue;
- }
- mat.map0 = k;
- break;
- }
- }
- this.materials.push(mat);
- }
- },
- getGroups : function(geometry) {
- // Check for uv0
- if(geometry.faceVertexUvs && geometry.faceVertexUvs[0]) {
- this.groupflags.uv0 = true;
- }
- // Check for uv1
- if(geometry.faceVertexUvs && geometry.faceVertexUvs[1]) {
- this.groupflags.uv1 = true;
- }
- // Check for vertex normal
- if(geometry.faces[0].vertexNormals.length) {
- this.groupflags.normal = true;
- }
- // Check for vertex color
- if(geometry.faces[0].vertexColors.length) {
- this.groupflags.vcolor = true;
- }
- // Loop over the faces
- let group;
- let matId = -1;
- for(let i = 0; i < geometry.faces.length; i++) {
- let face = geometry.faces[i];
- let matIndex = face.materialIndex;
- if(matId !== matIndex) {
- if(group) {
- this.groups.push(group);
- }
- matId = matIndex;
- group = {
- matIndex : matIndex,
- tri : []
- };
- }
- let a = {
- index : face.a
- }
- let b = {
- index : face.b
- }
- let c = {
- index : face.c
- }
- if(this.groupflags.uv0) {
- a.uv0 = {
- u : geometry.faceVertexUvs[0][i][0].x,
- v : geometry.faceVertexUvs[0][i][0].y
- }
- b.uv0 = {
- u : geometry.faceVertexUvs[0][i][1].x,
- v : geometry.faceVertexUvs[0][i][1].y
- }
- c.uv0 = {
- u : geometry.faceVertexUvs[0][i][2].x,
- v : geometry.faceVertexUvs[0][i][2].y
- }
- }
- if(this.groupflags.vcolor) {
- a.vcolor = {
- r : face.vertexColors[0].r,
- g : face.vertexColors[0].g,
- b : face.vertexColors[0].b
- }
- b.vcolor = {
- r : face.vertexColors[1].r,
- g : face.vertexColors[1].g,
- b : face.vertexColors[1].b
- }
- b.vcolor = {
- r : face.vertexColors[2].r,
- g : face.vertexColors[2].g,
- b : face.vertexColors[2].b
- }
- }
- group.tri.push(a, b, c);
- }
- this.groups.push(group);
- },
- getAnims : function(geometry) {
- if(!geometry.animations || !geometry.animations.length) {
- return;
- }
- for(let i = 0; i < geometry.animations.length; i++) {
- }
- },
- calcBufferLen : function(byteLen) {
- let bufferLen;
- let remainder = byteLen % 16;
- if(remainder === 8) {
- bufferLen = byteLen + 8;
- } else if(remainder < 8) {
- bufferLen = byteLen + (16 - remainder);
- } else {
- bufferLen = byteLen + (16 - remainder) + 16;
- }
- return bufferLen;
- },
- writeBones : function() {
- if(!this.bones.length) {
- return;
- }
- // First read the bones list
- let structSize = (16 * 4 + 4);
- let byteLen = this.bones.length * structSize;
- let bufferLen = this.calcBufferLen(byteLen);
- let buffer = new ArrayBuffer(bufferLen);
- let view = new DataView(buffer);
- view.setUint8(0, 0x42); // 'B'
- view.setUint8(1, 0x4F); // '0'
- view.setUint8(2, 0x4E); // 'N'
- view.setUint8(3, 0x45); // 'E'
- view.setUint32(4, byteLen, true);
- let ofs = 8;
- for(let i = 0; i < this.bones.length; i++) {
- view.setInt16(ofs, this.bones[i].id, true);
- view.setInt16(ofs + 2, this.bones[i].parent, true);
- ofs += 4;
- this.bones[i].elements.forEach(e => {
- view.setFloat32(ofs, e, true);
- ofs += 4;
- });
- }
- this.blocks.push({
- type : "BONE",
- num : this.bones.length,
- buffer : buffer
- });
- },
- writeVertices : function() {
- let structSize = 12;
- if(this.influence) {
- structSize += 2*4 + 4*4;
- }
- let byteLen = this.vertices.length * structSize;
- let bufferLen = this.calcBufferLen(byteLen);
- let buffer = new ArrayBuffer(bufferLen);
- let view = new DataView(buffer);
- view.setUint8(0, 0x56); // 'V'
- view.setUint8(1, 0x45); // 'E'
- view.setUint8(2, 0x52); // 'R'
- view.setUint8(3, 0x54); // 'T'
- view.setUint32(4, byteLen, true);
- let ofs = 8;
- for(let i = 0; i < this.vertices.length; i++) {
- view.setFloat32(ofs + 0, this.vertices[i].x, true);
- view.setFloat32(ofs + 4, this.vertices[i].y, true);
- view.setFloat32(ofs + 8, this.vertices[i].z, true);
- ofs += 12;
- if(!this.influence) {
- continue;
- }
- view.setUint16(ofs + 0, this.vertices[i].indice.x, true);
- view.setUint16(ofs + 2, this.vertices[i].indice.y, true);
- view.setUint16(ofs + 4, this.vertices[i].indice.z, true);
- view.setUint16(ofs + 6, this.vertices[i].indice.w, true);
- ofs += 8;
- view.setFloat32(ofs + 0, this.vertices[i].weight.x, true);
- view.setFloat32(ofs + 4, this.vertices[i].weight.y, true);
- view.setFloat32(ofs + 8, this.vertices[i].weight.z, true);
- view.setFloat32(ofs + 12, this.vertices[i].weight.w, true);
- ofs += 16;
- }
- this.blocks.push({
- type : "VERT",
- buffer : buffer,
- num : this.vertices.length,
- flag : this.influence
- });
- },
- writeTextures : function() {
- for(let i = 0; i < this.textures.length; i++) {
- switch(this.textures[i].img.tagName) {
- case "CANVAS":
- let canvas = this.textures[i].img;
- let data = canvas.toDataURL("image/png");
- let index = data.indexOf(',')+1
- data = data.substr(index);
- data = window.atob(data);
- let byteLen = data.length;
- let bufferLen = this.calcBufferLen(byteLen);
- let buffer = new ArrayBuffer(bufferLen);
- let view = new DataView(buffer);
- view.setUint8(0, 0x54); // 'T'
- view.setUint8(1, 0x45); // 'E'
- view.setUint8(2, 0x58); // 'X'
- view.setUint8(3, 0); // '\0'
- view.setUint32(4, byteLen, true);
- let ofs = 8;
- for(let i = 0; i < byteLen; i++) {
- let byte = data.charCodeAt(i);
- view.setUint8(ofs, byte);
- ofs++;
- }
- this.blocks.push({
- type : "TEX",
- id : i,
- flag : "PNG",
- buffer : buffer
- });
- break;
- case "IMG":
- break;
- }
- }
- },
- writeMaterials : function() {
- for(let i = 0; i < this.materials.length; i++) {
- let byteLen = 0;
- let properties = Object.keys(this.materials[i]);
- for(let key in this.materials[i]) {
- switch(key) {
- case "diffuse":
- byteLen += 16;
- break;
- case "map0":
- byteLen += 8;
- break;
- }
- }
- let bufferLen = this.calcBufferLen(byteLen);
- let buffer = new ArrayBuffer(bufferLen);
- let view = new DataView(buffer);
- view.setUint8(0, "M".charCodeAt(0));
- view.setUint8(1, "A".charCodeAt(0));
- view.setUint8(2, "T".charCodeAt(0));
- view.setUint8(3, 0);
- view.setUint32(4, byteLen, true);
- let ofs = 8;
- for(let key in this.materials[i]) {
- let val = this.materials[i][key];
- console.log(val);
- switch(key) {
- case "diffuse":
- view.setUint8(ofs + 0, "D".charCodeAt(0));
- view.setUint8(ofs + 1, "I".charCodeAt(0));
- view.setUint8(ofs + 2, "F".charCodeAt(0));
- view.setUint8(ofs + 3, "F".charCodeAt(0));
- view.setFloat32(ofs + 4, val.r);
- view.setFloat32(ofs + 8, val.r);
- view.setFloat32(ofs + 12, val.r);
- ofs += 16;
- break;
- case "map0":
- view.setUint8(ofs + 0, "M".charCodeAt(0));
- view.setUint8(ofs + 1, "A".charCodeAt(0));
- view.setUint8(ofs + 2, "P".charCodeAt(0));
- view.setUint8(ofs + 3, "0".charCodeAt(0));
- view.setUint32(ofs + 4, val);
- ofs += 8;
- break;
- }
- }
- this.blocks.push({
- type : "MAT",
- id : i,
- num : properties.length,
- buffer: buffer
- });
- console.log("okay");
- }
- },
- writeFaceGroups : function() {
- let structSize = 2;
- let flags = 0;
- if(this.groupflags.uv0) {
- structSize += 8;
- flags |= 1;
- }
- if(this.groupflags.uv1) {
- structSize += 8;
- flags |= 2;
- }
- if(this.groupflags.normal) {
- structSize += 12;
- flags |= 4;
- }
- if(this.groupflags.vcolor) {
- structSize += 12;
- flags |= 8;
- }
- for(let i = 0; i < this.groups.length; i++) {
- let group = this.groups[i];
- let byteLen = group.tri.length * structSize;
- let bufferLen = this.calcBufferLen(byteLen);
- let buffer = new ArrayBuffer(bufferLen);
- let view = new DataView(buffer);
- view.setUint8(0, 0x46); // 'F'
- view.setUint8(1, 0x41); // 'A'
- view.setUint8(2, 0x43); // 'C'
- view.setUint8(3, 0x45); // 'E'
- view.setUint32(4, byteLen, true);
- let ofs = 8;
- group.tri.forEach(tri => {
- view.setUint16(ofs, tri.index, true);
- ofs += 2;
- if(this.groupflags.uv0) {
- view.setFloat32(ofs + 0, tri.uv0.u, true);
- view.setFloat32(ofs + 4, tri.uv0.v, true);
- ofs += 8;
- }
- if(this.groupflags.uv1) {
- view.setFloat32(ofs + 0, tri.uv1.u, true);
- view.setFloat32(ofs + 4, tri.uv1.v, true);
- ofs += 8;
- }
- if(this.groupflags.normal) {
- view.setFloat32(ofs + 0, tri.normal.x, true);
- view.setFloat32(ofs + 4, tri.normal.y, true);
- view.setFloat32(ofs + 8, tri.normal.z, true);
- ofs += 12;
- }
- if(this.groupflags.vcolor) {
- tri.vcolor = tri.vcolor || { r : 1, g : 1, b : 1 };
- view.setFloat32(ofs + 0, tri.vcolor.r, true);
- view.setFloat32(ofs + 4, tri.vcolor.g, true);
- view.setFloat32(ofs + 8, tri.vcolor.b, true);
- ofs += 12;
- }
- });
- this.blocks.push({
- type : "FACE",
- id : i,
- mat_id : group.matIndex,
- flags: flags,
- num : group.tri.length,
- buffer : buffer
- });
- }
- },
- writeHeader : function() {
- let byteLen = (this.blocks.length+2) * 16;
- let buffer = new ArrayBuffer(byteLen);
- let view = new DataView(buffer);
- view.setUint8(0, 0x44); // 'D'
- view.setUint8(1, 0x41); // 'A'
- view.setUint8(2, 0x53); // 'S'
- view.setUint8(3, 0x48); // 'H'
- view.setUint32(4, 1, true);
- view.setUint32(8, 16, true);
- view.setUint32(12, this.blocks.length, true);
- let ofs = 16;
- let startOfs = byteLen;
- for(let i = 0; i < this.blocks.length; i++) {
- let block = this.blocks[i];
- switch(block.type) {
- case "BONE":
- view.setUint8(ofs + 0, 'B'.charCodeAt(0));
- view.setUint8(ofs + 1, 'O'.charCodeAt(0));
- view.setUint8(ofs + 2, 'N'.charCodeAt(0));
- view.setUint8(ofs + 3, 'E'.charCodeAt(0));
- view.setUint32(ofs + 4, startOfs, true);
- view.setUint32(ofs + 12, block.num, true);
- break;
- case "VERT":
- view.setUint8(ofs + 0, 'V'.charCodeAt(0));
- view.setUint8(ofs + 1, 'E'.charCodeAt(0));
- view.setUint8(ofs + 2, 'R'.charCodeAt(0));
- view.setUint8(ofs + 3, 'T'.charCodeAt(0));
- view.setUint32(ofs + 4, startOfs, true);
- if(block.flag) {
- view.setUint32(ofs + 8, 1, true);
- }
- view.setUint32(ofs + 12, block.num, true);
- break;
- case "TEX":
- view.setUint8(ofs + 0, 'T'.charCodeAt(0));
- view.setUint8(ofs + 1, 'E'.charCodeAt(0));
- view.setUint8(ofs + 2, 'X'.charCodeAt(0));
- view.setUint32(ofs + 4, startOfs, true);
- view.setUint32(ofs + 8, block.id, true);
- for(let k = 0; k < block.flag.length; k++) {
- view.setUint8(ofs + 12+k, block.flag.charCodeAt(k));
- }
- break;
- case "MAT":
- view.setUint8(ofs + 0, 'M'.charCodeAt(0));
- view.setUint8(ofs + 1, 'A'.charCodeAt(0));
- view.setUint8(ofs + 2, 'T'.charCodeAt(0));
- view.setUint32(ofs + 4, startOfs, true);
- view.setUint32(ofs + 8, block.id, true);
- view.setUint32(ofs + 12, block.num, true);
- break;
- case "FACE":
- view.setUint8(ofs + 0, 'F'.charCodeAt(0));
- view.setUint8(ofs + 1, 'A'.charCodeAt(0));
- view.setUint8(ofs + 2, 'C'.charCodeAt(0));
- view.setUint8(ofs + 3, 'E'.charCodeAt(0));
- view.setUint32(ofs + 4, startOfs, true);
- view.setUint16(ofs + 8, block.mat_id, true);
- view.setUint16(ofs + 10, block.flags, true);
- view.setUint32(ofs + 12, block.num, true);
- break;
- case "ANIM":
- break;
- }
- ofs += 16;
- startOfs += block.buffer.byteLength;
- }
- this.blocks.unshift({
- type : "HEAD",
- buffer : buffer
- });
- },
- writeBlob : function() {
- let array = new Array(this.blocks.length);
- for(let i = 0; i < this.blocks.length; i++) {
- array[i] = this.blocks[i].buffer;
- }
- return = new Blob(array);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement