war3-model
Version:
Warcraft 3 model parser, generator, convertor and previewer
623 lines (611 loc) • 20 kB
TypeScript
import { DdsInfo } from 'dds-parser';
import { vec3, quat, mat4 } from 'gl-matrix';
interface ModelInfo {
Name: string;
MinimumExtent: Float32Array;
MaximumExtent: Float32Array;
BoundsRadius: number;
BlendTime: number;
NumGeosets?: number;
NumGeosetAnims?: number;
NumBones?: number;
NumLights?: number;
NumAttachments?: number;
NumEvents?: number;
NumParticleEmitters?: number;
NumParticleEmitters2?: number;
NumRibbonEmitters?: number;
}
interface Sequence {
Name: string;
Interval: Uint32Array;
NonLooping: boolean;
MinimumExtent: Float32Array;
MaximumExtent: Float32Array;
BoundsRadius: number;
MoveSpeed: number;
Rarity: number;
}
declare enum TextureFlags {
WrapWidth = 1,
WrapHeight = 2
}
interface Texture {
Image: string;
ReplaceableId?: number;
Flags?: TextureFlags;
}
declare enum FilterMode {
None = 0,
Transparent = 1,
Blend = 2,
Additive = 3,
AddAlpha = 4,
Modulate = 5,
Modulate2x = 6
}
declare enum LineType {
DontInterp = 0,
Linear = 1,
Hermite = 2,
Bezier = 3
}
interface AnimKeyframe {
Frame: number;
Vector: Float32Array | Int32Array;
InTan?: Float32Array | Int32Array;
OutTan?: Float32Array | Int32Array;
}
interface AnimVector {
LineType: LineType;
GlobalSeqId?: number;
Keys: AnimKeyframe[];
}
declare enum LayerShading {
Unshaded = 1,
SphereEnvMap = 2,
TwoSided = 16,
Unfogged = 32,
NoDepthTest = 64,
NoDepthSet = 128
}
interface Layer {
FilterMode?: FilterMode;
Shading?: number;
TextureID?: AnimVector | number;
TVertexAnimId?: number;
CoordId: number;
Alpha?: AnimVector | number;
EmissiveGain?: AnimVector | number;
FresnelColor?: AnimVector | Float32Array;
FresnelOpacity?: AnimVector | number;
FresnelTeamColor?: AnimVector | number;
ShaderTypeId?: number;
NormalTextureID?: AnimVector | number;
ORMTextureID?: AnimVector | number;
EmissiveTextureID?: AnimVector | number;
TeamColorTextureID?: AnimVector | number;
ReflectionsTextureID?: AnimVector | number;
}
declare enum MaterialRenderMode {
ConstantColor = 1,
SortPrimsFarZ = 16,
FullResolution = 32
}
interface Material {
PriorityPlane?: number;
RenderMode?: number;
Layers: Layer[];
Shader?: string;
}
interface GeosetAnimInfo {
MinimumExtent: Float32Array;
MaximumExtent: Float32Array;
BoundsRadius: number;
}
interface Geoset {
Vertices: Float32Array;
Normals: Float32Array;
TVertices: Float32Array[];
VertexGroup: Uint8Array;
Faces: Uint16Array;
Groups: number[][];
TotalGroupsCount: number;
MinimumExtent: Float32Array;
MaximumExtent: Float32Array;
BoundsRadius: number;
Anims: GeosetAnimInfo[];
MaterialID: number;
SelectionGroup: number;
Unselectable: boolean;
LevelOfDetail?: number;
Name?: string;
Tangents?: Float32Array;
SkinWeights?: Uint8Array;
}
declare enum GeosetAnimFlags {
DropShadow = 1,
Color = 2
}
interface GeosetAnim {
GeosetId: number;
Alpha: AnimVector | number;
Color: AnimVector | Float32Array;
Flags: number;
}
declare enum NodeFlags {
DontInheritTranslation = 1,
DontInheritRotation = 2,
DontInheritScaling = 4,
Billboarded = 8,
BillboardedLockX = 16,
BillboardedLockY = 32,
BillboardedLockZ = 64,
CameraAnchored = 128
}
declare enum NodeType {
Helper = 0,
Bone = 256,
Light = 512,
EventObject = 1024,
Attachment = 2048,
ParticleEmitter = 4096,
CollisionShape = 8192,
RibbonEmitter = 16384
}
interface Node {
Name: string;
ObjectId: number;
Parent?: number | null;
PivotPoint: Float32Array;
Flags: number;
Translation?: AnimVector;
Rotation?: AnimVector;
Scaling?: AnimVector;
}
interface Bone extends Node {
GeosetId?: number;
GeosetAnimId?: number;
}
declare type Helper = Node;
interface Attachment extends Node {
Path?: string;
AttachmentID?: number;
Visibility?: AnimVector;
}
interface EventObject extends Node {
EventTrack: Uint32Array;
}
declare enum CollisionShapeType {
Box = 0,
Sphere = 2
}
interface CollisionShape extends Node {
Shape: CollisionShapeType;
Vertices: Float32Array;
BoundsRadius?: number;
}
declare enum ParticleEmitterFlags {
EmitterUsesMDL = 32768,
EmitterUsesTGA = 65536
}
interface ParticleEmitter extends Node {
EmissionRate: AnimVector | number;
Gravity: AnimVector | number;
Longitude: AnimVector | number;
Latitude: AnimVector | number;
Path: string;
LifeSpan: AnimVector | number;
InitVelocity: AnimVector | number;
Visibility: AnimVector;
}
declare enum ParticleEmitter2Flags {
Unshaded = 32768,
SortPrimsFarZ = 65536,
LineEmitter = 131072,
Unfogged = 262144,
ModelSpace = 524288,
XYQuad = 1048576
}
declare enum ParticleEmitter2FilterMode {
Blend = 0,
Additive = 1,
Modulate = 2,
Modulate2x = 3,
AlphaKey = 4
}
declare enum ParticleEmitter2FramesFlags {
Head = 1,
Tail = 2
}
interface ParticleEmitter2 extends Node {
Speed?: AnimVector | number;
Variation?: AnimVector | number;
Latitude?: AnimVector | number;
Gravity?: AnimVector | number;
Visibility?: AnimVector | number;
Squirt?: boolean;
LifeSpan?: number;
EmissionRate?: AnimVector | number;
Width?: AnimVector | number;
Length?: AnimVector | number;
FilterMode?: ParticleEmitter2FilterMode;
Rows?: number;
Columns?: number;
FrameFlags: number;
TailLength?: number;
Time?: number;
SegmentColor?: Float32Array[];
Alpha?: Uint8Array;
ParticleScaling?: Float32Array;
LifeSpanUVAnim?: Uint32Array;
DecayUVAnim?: Uint32Array;
TailUVAnim?: Uint32Array;
TailDecayUVAnim?: Uint32Array;
TextureID?: number;
ReplaceableId?: number;
PriorityPlane?: number;
}
interface Camera {
Name: string;
Position: Float32Array;
FieldOfView: number;
NearClip: number;
FarClip: number;
TargetPosition: Float32Array;
TargetTranslation?: AnimVector;
Translation?: AnimVector;
Rotation?: AnimVector;
}
declare enum LightType {
Omnidirectional = 0,
Directional = 1,
Ambient = 2
}
interface Light extends Node {
LightType: LightType;
AttenuationStart?: AnimVector | number;
AttenuationEnd?: AnimVector | number;
Color?: AnimVector | Float32Array;
Intensity?: AnimVector | number;
AmbIntensity?: AnimVector | number;
AmbColor?: AnimVector | Float32Array;
Visibility?: AnimVector;
}
interface RibbonEmitter extends Node {
HeightAbove?: AnimVector | number;
HeightBelow?: AnimVector | number;
Alpha?: AnimVector | number;
Color?: Float32Array;
LifeSpan?: number;
TextureSlot?: AnimVector | number;
EmissionRate?: number;
Rows?: number;
Columns?: number;
MaterialID?: number;
Gravity?: number;
Visibility?: AnimVector;
}
interface TVertexAnim {
Translation?: AnimVector;
Rotation?: AnimVector;
Scaling?: AnimVector;
}
interface FaceFX {
Name: string;
Path: string;
}
interface BindPose {
Matrices: Float32Array[];
}
declare enum ParticleEmitterPopcornFlags {
Unshaded = 32768,
SortPrimsFarZ = 65536,
Unfogged = 262144
}
interface ParticleEmitterPopcorn extends Node {
LifeSpan?: AnimVector | number;
EmissionRate?: AnimVector | number;
Speed?: AnimVector | number;
Color?: AnimVector | Float32Array;
Alpha?: AnimVector | number;
ReplaceableId?: number;
Path?: string;
AnimVisibilityGuide?: string;
Visibility?: AnimVector;
}
interface Model {
Version: number;
Info: ModelInfo;
Sequences: Sequence[];
Textures: Texture[];
Materials: Material[];
Geosets: Geoset[];
GeosetAnims: GeosetAnim[];
Bones: Bone[];
Helpers: Helper[];
Attachments: Attachment[];
Nodes: Node[];
PivotPoints: Float32Array[];
EventObjects: EventObject[];
CollisionShapes: CollisionShape[];
GlobalSequences: number[];
ParticleEmitters: ParticleEmitter[];
ParticleEmitters2: ParticleEmitter2[];
Cameras: Camera[];
Lights: Light[];
RibbonEmitters: RibbonEmitter[];
TextureAnims: TVertexAnim[];
FaceFX?: FaceFX[];
BindPoses?: BindPose[];
ParticleEmitterPopcorns?: ParticleEmitterPopcorn[];
}
type model_AnimKeyframe = AnimKeyframe;
type model_AnimVector = AnimVector;
type model_Attachment = Attachment;
type model_BindPose = BindPose;
type model_Bone = Bone;
type model_Camera = Camera;
type model_CollisionShape = CollisionShape;
type model_CollisionShapeType = CollisionShapeType;
declare const model_CollisionShapeType: typeof CollisionShapeType;
type model_EventObject = EventObject;
type model_FaceFX = FaceFX;
type model_FilterMode = FilterMode;
declare const model_FilterMode: typeof FilterMode;
type model_Geoset = Geoset;
type model_GeosetAnim = GeosetAnim;
type model_GeosetAnimFlags = GeosetAnimFlags;
declare const model_GeosetAnimFlags: typeof GeosetAnimFlags;
type model_GeosetAnimInfo = GeosetAnimInfo;
type model_Helper = Helper;
type model_Layer = Layer;
type model_LayerShading = LayerShading;
declare const model_LayerShading: typeof LayerShading;
type model_Light = Light;
type model_LightType = LightType;
declare const model_LightType: typeof LightType;
type model_LineType = LineType;
declare const model_LineType: typeof LineType;
type model_Material = Material;
type model_MaterialRenderMode = MaterialRenderMode;
declare const model_MaterialRenderMode: typeof MaterialRenderMode;
type model_Model = Model;
type model_ModelInfo = ModelInfo;
type model_Node = Node;
type model_NodeFlags = NodeFlags;
declare const model_NodeFlags: typeof NodeFlags;
type model_NodeType = NodeType;
declare const model_NodeType: typeof NodeType;
type model_ParticleEmitter = ParticleEmitter;
type model_ParticleEmitter2 = ParticleEmitter2;
type model_ParticleEmitter2FilterMode = ParticleEmitter2FilterMode;
declare const model_ParticleEmitter2FilterMode: typeof ParticleEmitter2FilterMode;
type model_ParticleEmitter2Flags = ParticleEmitter2Flags;
declare const model_ParticleEmitter2Flags: typeof ParticleEmitter2Flags;
type model_ParticleEmitter2FramesFlags = ParticleEmitter2FramesFlags;
declare const model_ParticleEmitter2FramesFlags: typeof ParticleEmitter2FramesFlags;
type model_ParticleEmitterFlags = ParticleEmitterFlags;
declare const model_ParticleEmitterFlags: typeof ParticleEmitterFlags;
type model_ParticleEmitterPopcorn = ParticleEmitterPopcorn;
type model_ParticleEmitterPopcornFlags = ParticleEmitterPopcornFlags;
declare const model_ParticleEmitterPopcornFlags: typeof ParticleEmitterPopcornFlags;
type model_RibbonEmitter = RibbonEmitter;
type model_Sequence = Sequence;
type model_TVertexAnim = TVertexAnim;
type model_Texture = Texture;
type model_TextureFlags = TextureFlags;
declare const model_TextureFlags: typeof TextureFlags;
declare namespace model {
export { model_CollisionShapeType as CollisionShapeType, model_FilterMode as FilterMode, model_GeosetAnimFlags as GeosetAnimFlags, model_LayerShading as LayerShading, model_LightType as LightType, model_LineType as LineType, model_MaterialRenderMode as MaterialRenderMode, model_NodeFlags as NodeFlags, model_NodeType as NodeType, model_ParticleEmitter2FilterMode as ParticleEmitter2FilterMode, model_ParticleEmitter2Flags as ParticleEmitter2Flags, model_ParticleEmitter2FramesFlags as ParticleEmitter2FramesFlags, model_ParticleEmitterFlags as ParticleEmitterFlags, model_ParticleEmitterPopcornFlags as ParticleEmitterPopcornFlags, model_TextureFlags as TextureFlags };
export type { model_AnimKeyframe as AnimKeyframe, model_AnimVector as AnimVector, model_Attachment as Attachment, model_BindPose as BindPose, model_Bone as Bone, model_Camera as Camera, model_CollisionShape as CollisionShape, model_EventObject as EventObject, model_FaceFX as FaceFX, model_Geoset as Geoset, model_GeosetAnim as GeosetAnim, model_GeosetAnimInfo as GeosetAnimInfo, model_Helper as Helper, model_Layer as Layer, model_Light as Light, model_Material as Material, model_Model as Model, model_ModelInfo as ModelInfo, model_Node as Node, model_ParticleEmitter as ParticleEmitter, model_ParticleEmitter2 as ParticleEmitter2, model_ParticleEmitterPopcorn as ParticleEmitterPopcorn, model_RibbonEmitter as RibbonEmitter, model_Sequence as Sequence, model_TVertexAnim as TVertexAnim, model_Texture as Texture };
}
declare function parse$1(str: string): Model;
declare function parse(arrayBuffer: ArrayBuffer): Model;
declare function generate$1(model: Model): string;
declare function generate(model: Model): ArrayBuffer;
declare enum BLPType {
BLP0 = 0,
BLP1 = 1,
BLP2 = 2
}
declare enum BLPContent {
JPEG = 0,
Direct = 1
}
interface BLPMipMap {
offset: number;
size: number;
}
interface BLPImage {
type: BLPType;
width: number;
height: number;
content: BLPContent;
alphaBits: number;
mipmaps: BLPMipMap[];
data: ArrayBuffer;
}
type blpimage_BLPContent = BLPContent;
declare const blpimage_BLPContent: typeof BLPContent;
type blpimage_BLPImage = BLPImage;
type blpimage_BLPMipMap = BLPMipMap;
type blpimage_BLPType = BLPType;
declare const blpimage_BLPType: typeof BLPType;
declare namespace blpimage {
export { blpimage_BLPContent as BLPContent, blpimage_BLPType as BLPType };
export type { blpimage_BLPImage as BLPImage, blpimage_BLPMipMap as BLPMipMap };
}
interface ImageDataLike {
width: number;
height: number;
data: Uint8ClampedArray;
colorSpace: 'srgb' | 'display-p3' | undefined;
}
declare function decode(arrayBuffer: ArrayBuffer): BLPImage;
declare function getImageData(blp: BLPImage, mipmapLevel: number): ImageDataLike;
declare type DDS_FORMAT = WEBGL_compressed_texture_s3tc['COMPRESSED_RGBA_S3TC_DXT1_EXT'] | WEBGL_compressed_texture_s3tc['COMPRESSED_RGBA_S3TC_DXT3_EXT'] | WEBGL_compressed_texture_s3tc['COMPRESSED_RGBA_S3TC_DXT5_EXT'] | WEBGL_compressed_texture_s3tc['COMPRESSED_RGB_S3TC_DXT1_EXT'];
declare class ModelRenderer {
private isHD;
private canvas;
private gl;
private device;
private gpuContext;
private anisotropicExt;
private colorBufferFloatExt;
private vertexShader;
private fragmentShader;
private shaderProgram;
private vsBindGroupLayout;
private fsBindGroupLayout;
private gpuShaderModule;
private gpuDepthShaderModule;
private gpuPipelines;
private gpuWireframePipeline;
private gpuShadowPipeline;
private gpuPipelineLayout;
private gpuRenderPassDescriptor;
private shaderProgramLocations;
private skeletonShaderProgram;
private skeletonVertexShader;
private skeletonFragmentShader;
private skeletonShaderProgramLocations;
private skeletonVertexBuffer;
private skeletonColorBuffer;
private skeletonShaderModule;
private skeletonBindGroupLayout;
private skeletonPipelineLayout;
private skeletonPipeline;
private skeletonGPUVertexBuffer;
private skeletonGPUColorBuffer;
private skeletonGPUUniformsBuffer;
private model;
private interp;
private rendererData;
private particlesController;
private ribbonsController;
private softwareSkinning;
private vertexBuffer;
private normalBuffer;
private vertices;
private texCoordBuffer;
private indexBuffer;
private wireframeIndexBuffer;
private wireframeIndexGPUBuffer;
private groupBuffer;
private skinWeightBuffer;
private tangentBuffer;
private envShaderModeule;
private envPiepeline;
private envVSBindGroupLayout;
private envFSBindGroupLayout;
private envVSUniformsBuffer;
private envVSBindGroup;
private envSampler;
private cubeVertexBuffer;
private cubeGPUVertexBuffer;
private squareVertexBuffer;
private brdfLUT;
private gpuBrdfLUT;
private gpuBrdfSampler;
private envToCubemap;
private envToCubemapShaderModule;
private envToCubemapPiepeline;
private envToCubemapVSBindGroupLayout;
private envToCubemapFSBindGroupLayout;
private envToCubemapSampler;
private envSphere;
private convoluteDiffuseEnv;
private convoluteDiffuseEnvShaderModule;
private convoluteDiffuseEnvPiepeline;
private convoluteDiffuseEnvVSBindGroupLayout;
private convoluteDiffuseEnvFSBindGroupLayout;
private convoluteDiffuseEnvSampler;
private prefilterEnv;
private prefilterEnvShaderModule;
private prefilterEnvPiepeline;
private prefilterEnvVSBindGroupLayout;
private prefilterEnvFSBindGroupLayout;
private prefilterEnvSampler;
private integrateBRDF;
private gpuMultisampleTexture;
private gpuDepthTexture;
private gpuVertexBuffer;
private gpuNormalBuffer;
private gpuTexCoordBuffer;
private gpuGroupBuffer;
private gpuIndexBuffer;
private gpuSkinWeightBuffer;
private gpuTangentBuffer;
private gpuVSUniformsBuffer;
private gpuVSUniformsBindGroup;
private gpuFSUniformsBuffers;
constructor(model: Model);
destroy(): void;
private initRequiredEnvMaps;
initGL(glContext: WebGL2RenderingContext | WebGLRenderingContext): void;
initGPUDevice(canvas: HTMLCanvasElement, device: GPUDevice, context: GPUCanvasContext): Promise<void>;
setTextureImage(path: string, img: HTMLImageElement): void;
setTextureImageData(path: string, imageData: ImageData[]): void;
setTextureCompressedImage(path: string, format: DDS_FORMAT, imageData: ArrayBuffer, ddsInfo: DdsInfo): void;
setGPUTextureCompressedImage(path: string, format: GPUTextureFormat, imageData: ArrayBuffer, ddsInfo: DdsInfo): void;
setCamera(cameraPos: vec3, cameraQuat: quat): void;
setLightPosition(lightPos: vec3): void;
setLightColor(lightColor: vec3): void;
setSequence(index: number): void;
getSequence(): number;
setFrame(frame: number): void;
getFrame(): number;
setTeamColor(color: vec3): void;
update(delta: number): void;
render(mvMatrix: mat4, pMatrix: mat4, { wireframe, env, levelOfDetail, useEnvironmentMap, shadowMapTexture, shadowMapMatrix, shadowBias, shadowSmoothingStep, depthTextureTarget }: {
wireframe?: boolean;
env?: boolean;
levelOfDetail?: number;
useEnvironmentMap?: boolean;
shadowMapTexture?: WebGLTexture | GPUTexture;
shadowMapMatrix?: mat4;
shadowBias?: number;
shadowSmoothingStep?: number;
depthTextureTarget?: GPUTexture;
}): void;
private renderEnvironmentGPU;
private renderEnvironment;
/**
* @param mvMatrix
* @param pMatrix
* @param nodes Nodes to highlight. null means draw all
*/
renderSkeleton(mvMatrix: mat4, pMatrix: mat4, nodes: string[] | null): void;
private initSkeletonShaderProgram;
private generateGeosetVertices;
private setTextureParameters;
private processEnvMaps;
private initShaderProgram;
private destroyShaderProgramObject;
private initShaders;
private initGPUShaders;
private createWireframeBuffer;
private createWireframeGPUBuffer;
private initBuffers;
private createGPUPipeline;
private createGPUPipelineByLayer;
private getGPUPipeline;
private initGPUPipeline;
private initGPUBuffers;
private initGPUUniformBuffers;
private initGPUMultisampleTexture;
private initGPUDepthTexture;
private initGPUEmptyTexture;
private initCube;
private initSquare;
private initBRDFLUT;
private initGPUBRDFLUT;
private updateGlobalSequences;
private updateNode;
private findAlpha;
private getTexCoordMatrix;
private setLayerProps;
private setLayerPropsHD;
}
export { ModelRenderer, blpimage as blp, decode as decodeBLP, generate$1 as generateMDL, generate as generateMDX, getImageData as getBLPImageData, model, parse$1 as parseMDL, parse as parseMDX };