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.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.getFaceGroups(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) {
- // 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.bones.length) {
- 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;
- }
- let canvas, ctx;
- let tex = material[i].map;
- switch (tex.image.tagName) {
- case "IMG":
- canvas = document.createElement("canvas");
- canvas.width = tex.image.offsetWidth;
- canvas.height = tex.image.offsetHeight;
- ctx = canvas.getContext("2d");
- ctx.drawImage(tex.image, 0, 0);
- break;
- case "CANVAS":
- canvas = tex.image;
- break;
- }
- this.textures.push({
- uuid: uuid,
- img: canvas,
- flipY: tex.flipY,
- width: canvas.width,
- height: canvas.height,
- wrapS: tex.wrapS,
- wrapT: tex.wrapT
- });
- }
- },
- 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 = {};
- if (material[i].color) {
- 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);
- }
- },
- getFaceGroups: 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.uv1) {
- a.uv0 = {
- u: geometry.faceVertexUvs[1][i][0].x,
- v: geometry.faceVertexUvs[1][i][0].y
- }
- b.uv0 = {
- u: geometry.faceVertexUvs[1][i][1].x,
- v: geometry.faceVertexUvs[1][i][1].y
- }
- c.uv0 = {
- u: geometry.faceVertexUvs[1][i][2].x,
- v: geometry.faceVertexUvs[1][i][2].y
- }
- }
- if (this.groupflags.normal) {
- a.normal = {
- x: face.vertexNormals[0].x,
- y: face.vertexNormals[0].y,
- z: face.vertexNormals[0].z
- }
- b.normal = {
- x: face.vertexNormals[1].x,
- y: face.vertexNormals[1].y,
- z: face.vertexNormals[1].z
- }
- c.normal = {
- x: face.vertexNormals[2].x,
- y: face.vertexNormals[2].y,
- z: face.vertexNormals[2].z
- }
- }
- 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.bones.length) {
- 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].pos.x, true);
- view.setFloat32(ofs + 4, this.vertices[i].pos.y, true);
- view.setFloat32(ofs + 8, this.vertices[i].pos.z, true);
- ofs += 12;
- if (!this.bones.length) {
- 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
- });
- },
- writeTextures: function() {
- for (let i = 0; i < this.textures.length; i++) {
- let tex = this.textures[i];
- 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 structSize = byteLen + 4;
- tex.type = "PNG";
- tex.len = byteLen;
- let props = 1;
- let prop = {};
- for (let key in tex) {
- switch (key) {
- case "type":
- case "len":
- case "flipY":
- case "width":
- case "height":
- case "wrapS":
- case "wrapT":
- prop[key] = true;
- props++;
- structSize += 8;
- break;
- }
- }
- let bufferLen = this.calcBufferLen(structSize);
- 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, structSize, true);
- let ofs = 8;
- if (prop.type) {
- view.setUint8(ofs + 0, 'T'.charCodeAt(0));
- view.setUint8(ofs + 1, 'Y'.charCodeAt(0));
- view.setUint8(ofs + 2, 'P'.charCodeAt(0));
- view.setUint8(ofs + 3, 'E'.charCodeAt(0));
- ofs += 4;
- for (let k = 0; k < tex.type.length; k++) {
- view.setUint8(ofs + k, tex.type.charCodeAt(k));
- }
- ofs += 4;
- }
- if (prop.len) {
- view.setUint8(ofs + 0, 'L'.charCodeAt(0));
- view.setUint8(ofs + 1, 'E'.charCodeAt(0));
- view.setUint8(ofs + 2, 'N'.charCodeAt(0));
- view.setUint8(ofs + 3, '\0'.charCodeAt(0));
- view.setUint32(ofs + 4, byteLen, true);
- ofs += 8;
- }
- if (prop.flipY) {
- let flipY = tex.flipY ? 1 : 0;
- view.setUint8(ofs + 0, 'F'.charCodeAt(0));
- view.setUint8(ofs + 1, 'L'.charCodeAt(0));
- view.setUint8(ofs + 2, 'P'.charCodeAt(0));
- view.setUint8(ofs + 3, 'Y'.charCodeAt(0));
- view.setUint32(ofs + 4, flipY, true);
- ofs += 8;
- }
- if (prop.width) {
- view.setUint8(ofs + 0, 'W'.charCodeAt(0));
- view.setUint8(ofs + 1, 'I'.charCodeAt(0));
- view.setUint8(ofs + 2, 'D'.charCodeAt(0));
- view.setUint8(ofs + 3, '\0'.charCodeAt(0));
- view.setUint32(ofs + 4, tex.width, true);
- ofs += 8;
- }
- if (prop.width) {
- view.setUint8(ofs + 0, 'H'.charCodeAt(0));
- view.setUint8(ofs + 1, 'G'.charCodeAt(0));
- view.setUint8(ofs + 2, 'T'.charCodeAt(0));
- view.setUint8(ofs + 3, '\0'.charCodeAt(0));
- view.setUint32(ofs + 4, tex.width, true);
- ofs += 8;
- }
- if (prop.wrapS) {
- view.setUint8(ofs + 0, 'W'.charCodeAt(0));
- view.setUint8(ofs + 1, 'R'.charCodeAt(0));
- view.setUint8(ofs + 2, 'P'.charCodeAt(0));
- view.setUint8(ofs + 3, 'S'.charCodeAt(0));
- view.setUint32(ofs + 4, tex.wrapS, true);
- ofs += 8;
- }
- if (prop.wrapT) {
- view.setUint8(ofs + 0, 'W'.charCodeAt(0));
- view.setUint8(ofs + 1, 'R'.charCodeAt(0));
- view.setUint8(ofs + 2, 'P'.charCodeAt(0));
- view.setUint8(ofs + 3, 'T'.charCodeAt(0));
- view.setUint32(ofs + 4, tex.wrapT, true);
- ofs += 8;
- }
- view.setUint8(ofs + 0, 'I'.charCodeAt(0));
- view.setUint8(ofs + 1, 'M'.charCodeAt(0));
- view.setUint8(ofs + 2, 'G'.charCodeAt(0));
- view.setUint8(ofs + 3, '\0'.charCodeAt(0));
- ofs += 4;
- for (let i = 0; i < byteLen; i++) {
- view.setUint8(ofs, data.charCodeAt(i));
- ofs++;
- }
- this.blocks.push({
- type: "TEX",
- id: i,
- num: props,
- buffer: buffer
- });
- }
- },
- 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;
- }
- if (this.groupflags.uv1) {
- structSize += 8;
- }
- if (this.groupflags.normal) {
- structSize += 12;
- }
- if (this.groupflags.vcolor) {
- structSize += 12;
- }
- 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",
- mat_id: group.matIndex,
- num: group.tri.length,
- buffer: buffer
- });
- }
- },
- writeHeader: function() {
- let flags = 0;
- if (this.groupflags.uv0) {
- flags |= 1;
- }
- if (this.groupflags.uv1) {
- flags |= 2;
- }
- if (this.groupflags.normal) {
- flags |= 4;
- }
- if (this.groupflags.vcolor) {
- flags |= 8;
- }
- let byteLen = (this.blocks.length + 3) * 16;
- let gen_text = "Generated by THREE.DashExporter";
- let bufferLen = this.calcBufferLen(byteLen + gen_text.length);
- let buffer = new ArrayBuffer(bufferLen);
- let view = new DataView(buffer);
- view.setUint8(0, 'D'.charCodeAt(0));
- view.setUint8(1, 'M'.charCodeAt(0));
- view.setUint8(2, 'F'.charCodeAt(0));
- view.setUint8(3, '\0'.charCodeAt(0));
- view.setUint32(4, 1, true);
- view.setUint32(8, flags, true);
- view.setUint32(12, this.blocks.length, true);
- let ofs = 32;
- let startOfs = bufferLen;
- console.log("Header length: 0x%s", bufferLen.toString(16));
- 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);
- view.setUint32(ofs + 12, block.num, true);
- break;
- case "TEX":
- console.log(block);
- 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);
- view.setUint32(ofs + 12, block.num, true);
- 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;
- }
- ofs += 16;
- for (let i = 0; i < gen_text.length; i++) {
- view.setUint8(ofs + i, gen_text.charCodeAt(i));
- }
- 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