mdx-m3-viewer
Version:
A browser WebGL model viewer. Mainly focused on models of the games Warcraft 3 and Starcraft 2.
198 lines (168 loc) • 4.48 kB
JavaScript
import AnimatedObject from './animatedobject';
let filterModeToMdx = {
None: 0,
Transparent: 1,
Blend: 2,
Additive: 3,
AddAlpha: 4,
Modulate: 5,
Modulate2x: 6,
};
let filterModeToMdl = {
0: 'None',
1: 'Transparent',
2: 'Blend',
3: 'Additive',
4: 'AddAlpha',
5: 'Modulate',
6: 'Modulate2x',
};
/**
* A layer.
*/
export default class Layer extends AnimatedObject {
/**
*
*/
constructor() {
super();
/** @member {number} */
this.filterMode = 0;
/** @member {number} */
this.flags = 0;
/** @member {number} */
this.textureId = -1;
/** @member {number} */
this.textureAnimationId = -1;
/** @member {number} */
this.coordId = 0;
/** @member {number} */
this.alpha = 1;
/**
* @since 900
* @member {number}
*/
this.emissive = 0;
}
/**
* @param {BinaryStream} stream
* @param {number} version
*/
readMdx(stream, version) {
let size = stream.readUint32();
this.filterMode = stream.readUint32();
this.flags = stream.readUint32();
this.textureId = stream.readInt32();
this.textureAnimationId = stream.readInt32();
this.coordId = stream.readUint32();
this.alpha = stream.readFloat32();
if (version === 900) {
this.emissive = stream.readFloat32();
// Instead of -32 below.
size -= 4;
}
this.readAnimations(stream, size - 28);
}
/**
* @param {BinaryStream} stream
* @param {number} version
*/
writeMdx(stream, version) {
stream.writeUint32(this.getByteLength());
stream.writeUint32(this.filterMode);
stream.writeUint32(this.flags);
stream.writeInt32(this.textureId);
stream.writeInt32(this.textureAnimationId);
stream.writeUint32(this.coordId);
stream.writeFloat32(this.alpha);
if (version === 900) {
stream.writeFloat32(this.emissive);
}
this.writeAnimations(stream);
}
/**
* @param {TokenStream} stream
*/
readMdl(stream) {
for (let token of this.readAnimatedBlock(stream)) {
if (token === 'FilterMode') {
this.filterMode = filterModeToMdx[stream.read()];
} else if (token === 'Unshaded') {
this.flags |= 0x1;
} else if (token === 'SphereEnvMap') {
this.flags |= 0x2;
} else if (token === 'TwoSided') {
this.flags |= 0x10;
} else if (token === 'Unfogged') {
this.flags |= 0x20;
} else if (token === 'NoDepthTest') {
this.flags |= 0x40;
} else if (token === 'NoDepthSet') {
this.flags |= 0x100;
} else if (token === 'static TextureID') {
this.textureId = stream.readInt();
} else if (token === 'TextureID') {
this.readAnimation(stream, 'KMTF');
} else if (token === 'TVertexAnimId') {
this.textureAnimationId = stream.readInt();
} else if (token === 'CoordId') {
this.coordId = stream.readInt();
} else if (token === 'static Alpha') {
this.alpha = stream.readFloat();
} else if (token === 'Alpha') {
this.readAnimation(stream, 'KMTA');
} else {
throw new Error(`Unknown token in Layer: "${token}"`);
}
}
}
/**
* @param {TokenStream} stream
*/
writeMdl(stream) {
stream.startBlock('Layer');
stream.writeAttrib('FilterMode', filterModeToMdl[this.filterMode]);
if (this.flags & 0x1) {
stream.writeFlag('Unshaded');
}
if (this.flags & 0x2) {
stream.writeFlag('SphereEnvMap');
}
if (this.flags & 0x10) {
stream.writeFlag('TwoSided');
}
if (this.flags & 0x20) {
stream.writeFlag('Unfogged');
}
if (this.flags & 0x40) {
stream.writeFlag('NoDepthTest');
}
if (this.flags & 0x100) {
stream.writeFlag('NoDepthSet');
}
if (!this.writeAnimation(stream, 'KMTF')) {
stream.writeAttrib('static TextureID', this.textureId);
}
if (this.textureAnimationId !== -1) {
stream.writeAttrib('TVertexAnimId', this.textureAnimationId);
}
if (this.coordId !== 0) {
stream.writeAttrib('CoordId', this.coordId);
}
if (!this.writeAnimation(stream, 'KMTA') && this.alpha !== 1) {
stream.writeFloatAttrib('static Alpha', this.alpha);
}
stream.endBlock();
}
/**
* @param {number} version
* @return {number}
*/
getByteLength(version) {
let size = 28 + super.getByteLength();
if (version === 900) {
size += 4;
}
return size;
}
}