mdx-m3-viewer
Version:
A browser WebGL model viewer. Mainly focused on models of the games Warcraft 3 and Starcraft 2.
121 lines (99 loc) • 4.65 kB
text/typescript
import Attachment from '../../parsers/mdlx/attachment';
import Bone from '../../parsers/mdlx/bone';
import Camera from '../../parsers/mdlx/camera';
import CollisionShape from '../../parsers/mdlx/collisionshape';
import FaceEffect from '../../parsers/mdlx/faceeffect';
import Geoset from '../../parsers/mdlx/geoset';
import GeosetAnimation from '../../parsers/mdlx/geosetanimation';
import Helper from '../../parsers/mdlx/helper';
import Layer from '../../parsers/mdlx/layer';
import Light from '../../parsers/mdlx/light';
import Model from '../../parsers/mdlx/model';
import ParticleEmitter from '../../parsers/mdlx/particleemitter';
import ParticleEmitter2 from '../../parsers/mdlx/particleemitter2';
import ParticleEmitterPopcorn from '../../parsers/mdlx/particleemitterpopcorn';
import RibbonEmitter from '../../parsers/mdlx/ribbonemitter';
import Sequence from '../../parsers/mdlx/sequence';
import Texture from '../../parsers/mdlx/texture';
import TextureAnimation from '../../parsers/mdlx/textureanimation';
import TokenStream from '../../parsers/mdlx/tokenstream';
import { getObjectName, getObjectTypeName } from './sanitytest/utils';
interface MdlStructureNode {
name: string;
source: string;
nodes?: MdlStructureNode[];
}
function mdlObjects(stream: TokenStream, model: Model, objects: (Sequence | Layer | Texture | TextureAnimation | Geoset | GeosetAnimation | Bone | Light | Helper | Attachment | ParticleEmitter | ParticleEmitter2 | ParticleEmitterPopcorn | RibbonEmitter | Camera | CollisionShape | FaceEffect)[], out: MdlStructureNode[]) {
if (objects.length) {
for (let [index, object] of objects.entries()) {
object.writeMdl(stream, model.version);
out.push({ name: getObjectName(object, index), source: stream.buffer });
stream.clear();
}
}
}
function mdlObjectsBlock(stream: TokenStream, model: Model, objects: (Sequence | Texture | TextureAnimation)[], out: MdlStructureNode[]) {
if (objects.length) {
let name = getObjectTypeName(objects[0]) + 's';
let nodes = <MdlStructureNode[]>[];
mdlObjects(stream, model, objects, nodes);
model.saveStaticObjectsBlock(stream, name, objects);
out.push({ name, source: stream.buffer, nodes });
stream.clear();
}
}
export default function mdlStructure(model: Model) {
let stream = new TokenStream();
let out = <MdlStructureNode[]>[];
model.saveVersionBlock(stream);
out.push({ name: 'Version', source: stream.buffer });
stream.clear();
model.saveModelBlock(stream);
out.push({ name: 'Model', source: stream.buffer });
stream.clear();
mdlObjectsBlock(stream, model, model.sequences, out);
if (model.globalSequences.length) {
model.saveGlobalSequenceBlock(stream);
out.push({ name: 'GlobalSequences', source: stream.buffer });
stream.clear();
}
mdlObjectsBlock(stream, model, model.textures, out);
if (model.materials.length) {
let nodes = [];
for (let [index, material] of model.materials.entries()) {
let layerNodes = <MdlStructureNode[]>[];
mdlObjects(stream, model, material.layers, layerNodes);
material.writeMdl(stream, model.version);
nodes.push({ name: `Material ${index + 1}`, source: stream.buffer, nodes: layerNodes });
stream.clear();
}
model.saveStaticObjectsBlock(stream, 'Materials', model.materials);
out.push({ name: 'Materials', source: stream.buffer, nodes });
stream.clear();
}
mdlObjectsBlock(stream, model, model.textureAnimations, out);
mdlObjects(stream, model, model.geosets, out);
mdlObjects(stream, model, model.geosetAnimations, out);
mdlObjects(stream, model, model.bones, out);
mdlObjects(stream, model, model.lights, out);
mdlObjects(stream, model, model.helpers, out);
mdlObjects(stream, model, model.attachments, out);
if (model.pivotPoints.length) {
model.savePivotPointBlock(stream);
out.push({ name: 'PivotPoints', source: stream.buffer });
stream.clear();
}
mdlObjects(stream, model, model.particleEmitters, out);
mdlObjects(stream, model, model.particleEmitters2, out);
mdlObjects(stream, model, model.particleEmittersPopcorn, out);
mdlObjects(stream, model, model.ribbonEmitters, out);
mdlObjects(stream, model, model.cameras, out);
mdlObjects(stream, model, model.collisionShapes, out);
mdlObjects(stream, model, model.faceEffects, out);
if (model.bindPose.length) {
model.saveBindPoseBlock(stream);
out.push({ name: 'BindPose', source: stream.buffer });
stream.clear();
}
return { nodes: out };
}