Huffman.prototype.decompress = function(cdata) { var data = new _utils.DynamicBuffer(); var readCount = cdata.readUInt32LE(3); var pos = 7; var load = loadPrefixMap(cdata, pos); pos = load[1]; var tree = load[0]; var bits = new _bb.BitStream(cdata, pos); bits._view._view = bits._view._view.slice(pos); var pb = new _utils.ProgressBar(readCount / 1000, 20, "Huffman-Algorithm: Decompressing"); pb.run(function(updater) { var bit, byte; var cstream = []; for (var i = 0; i < readCount; i++) { bit = bits.readBits(1, false); cstream.push(bit); byte = findInTree(tree, cstream); if (byte !== null) { data.uwrite(byte); cstream = []; } if (i % 1000 === 0) { updater(); } } }); var resultBuffer = data.getBuffer(); console.log("Decompression finished: decompressed from " + cdata.length + " bytes to " + resultBuffer.length + " bytes"); return resultBuffer; };
pb.run(function(updater) { var bit, byte; var cstream = []; for (var i = 0; i < readCount; i++) { bit = bits.readBits(1, false); cstream.push(bit); byte = findInTree(tree, cstream); if (byte !== null) { data.uwrite(byte); cstream = []; } if (i % 1000 === 0) { updater(); } } });
function load(data) { var md3 = new Md3(); var bb = new BitStream(data); // Load the md3's header. var header = new Md3Header(); header.ident = bb.readInt32(); header.version = bb.readInt32(); if (header.version !== MD3_VERSION) { throw new Error('LoadMd3: Wrong version (' + header.version + ' should be ' + MD3_VERSION + ')'); } header.name = bb.readASCIIString(MAX_QPATH); header.flags = bb.readInt32(); header.numFrames = bb.readInt32(); header.numTags = bb.readInt32(); header.numSurfaces = bb.readInt32(); header.numSkins = bb.readInt32(); header.ofsFrames = bb.readInt32(); header.ofsTags = bb.readInt32(); header.ofsSurfaces = bb.readInt32(); header.ofsEnd = bb.readInt32(); // Validate the header. if (header.numFrames < 1) { throw new Error('LoadMd3: 0 frames'); } md3.name = header.name; md3.frames = new Array(header.numFrames); md3.tags = new Array(header.numFrames * header.numTags); md3.surfaces = new Array(header.numSurfaces); md3.skins = new Array(header.numSkins); // Read all of the frames. bb.byteIndex = header.ofsFrames; for (var i = 0; i < header.numFrames; i++) { var frame = md3.frames[i] = new Md3Frame(); for (var j = 0; j < 6; j++) { frame.bounds[Math.floor(j/3)][j % 3] = bb.readFloat32(); } for (var j = 0; j < 3; j++) { frame.localOrigin[j] = bb.readFloat32(); } frame.radius = bb.readFloat32(); frame.name = bb.readASCIIString(16); } // Read all of the tags. bb.byteIndex = header.ofsTags; for (var i = 0; i < header.numFrames * header.numTags; i++) { var tag = md3.tags[i] = new Md3Tag(); tag.name = bb.readASCIIString(MAX_QPATH); for (var j = 0; j < 3; j++) { tag.origin[j] = bb.readFloat32(); } for (var j = 0; j < 9; j++) { tag.axis[Math.floor(j/3)][j % 3] = bb.readFloat32(); } } // Read all of the meshes. var meshOffset = header.ofsSurfaces; for (var i = 0; i < header.numSurfaces; i++) { bb.byteIndex = meshOffset; // Load this surface's header. var surfheader = new Md3SurfaceHeader(); surfheader.ident = bb.readInt32(); surfheader.name = bb.readASCIIString(MAX_QPATH); surfheader.flags = bb.readInt32(); surfheader.numFrames = bb.readInt32(); surfheader.numShaders = bb.readInt32(); surfheader.numVerts = bb.readInt32(); surfheader.numTriangles = bb.readInt32(); surfheader.ofsTriangles = bb.readInt32(); surfheader.ofsShaders = bb.readInt32(); surfheader.ofsSt = bb.readInt32(); surfheader.ofsXyzNormals = bb.readInt32(); surfheader.ofsEnd = bb.readInt32(); // Calidate the surface's header. if (surfheader.numVerts > SHADER_MAX_VERTEXES) { throw new Error('LoadMd3: More than ' + SHADER_MAX_VERTEXES + ' verts on a surface (' + surfheader.numVerts + ')'); } if (surfheader.numTriangles * 3 > SHADER_MAX_INDEXES) { throw new Error('LoadMd3: More than ' + (SHADER_MAX_INDEXES / 3) + ' triangles on a surface (' + surfheader.numTriangles + ')'); } // var surf = md3.surfaces[i] = new Md3Surface(); // Strip off a trailing _1 or _2 // this is a crutch for q3data being a mess. surf.name = surfheader.name.toLowerCase().replace(/_\d+/, ''); surf.numFrames = surfheader.numFrames; surf.numVerts = surfheader.numVerts; surf.shaders = new Array(surfheader.numShaders); surf.indexes = new Array(surfheader.numTriangles * 3); surf.st = new Array(surfheader.numVerts); surf.xyz = new Array(surfheader.numFrames * surfheader.numVerts); surf.normals = new Array(surfheader.numFrames * surfheader.numVerts); // Register all the shaders. bb.byteIndex = meshOffset + surfheader.ofsShaders; for (var j = 0; j < surfheader.numShaders; j++) { // Strip extension. var name = bb.readASCIIString(MAX_QPATH).replace(/\.[^\/.]+$/, ''); surf.shaders[j] = name; } // Read all of the triangles. bb.byteIndex = meshOffset + surfheader.ofsTriangles; for (var j = 0; j < surfheader.numTriangles; j++) { for (var k = 0; k < 3; k++) { surf.indexes[j * 3 + k] = bb.readInt32(); } } // Read all of the ST coordinates. bb.byteIndex = meshOffset + surfheader.ofsSt; for (var j = 0; j < surfheader.numVerts; j++) { var st = surf.st[j] = [0, 0]; st[0] = bb.readFloat32(); st[1] = bb.readFloat32(); } // Read all of the xyz normals. bb.byteIndex = meshOffset + surfheader.ofsXyzNormals; for (var j = 0; j < surfheader.numFrames * surfheader.numVerts; j++) { var xyz = surf.xyz[j] = [0, 0, 0]; var normal = surf.normals[j] = [0, 0, 0]; for (var k = 0; k < 3; k++) { xyz[k] = bb.readInt16() * MD3_XYZ_SCALE; } // Convert from spherical coordinates to normalized vec3. var zenith = bb.readInt8(); var azimuth = bb.readInt8(); var lat = zenith * (2 * Math.PI) / 255; var lng = azimuth * (2 * Math.PI) / 255; normal[0] = Math.cos(lng) * Math.sin(lat); normal[1] = Math.sin(lng) * Math.sin(lat); normal[2] = Math.cos(lat); // normalize var len = normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2]; if (len > 0) { len = 1 / Math.sqrt(len); normal[0] = normal[0] * len; normal[1] = normal[1] * len; normal[2] = normal[2] * len; } } meshOffset += surfheader.ofsEnd; } return md3; }