UNPKG

mdx-m3-viewer

Version:

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

261 lines (208 loc) 6.96 kB
import BinaryStream from '../../common/binarystream'; import TokenStream from './tokenstream'; /** * An animation. */ export abstract class Animation { name: string = ''; interpolationType: number = 0; globalSequenceId: number = -1; frames: number[] = []; values: (Uint32Array | Float32Array)[] = []; inTans: (Uint32Array | Float32Array)[] = []; outTans: (Uint32Array | Float32Array)[] = []; abstract readMdxValue(stream: BinaryStream): Uint32Array | Float32Array; abstract writeMdxValue(stream: BinaryStream, value: Uint32Array | Float32Array): void; abstract readMdlValue(stream: TokenStream): Uint32Array | Float32Array; abstract writeMdlValue(stream: TokenStream, name: string, value: Uint32Array | Float32Array): void; readMdx(stream: BinaryStream, name: string) { let frames = this.frames; let values = this.values; let inTans = this.inTans; let outTans = this.outTans; let tracksCount = stream.readUint32(); let interpolationType = stream.readUint32(); this.name = name; this.interpolationType = interpolationType; this.globalSequenceId = stream.readInt32(); for (let i = 0; i < tracksCount; i++) { frames.push(stream.readInt32()); values.push(this.readMdxValue(stream)); if (interpolationType > 1) { inTans.push(this.readMdxValue(stream)); outTans.push(this.readMdxValue(stream)); } } } writeMdx(stream: BinaryStream) { let interpolationType = this.interpolationType; let frames = this.frames; let values = this.values; let inTans = this.inTans; let outTans = this.outTans; let tracksCount = frames.length; stream.write(this.name); stream.writeUint32(tracksCount); stream.writeUint32(interpolationType); stream.writeInt32(this.globalSequenceId); for (let i = 0; i < tracksCount; i++) { stream.writeInt32(frames[i]); this.writeMdxValue(stream, values[i]); if (interpolationType > 1) { this.writeMdxValue(stream, inTans[i]); this.writeMdxValue(stream, outTans[i]); } } } readMdl(stream: TokenStream, name: string) { let frames = this.frames; let values = this.values; let inTans = this.inTans; let outTans = this.outTans; this.name = name; let tracksCount = stream.readInt(); stream.read(); // { let interpolationType = 0; let token = stream.read(); if (token === 'DontInterp') { interpolationType = 0; } else if (token === 'Linear') { interpolationType = 1; } else if (token === 'Hermite') { interpolationType = 2; } else if (token === 'Bezier') { interpolationType = 3; } this.interpolationType = interpolationType; // GlobalSeqId only exists if it's not -1. if (stream.peek() === 'GlobalSeqId') { stream.read(); this.globalSequenceId = stream.readInt(); } for (let i = 0; i < tracksCount; i++) { frames[i] = stream.readInt(); values[i] = this.readMdlValue(stream); if (interpolationType > 1) { stream.read(); // InTan inTans[i] = this.readMdlValue(stream); stream.read(); // OutTan outTans[i] = this.readMdlValue(stream); } } stream.read(); // } } writeMdl(stream: TokenStream, name: string) { let interpolationType = this.interpolationType; let frames = this.frames; let values = this.values; let inTans = this.inTans; let outTans = this.outTans; let tracksCount = frames.length; stream.startBlock(name, this.frames.length); let token = ''; if (this.interpolationType === 0) { token = 'DontInterp'; } else if (this.interpolationType === 1) { token = 'Linear'; } else if (this.interpolationType === 2) { token = 'Hermite'; } else if (this.interpolationType === 3) { token = 'Bezier'; } stream.writeFlag(token); if (this.globalSequenceId !== -1) { stream.writeNumberAttrib('GlobalSeqId', this.globalSequenceId); } for (let i = 0; i < tracksCount; i++) { this.writeMdlValue(stream, `${frames[i]}:`, values[i]); if (interpolationType > 1) { stream.indent(); this.writeMdlValue(stream, 'InTan', inTans[i]); this.writeMdlValue(stream, 'OutTan', outTans[i]); stream.unindent(); } } stream.endBlock(); } getByteLength() { let tracksCount = this.frames.length; let size = 16; if (tracksCount) { let bytesPerValue = this.values[0].byteLength; let valuesPerTrack = 1; if (this.interpolationType > 1) { valuesPerTrack = 3; } size += (4 + valuesPerTrack * bytesPerValue) * tracksCount; } return size; } } /** * A uint animation. */ export class UintAnimation extends Animation { readMdxValue(stream: BinaryStream) { return stream.readUint32Array(1); } writeMdxValue(stream: BinaryStream, value: Uint32Array) { stream.writeUint32(value[0]); } readMdlValue(stream: TokenStream) { return new Uint32Array([stream.readInt()]); } writeMdlValue(stream: TokenStream, name: string, value: Uint32Array) { stream.writeNumberAttrib(name, value[0]); } } /** * A float animation */ export class FloatAnimation extends Animation { readMdxValue(stream: BinaryStream) { return stream.readFloat32Array(1); } writeMdxValue(stream: BinaryStream, value: Float32Array) { stream.writeFloat32(value[0]); } readMdlValue(stream: TokenStream) { return new Float32Array([stream.readFloat()]); } writeMdlValue(stream: TokenStream, name: string, value: Float32Array) { stream.writeNumberAttrib(name, value[0]); } } /** * A vector 3 animation. */ export class Vector3Animation extends Animation { readMdxValue(stream: BinaryStream) { return stream.readFloat32Array(3); } writeMdxValue(stream: BinaryStream, value: Float32Array) { stream.writeFloat32Array(value); } readMdlValue(stream: TokenStream) { return <Float32Array>stream.readVector(new Float32Array(3)); } writeMdlValue(stream: TokenStream, name: string, value: Float32Array) { stream.writeVectorAttrib(name, value); } } /** * A vector 4 animation. */ export class Vector4Animation extends Animation { readMdxValue(stream: BinaryStream) { return stream.readFloat32Array(4); } writeMdxValue(stream: BinaryStream, value: Float32Array) { stream.writeFloat32Array(value); } readMdlValue(stream: TokenStream) { return <Float32Array>stream.readVector(new Float32Array(4)); } writeMdlValue(stream: TokenStream, name: string, value: Float32Array) { stream.writeVectorAttrib(name, value); } }