UNPKG

mdx-m3-viewer

Version:

A browser WebGL model viewer. Mainly focused on models of the games Warcraft 3 and Starcraft 2.

249 lines (238 loc) 9.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const model_1 = require("../../../parsers/m3/model"); const model_2 = require("../../model"); const standardmaterial_1 = require("./standardmaterial"); const bone_1 = require("./bone"); const sequence_1 = require("./sequence"); const sts_1 = require("./sts"); const stc_1 = require("./stc"); const stg_1 = require("./stg"); const attachment_1 = require("./attachment"); const camera_1 = require("./camera"); const region_1 = require("./region"); const modelinstance_1 = require("./modelinstance"); const batch_1 = require("./batch"); /** * An M3 model. */ class M3Model extends model_2.default { constructor(bufferOrParser, resourceData) { super(resourceData); this.name = ''; this.batches = []; this.materials = [[], []]; // 2D array for the possibility of adding more material types in the future this.materialMaps = []; this.bones = []; this.sequences = []; this.sts = []; this.stc = []; this.stg = []; this.attachments = []; this.cameras = []; this.regions = []; this.initialReference = []; this.elementBuffer = null; this.arrayBuffer = null; this.vertexSize = 0; this.uvSetCount = 0; let parser; if (bufferOrParser instanceof model_1.default) { parser = bufferOrParser; } else { parser = new model_1.default(); parser.load(bufferOrParser); } const model = parser.model; const div = model.divisions.first(); this.name = model.modelName.get(); this.setupGeometry(model, div); const materialMaps = model.materialReferences.get(); this.materialMaps = materialMaps; // Create concrete material objects for standard materials const standardMaterials = model.materials[0].get(); for (let i = 0, l = standardMaterials.length; i < l; i++) { this.materials[1].push(new standardmaterial_1.M3StandardMaterial(this, i, standardMaterials[i])); } // Create concrete batch objects for (const batch of div.batches.get()) { const regionId = batch.regionIndex; const materialMap = materialMaps[batch.materialReferenceIndex]; if (materialMap.materialType === 1) { this.batches.push(new batch_1.default(this.regions[regionId], this.materials[1][materialMap.materialIndex])); } } /* var batchGroups = [[], [], [], [], [], []]; for (i = 0, l = batches.length; i < l; i++) { var blendMode = batches[i].material.blendMode; batchGroups[blendMode].push(batches[i]); } function sortByPriority(a, b) { var a = a.material.priority; var b = b.material.priority; if (a < b) { return 1; } else if (a == b) { return 0; } else { return -1; } } for (i = 0; i < 6; i++) { batchGroups[i].sort(sortByPriority); } */ /* // In the EggPortrait model the batches seem to be sorted by blend mode. Is this true for every model? this.batches.sort(function (a, b) { var ba = a.material.blendMode; var bb = b.material.blendMode; if (ba < bb) { return -1; } else if (ba == bb) { return 0; } else { return 1; } }); */ // this.batches = batchGroups[0].concat(batchGroups[1]).concat(batchGroups[2]).concat(batchGroups[3]).concat(batchGroups[4]).concat(batchGroups[5]); this.initialReference = model.absoluteInverseBoneRestPositions.get(); for (const bone of model.bones.get()) { this.bones.push(new bone_1.default(bone)); } this.boneLookup = model.boneLookup.get(); const sequences = model.sequences.get(); if (sequences) { for (const sequence of sequences) { this.sequences.push(new sequence_1.default(sequence)); } } const stss = model.sts.get(); if (stss) { for (const sts of stss) { this.sts.push(new sts_1.default(sts)); } } const stcs = model.stc.get(); if (stcs) { for (const stc of stcs) { this.stc.push(new stc_1.default(stc)); } } const stgs = model.stg.get(); if (stgs) { for (const stg of stgs) { this.stg.push(new stg_1.default(stg, this.sts, this.stc)); } } this.addGlobalAnims(); /* if (parser.fuzzyHitTestObjects.length > 0) { for (i = 0, l = parser.fuzzyHitTestObjects.length; i < l; i++) { this.boundingShapes[i] = new M3BoundingShape(parser.fuzzyHitTestObjects[i], parser.bones, gl); } } */ /* if (parser.particleEmitters.length > 0) { this.particleEmitters = []; for (i = 0, l = parser.particleEmitters.length; i < l; i++) { this.particleEmitters[i] = new M3ParticleEmitter(parser.particleEmitters[i], this); } } */ const attachmentPoints = model.attachmentPoints.get(); if (attachmentPoints) { for (const attachment of attachmentPoints) { this.attachments.push(new attachment_1.default(attachment)); } } const cameras = model.cameras.get(); if (cameras) { for (const camera of cameras) { this.cameras.push(new camera_1.default(camera)); } } } addInstance() { return new modelinstance_1.default(this); } setupGeometry(parser, div) { const gl = this.viewer.gl; let uvSetCount = 1; const vertexFlags = parser.vertexFlags; if (vertexFlags & 0x40000) { uvSetCount = 2; } else if (vertexFlags & 0x80000) { uvSetCount = 3; } else if (vertexFlags & 0x100000) { uvSetCount = 4; } const regions = div.regions.get(); let totalElements = 0; const offsets = []; for (let i = 0, l = regions.length; i < l; i++) { offsets[i] = totalElements; totalElements += regions[i].triangleIndicesCount; } const elementArray = new Uint16Array(totalElements); const triangles = div.triangles.get(); for (let i = 0, l = regions.length; i < l; i++) { this.regions.push(new region_1.default(this, regions[i], triangles, elementArray, offsets[i])); } const vertices = parser.vertices.get(); this.elementBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.elementBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, elementArray, gl.STATIC_DRAW); const arrayBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, arrayBuffer); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); this.arrayBuffer = arrayBuffer; this.vertexSize = (7 + uvSetCount) * 4; this.uvSetCount = uvSetCount; } mapMaterial(index) { const materialMap = this.materialMaps[index]; // return this.materials[materialMap.materialType][materialMap.materialIndex]; return this.materials[1][materialMap.materialIndex]; } addGlobalAnims() { /* var i, l; var glbirth, glstand, gldeath; var stgs = this.stg; var stg, name; for (i = 0, l = stgs.length; i < l; i++) { stg = stgs[i]; name = stg.name.toLowerCase(); // Because obviously there will be a wrong case in some model... if (name === 'glbirth') { glbirth = stg; } else if (name === 'glstand') { glstand = stg; } else if (name === 'gldeath') { gldeath = stg; } } for (i = 0, l = stgs.length; i < l; i++) { stg = stgs[i]; name = stg.name.toLowerCase(); // Because obviously there will be a wrong case in some model... if (name !== 'glbirth' && name !== 'glstand' && name !== 'gldeath') { if (name.indexOf('birth') !== -1 && glbirth) { stg.stcIndices = stg.stcIndices.concat(glbirth.stcIndices); } else if (name.indexOf('death') !== -1 && gldeath) { stg.stcIndices = stg.stcIndices.concat(gldeath.stcIndices); } else if (glstand) { stg.stcIndices = stg.stcIndices.concat(glstand.stcIndices); } } } */ } } exports.default = M3Model; //# sourceMappingURL=model.js.map