{"version":3,"file":"war3-model.mjs","names":["decode","create","glMatrix.ARRAY_TYPE","set","create","glMatrix.ARRAY_TYPE","create","glMatrix.ARRAY_TYPE","clone","length","fromValues","copy","set","add","scale","normalize","dot","lerp","hermite","bezier","forEach","create","glMatrix.ARRAY_TYPE","clone","fromValues","copy","set","add","scale","length","squaredLength","normalize","dot","lerp","exactEquals","equals","glMatrix.ARRAY_TYPE","vec4.clone","vec4.fromValues","vec4.copy","vec4.set","vec4.add","vec4.scale","vec4.dot","lerp","vec4.lerp","vec4.length","vec4.squaredLength","vec4.normalize","vec4.exactEquals","vec4.equals","vec3.create","vec3.fromValues","vec3.dot","vec3.len","mat3.create"],"sources":["../../model.ts","../../renderer/util.ts","../../mdl/parse.ts","../../mdx/parse.ts","../../mdl/generate.ts","../../mdx/generate.ts","../../blp/blpimage.ts","../../third_party/decoder.js","../../blp/decode.ts","../../node_modules/gl-matrix/esm/common.js","../../node_modules/gl-matrix/esm/mat3.js","../../node_modules/gl-matrix/esm/mat4.js","../../node_modules/gl-matrix/esm/vec3.js","../../node_modules/gl-matrix/esm/vec4.js","../../node_modules/gl-matrix/esm/quat.js","../../renderer/interp.ts","../../renderer/modelInterp.ts","../../renderer/shaders/webgl/particles.vs.glsl?raw","../../renderer/shaders/webgl/particles.fs.glsl?raw","../../renderer/shaders/webgpu/particles.wgsl?raw","../../renderer/particles.ts","../../renderer/shaders/webgl/ribbon.vs.glsl?raw","../../renderer/shaders/webgl/ribbon.fs.glsl?raw","../../renderer/shaders/webgpu/ribbons.wgsl?raw","../../renderer/ribbons.ts","../../renderer/shaders/webgl/sdHardwareSkinning.vs.glsl?raw","../../renderer/shaders/webgl/sdSoftwareSkinning.vs.glsl?raw","../../renderer/shaders/webgl/sd.fs.glsl?raw","../../renderer/shaders/webgl/hdHardwareSkinningOld.vs.glsl?raw","../../renderer/shaders/webgl/hdHardwareSkinningNew.vs.glsl?raw","../../renderer/shaders/webgl/hdOld.fs.glsl?raw","../../renderer/shaders/webgl/hdNew.fs.glsl?raw","../../renderer/shaders/webgl/skeleton.vs.glsl?raw","../../renderer/shaders/webgl/skeleton.fs.glsl?raw","../../renderer/shaders/webgl/envToCubemap.vs.glsl?raw","../../renderer/shaders/webgl/envToCubemap.fs.glsl?raw","../../renderer/shaders/webgl/env.vs.glsl?raw","../../renderer/shaders/webgl/env.fs.glsl?raw","../../renderer/shaders/webgl/convoluteEnvDiffuse.vs.glsl?raw","../../renderer/shaders/webgl/convoluteEnvDiffuse.fs.glsl?raw","../../renderer/shaders/webgl/prefilterEnv.vs.glsl?raw","../../renderer/shaders/webgl/prefilterEnv.fs.glsl?raw","../../renderer/shaders/webgl/integrateBRDF.vs.glsl?raw","../../renderer/shaders/webgl/integrateBRDF.fs.glsl?raw","../../renderer/shaders/webgpu/sd.wgsl?raw","../../renderer/shaders/webgpu/hd.wgsl?raw","../../renderer/shaders/webgpu/depth.wgsl?raw","../../renderer/shaders/webgpu/skeleton.wgsl?raw","../../renderer/shaders/webgpu/env.wgsl?raw","../../renderer/shaders/webgpu/envToCubemap.wgsl?raw","../../renderer/shaders/webgpu/convoluteEnvDiffuse.wgsl?raw","../../renderer/shaders/webgpu/prefilterEnv.wgsl?raw","../../renderer/shaders/webgpu/integrateBRDF.wgsl?raw","../../renderer/shaders/webgpu/mips.wgsl?raw","../../renderer/generateMips.ts","../../renderer/modelRenderer.ts"],"sourcesContent":["export interface ModelInfo {\n    Name: string;\n    MinimumExtent: Float32Array;\n    MaximumExtent: Float32Array;\n    BoundsRadius: number;\n    BlendTime: number;\n    NumGeosets?: number;\n    NumGeosetAnims?: number;\n    NumBones?: number;\n    NumLights?: number;\n    NumAttachments?: number;\n    NumEvents?: number;\n    NumParticleEmitters?: number;\n    NumParticleEmitters2?: number;\n    NumRibbonEmitters?: number;\n}\n\nexport interface Sequence {\n    Name: string;\n    Interval: Uint32Array;\n    NonLooping: boolean;\n    MinimumExtent: Float32Array;\n    MaximumExtent: Float32Array;\n    BoundsRadius: number;\n    MoveSpeed: number;\n    Rarity: number;\n}\n\nexport enum TextureFlags {\n    WrapWidth = 1,\n    WrapHeight = 2\n}\n\nexport interface Texture {\n    Image: string;\n    ReplaceableId?: number;\n    Flags?: TextureFlags;\n}\n\nexport enum FilterMode {\n    None = 0,\n    Transparent = 1,\n    Blend = 2,\n    Additive = 3,\n    AddAlpha = 4,\n    Modulate = 5,\n    Modulate2x = 6\n}\n\nexport enum LineType {\n    DontInterp = 0,\n    Linear = 1,\n    Hermite = 2,\n    Bezier = 3\n}\n\nexport interface AnimKeyframe {\n    Frame: number;\n    Vector: Float32Array|Int32Array;\n    InTan?: Float32Array|Int32Array;\n    OutTan?: Float32Array|Int32Array;\n}\n\nexport interface AnimVector {\n    LineType: LineType;\n    GlobalSeqId?: number;\n    Keys: AnimKeyframe[];\n}\n\nexport enum LayerShading {\n    Unshaded = 1,\n    SphereEnvMap = 2,\n    TwoSided = 16,\n    Unfogged = 32,\n    NoDepthTest = 64,\n    NoDepthSet = 128\n}\n\nexport interface Layer {\n    FilterMode?: FilterMode;\n    Shading?: number;\n    TextureID?: AnimVector|number;\n    TVertexAnimId?: number;\n    CoordId: number;\n    Alpha?: AnimVector|number;\n    /* Since Version: 900 */\n    EmissiveGain?: AnimVector|number;\n    /* Since Version: 1000 */\n    FresnelColor?: AnimVector|Float32Array;\n    /* Since Version: 1000 */\n    FresnelOpacity?: AnimVector|number;\n    /* Since Version: 1000 */\n    FresnelTeamColor?: AnimVector|number;\n    /* Since version: 1100 */\n    ShaderTypeId?: number;\n    NormalTextureID?: AnimVector|number;\n    ORMTextureID?: AnimVector|number;\n    EmissiveTextureID?: AnimVector|number;\n    TeamColorTextureID?: AnimVector|number;\n    ReflectionsTextureID?: AnimVector|number;\n}\n\nexport enum MaterialRenderMode {\n    ConstantColor = 1,\n    SortPrimsFarZ = 16,\n    FullResolution = 32,\n}\n\nexport interface Material {\n    PriorityPlane?: number;\n    RenderMode?: number;\n    Layers: Layer[];\n    /* Since Version: 900 */\n    Shader?: string;\n}\n\nexport interface GeosetAnimInfo {\n    MinimumExtent: Float32Array;\n    MaximumExtent: Float32Array;\n    BoundsRadius: number;\n}\n\nexport interface Geoset {\n    Vertices: Float32Array;\n    Normals: Float32Array;\n    TVertices: Float32Array[];\n    VertexGroup: Uint8Array;\n    Faces: Uint16Array;\n    Groups: number[][];\n    TotalGroupsCount: number;\n    MinimumExtent: Float32Array;\n    MaximumExtent: Float32Array;\n    BoundsRadius: number;\n    Anims: GeosetAnimInfo[];\n    MaterialID: number;\n    SelectionGroup: number;\n    Unselectable: boolean;\n    /* Since Version: 900 */\n    LevelOfDetail?: number;\n    /* Since Version: 900 */\n    Name?: string;\n    /* Since Version: 900 */\n    Tangents?: Float32Array;\n    /* Since Version: 900 */\n    SkinWeights?: Uint8Array;\n}\n\nexport enum GeosetAnimFlags {\n    DropShadow = 1,\n    Color = 2\n}\n\nexport interface GeosetAnim {\n    GeosetId: number;\n    Alpha: AnimVector|number;\n    Color: AnimVector|Float32Array;\n    Flags: number;\n}\n\nexport enum NodeFlags {\n    DontInheritTranslation = 1,\n    DontInheritRotation = 2,\n    DontInheritScaling = 4,\n    Billboarded = 8,\n    BillboardedLockX = 16,\n    BillboardedLockY = 32,\n    BillboardedLockZ = 64,\n    CameraAnchored = 128\n}\n\nexport enum NodeType {\n    Helper = 0,\n    Bone = 256,\n    Light = 512,\n    EventObject = 1024,\n    Attachment = 2048,\n    ParticleEmitter = 4096, // ParticleEmitter | ParticleEmitter2 | ParticleEmitterPopcorn\n    CollisionShape = 8192,\n    RibbonEmitter = 16384\n}\n\nexport interface Node {\n    Name: string;\n    ObjectId: number;\n    Parent?: number|null;\n    PivotPoint: Float32Array;\n    Flags: number;\n\n    Translation?: AnimVector;\n    Rotation?: AnimVector;\n    Scaling?: AnimVector;\n}\n\nexport interface Bone extends Node {\n    GeosetId?: number;\n    GeosetAnimId?: number;\n}\n\nexport type Helper = Node\n\nexport interface Attachment extends Node {\n    Path?: string;\n    AttachmentID?: number;\n    Visibility?: AnimVector;\n}\n\nexport interface EventObject extends Node {\n    EventTrack: Uint32Array;\n}\n\nexport enum CollisionShapeType {\n    Box = 0,\n    Sphere = 2\n}\n\nexport interface CollisionShape extends Node {\n    Shape: CollisionShapeType;\n    Vertices: Float32Array;\n    BoundsRadius?: number;\n}\n\nexport enum ParticleEmitterFlags {\n    EmitterUsesMDL = 32768,\n    EmitterUsesTGA = 65536\n}\n\nexport interface ParticleEmitter extends Node {\n    EmissionRate: AnimVector|number;\n    Gravity: AnimVector|number;\n    Longitude: AnimVector|number;\n    Latitude: AnimVector|number;\n    Path: string;\n    LifeSpan: AnimVector|number;\n    InitVelocity: AnimVector|number;\n    Visibility: AnimVector;\n}\n\nexport enum ParticleEmitter2Flags {\n    Unshaded = 32768,\n    SortPrimsFarZ = 65536,\n    LineEmitter = 131072,\n    Unfogged = 262144,\n    ModelSpace = 524288,\n    XYQuad = 1048576\n}\n\nexport enum ParticleEmitter2FilterMode {\n    Blend = 0,\n    Additive = 1,\n    Modulate = 2,\n    Modulate2x = 3,\n    AlphaKey = 4\n}\n\n// Not actually mapped to mdx flags (0: Head, 1: Tail, 2: Both)\nexport enum ParticleEmitter2FramesFlags {\n    Head = 1,\n    Tail = 2\n}\n\nexport interface ParticleEmitter2 extends Node {\n    Speed?: AnimVector|number;\n    Variation?: AnimVector|number;\n    Latitude?: AnimVector|number;\n    Gravity?: AnimVector|number;\n    Visibility?: AnimVector|number;\n    Squirt?: boolean;\n    LifeSpan?: number;\n    EmissionRate?: AnimVector|number;\n    Width?: AnimVector|number;\n    Length?: AnimVector|number;\n    FilterMode?: ParticleEmitter2FilterMode;\n    Rows?: number;\n    Columns?: number;\n    FrameFlags: number;\n    TailLength?: number;\n    Time?: number;\n    SegmentColor?: Float32Array[];\n    Alpha?: Uint8Array;\n    ParticleScaling?: Float32Array;\n    LifeSpanUVAnim?: Uint32Array;\n    DecayUVAnim?: Uint32Array;\n    TailUVAnim?: Uint32Array;\n    TailDecayUVAnim?: Uint32Array;\n    TextureID?: number;\n    ReplaceableId?: number;\n    PriorityPlane?: number;\n}\n\nexport interface Camera {\n    Name: string;\n    Position: Float32Array;\n    FieldOfView: number;\n    NearClip: number;\n    FarClip: number;\n    TargetPosition: Float32Array;\n    TargetTranslation?: AnimVector;\n    Translation?: AnimVector;\n    Rotation?: AnimVector;\n}\n\nexport enum LightType {\n    Omnidirectional = 0,\n    Directional = 1,\n    Ambient = 2\n}\n\nexport interface Light extends Node {\n    LightType: LightType;\n\n    AttenuationStart?: AnimVector|number;\n    AttenuationEnd?: AnimVector|number;\n\n    Color?: AnimVector|Float32Array;\n    Intensity?: AnimVector|number;\n    AmbIntensity?: AnimVector|number;\n    AmbColor?: AnimVector|Float32Array;\n\n    Visibility?: AnimVector;\n}\n\nexport interface RibbonEmitter extends Node {\n    HeightAbove?: AnimVector|number;\n    HeightBelow?: AnimVector|number;\n    Alpha?: AnimVector|number;\n    // todo support KRCO\n    Color?: Float32Array;\n    LifeSpan?: number;\n    TextureSlot?: AnimVector|number;\n    EmissionRate?: number;\n    Rows?: number;\n    Columns?: number;\n    MaterialID?: number;\n    Gravity?: number;\n\n    Visibility?: AnimVector;\n}\n\nexport interface TVertexAnim {\n    Translation?: AnimVector;\n    Rotation?: AnimVector;\n    Scaling?: AnimVector;\n}\n\n/* Since Version: 900 */\nexport interface FaceFX {\n    Name: string;\n    Path: string;\n}\n\n/* Since Version: 900 */\nexport interface BindPose {\n    Matrices: Float32Array[];\n}\n\n/* Since Version: 900 */\nexport enum ParticleEmitterPopcornFlags {\n    Unshaded = 32768,\n    SortPrimsFarZ = 65536,\n    Unfogged = 262144\n}\n\n/* Since Version: 900 */\nexport interface ParticleEmitterPopcorn extends Node {\n    LifeSpan?: AnimVector|number;\n    EmissionRate?: AnimVector|number;\n    Speed?: AnimVector|number;\n    Color?: AnimVector|Float32Array;\n    Alpha?: AnimVector|number;\n    ReplaceableId?: number;\n    Path?: string;\n    AnimVisibilityGuide?: string;\n    Visibility?: AnimVector;\n}\n\nexport interface Model {\n    Version: number;\n    Info: ModelInfo;\n    Sequences: Sequence[];\n    Textures: Texture[];\n    Materials: Material[];\n    Geosets: Geoset[];\n    GeosetAnims: GeosetAnim[];\n    Bones: Bone[];\n    Helpers: Helper[];\n    Attachments: Attachment[];\n    Nodes: Node[];\n    PivotPoints: Float32Array[];\n    EventObjects: EventObject[];\n    CollisionShapes: CollisionShape[];\n    GlobalSequences: number[];\n    ParticleEmitters: ParticleEmitter[];\n    ParticleEmitters2: ParticleEmitter2[];\n    Cameras: Camera[];\n    Lights: Light[];\n    RibbonEmitters: RibbonEmitter[];\n    TextureAnims: TVertexAnim[];\n    /* Since Version: 900 */\n    FaceFX?: FaceFX[];\n    /* Since Version: 900 */\n    BindPoses?: BindPose[];\n    /* Since Version: 900 */\n    ParticleEmitterPopcorns?: ParticleEmitterPopcorn[];\n}\n","import {vec3, quat, mat4} from 'gl-matrix';\n\nexport function mat4fromRotationOrigin (out: mat4, rotation: quat, origin: vec3): mat4 {\n    const x = rotation[0], y = rotation[1], z = rotation[2], w = rotation[3],\n        x2 = x + x,\n        y2 = y + y,\n        z2 = z + z,\n\n        xx = x * x2,\n        xy = x * y2,\n        xz = x * z2,\n        yy = y * y2,\n        yz = y * z2,\n        zz = z * z2,\n        wx = w * x2,\n        wy = w * y2,\n        wz = w * z2,\n\n        ox = origin[0],\n        oy = origin[1],\n        oz = origin[2];\n\n    out[0] = (1 - (yy + zz));\n    out[1] = (xy + wz);\n    out[2] = (xz - wy);\n    out[3] = 0;\n    out[4] = (xy - wz);\n    out[5] = (1 - (xx + zz));\n    out[6] = (yz + wx);\n    out[7] = 0;\n    out[8] = (xz + wy);\n    out[9] = (yz - wx);\n    out[10] = (1 - (xx + yy));\n    out[11] = 0;\n    out[12] = ox - (out[0] * ox + out[4] * oy + out[8] * oz);\n    out[13] = oy - (out[1] * ox + out[5] * oy + out[9] * oz);\n    out[14] = oz - (out[2] * ox + out[6] * oy + out[10] * oz);\n    out[15] = 1;\n\n    return out;\n}\n\n/**\n * Rotate a 3D vector around the z-axis\n * @param {vec3} out The receiving vec3\n * @param {vec3} a The vec3 point to rotate\n * @param {Number} c The angle of rotation\n * @returns {vec3} out\n */\nexport function vec3RotateZ (out: vec3, a: vec3, c: number): vec3 {\n    out[0] = a[0] * Math.cos(c) - a[1] * Math.sin(c);\n    out[1] = a[0] * Math.sin(c) + a[1] * Math.cos(c);\n    out[2] = a[2];\n\n    return out;\n}\n\nexport function rand (from: number, to: number): number {\n    return from + Math.random() * (to - from);\n}\n\nexport function degToRad (angle: number): number {\n    return angle * Math.PI / 180;\n}\n\nexport function getShader (gl: WebGLRenderingContext, source: string, type: number): WebGLShader {\n    const shader: WebGLShader = gl.createShader(type);\n\n    gl.shaderSource(shader, source);\n    gl.compileShader(shader);\n\n    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n        alert(gl.getShaderInfoLog(shader));\n        return null;\n    }\n\n    return shader;\n}\n\nexport function isWebGL2 (gl: WebGLRenderingContext | WebGL2RenderingContext): gl is WebGL2RenderingContext {\n    return gl instanceof WebGL2RenderingContext;\n}\n\nexport const LAYER_TEXTURE_NAME_MAP = {\n    'TextureID': 0,\n    'NormalTextureID': 1,\n    'ORMTextureID': 2,\n    'EmissiveTextureID': 3,\n    'TeamColorTextureID': 4,\n    'ReflectionsTextureID': 5\n};\n\nexport const LAYER_TEXTURE_ID_MAP = [\n    'TextureID',\n    'NormalTextureID',\n    'ORMTextureID',\n    'EmissiveTextureID',\n    'TeamColorTextureID',\n    'ReflectionsTextureID'\n];\n","import {\n    Model, Layer, GeosetAnim, AnimVector, LineType, AnimKeyframe, Node,\n    CollisionShape, ParticleEmitter2, Camera, MaterialRenderMode, FilterMode, LayerShading, TextureFlags,\n    GeosetAnimFlags, NodeFlags, CollisionShapeType, ParticleEmitter2Flags, ParticleEmitter2FramesFlags, Light,\n    LightType, TVertexAnim, RibbonEmitter, ParticleEmitter2FilterMode, ParticleEmitter, ParticleEmitterFlags, NodeType,\n    EventObject, Sequence, ModelInfo, Geoset, GeosetAnimInfo, FaceFX, BindPose, ParticleEmitterPopcorn, ParticleEmitterPopcornFlags\n} from '../model';\nimport { LAYER_TEXTURE_NAME_MAP } from '../renderer/util';\n\nclass State {\n    public readonly str: string;\n    public pos: number;\n\n    constructor (str: string) {\n        this.str = str;\n        this.pos = 0;\n    }\n\n    public char (): string {\n        if (this.pos >= this.str.length) {\n            throwError(this, 'incorrect model data');\n        }\n        return this.str[this.pos];\n    }\n}\n\ntype IntArray = number[] | Uint8Array | Uint16Array | Uint32Array | Float32Array;\n\nfunction throwError (state: State, str = ''): void {\n    throw new Error(`SyntaxError, near ${state.pos}` + (str ? ', ' + str : ''));\n}\n\nfunction parseComment (state: State): boolean {\n    if (state.char() === '/' && state.str[state.pos + 1] === '/') {\n        state.pos += 2;\n        while (state.pos < state.str.length && state.str[++state.pos] !== '\\n');\n        ++state.pos;\n        return true;\n    }\n    return false;\n}\n\nconst spaceRE = /\\s/i;\nfunction parseSpace (state: State): void {\n    while (state.pos < state.str.length && spaceRE.test(state.char())) {\n        ++state.pos;\n    }\n}\n\nconst keywordFirstCharRE = /[a-z]/i;\nconst keywordOtherCharRE = /[a-z0-9]/i;\nfunction parseKeyword (state: State): string {\n    if (!keywordFirstCharRE.test(state.char())) {\n        return null;\n    }\n\n    let keyword = state.char();\n    ++state.pos;\n\n    while (keywordOtherCharRE.test(state.char())) {\n        keyword += state.str[state.pos++];\n    }\n\n    parseSpace(state);\n\n    return keyword;\n}\n\nfunction parseSymbol (state: State, symbol: string): void {\n    if (state.char() === symbol) {\n        ++state.pos;\n        parseSpace(state);\n    }\n}\n\nfunction strictParseSymbol (state: State, symbol: string): void {\n    if (state.char() !== symbol) {\n        throwError(state, `extected ${symbol}`);\n    }\n\n    ++state.pos;\n    parseSpace(state);\n}\n\nfunction parseString (state: State): string {\n    if (state.char() === '\"') {\n        const start = ++state.pos; // \"\n\n        while (state.char() !== '\"') {\n            ++state.pos;\n        }\n\n        ++state.pos; // \"\n\n        const res = state.str.substring(start, state.pos - 1);\n\n        parseSpace(state);\n\n        return res;\n    }\n\n    return null;\n}\n\nconst numberFirstCharRE = /[-0-9]/;\nconst numberOtherCharRE = /[-+.0-9e]/i;\nfunction parseNumber (state: State): number|null {\n    if (numberFirstCharRE.test(state.char())) {\n        const start = state.pos;\n\n        ++state.pos;\n\n        while (numberOtherCharRE.test(state.char())) {\n            ++state.pos;\n        }\n\n        const res = parseFloat(state.str.substring(start, state.pos));\n\n        parseSpace(state);\n\n        return res;\n    }\n\n    return null;\n}\n\nfunction parseArray (state: State, arr?: IntArray, pos?: number): typeof arr|null {\n    if (state.char() !== '{') {\n        return null;\n    }\n\n    if (!arr) {\n        arr = [];\n        pos = 0;\n    }\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const num = parseNumber(state);\n\n        if (num === null) {\n            throwError(state, 'expected number');\n        }\n\n        arr[pos++] = num;\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    return arr;\n}\n\nfunction parseArrayCounted (state: State, arr: IntArray, pos: number): number {\n    if (state.char() !== '{') {\n        return 0;\n    }\n\n    const start = pos;\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const num = parseNumber(state);\n\n        if (num === null) {\n            throwError(state, 'expected number');\n        }\n\n        arr[pos++] = num;\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    return pos - start;\n}\n\nfunction parseArrayOrSingleItem<ArrType extends Uint16Array|Uint32Array|Int32Array|Float32Array>\n    (state: State, arr: ArrType): ArrType {\n    if (state.char() !== '{') {\n        arr[0] = parseNumber(state);\n        return arr;\n    }\n\n    let pos = 0;\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const num = parseNumber(state);\n\n        if (num === null) {\n            throwError(state, 'expected number');\n        }\n\n        arr[pos++] = num;\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    return arr;\n}\n\nfunction parseObject (state: State): [string|number|null, Record<string, number | string | boolean | IntArray>] {\n    let prefix: string|number|null = null;\n    const obj: Record<string, number | string | IntArray> = {};\n\n    if (state.char() !== '{') {\n        prefix = parseString(state);\n        if (prefix === null) {\n            prefix = parseNumber(state);\n        }\n        if (prefix === null) {\n            throwError(state, 'expected string or number');\n        }\n    }\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const keyword: string = parseKeyword(state);\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'Interval') {\n            const array = new Uint32Array(2);\n            obj[keyword] = parseArray(state, array, 0);\n        } else if (keyword === 'MinimumExtent' || keyword === 'MaximumExtent') {\n            const array = new Float32Array(3);\n            obj[keyword] = parseArray(state, array, 0);\n        } else {\n            obj[keyword] = parseArray(state) || parseString(state);\n            if (obj[keyword] === null) {\n                obj[keyword] = parseNumber(state);\n            }\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    return [prefix, obj];\n}\n\nfunction parseVersion (state: State, model: Model): void {\n    const [_unused, obj] = parseObject(state);\n\n    if (obj.FormatVersion) {\n        model.Version = obj.FormatVersion as number;\n    }\n}\n\nfunction parseModelInfo (state: State, model: Model): void {\n    const [name, obj] = parseObject(state);\n\n    model.Info = obj as unknown as ModelInfo;\n    model.Info.Name = name as string;\n}\n\nfunction parseSequences (state: State, model: Model): void {\n    parseNumber(state); // count, not used\n\n    strictParseSymbol(state, '{');\n\n    const res: Sequence[] = [];\n\n    while (state.char() !== '}') {\n        parseKeyword(state); // Anim\n\n        const [name, obj] = parseObject(state);\n        obj.Name = name;\n        obj.NonLooping = 'NonLooping' in obj;\n        obj.MoveSpeed = obj.MoveSpeed || 0;\n        obj.Rarity = obj.Rarity || 0;\n\n        res.push(obj as unknown as Sequence);\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.Sequences = res;\n}\n\nfunction parseTextures (state: State, model: Model): void {\n    const res = [];\n\n    parseNumber(state); // count, not used\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        parseKeyword(state); // Bitmap\n\n        const [_unused, obj] = parseObject(state);\n        obj.Flags = 0;\n        if ('WrapWidth' in obj) {\n            obj.Flags += TextureFlags.WrapWidth;\n            delete obj.WrapWidth;\n        }\n        if ('WrapHeight' in obj) {\n            obj.Flags += TextureFlags.WrapHeight;\n            delete obj.WrapHeight;\n        }\n\n        res.push(obj);\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.Textures = res;\n}\n\nenum AnimVectorType {\n    INT1,\n    FLOAT1,\n    FLOAT3,\n    FLOAT4\n}\n\nconst animVectorSize = {\n    [AnimVectorType.INT1]: 1,\n    [AnimVectorType.FLOAT1]: 1,\n    [AnimVectorType.FLOAT3]: 3,\n    [AnimVectorType.FLOAT4]: 4\n};\n\nfunction parseAnimKeyframe (state: State, frame: number, type: AnimVectorType, lineType: LineType): AnimKeyframe {\n    const res: AnimKeyframe = {\n        Frame: frame,\n        Vector: null\n    };\n\n    const Vector = type === AnimVectorType.INT1 ? Int32Array : Float32Array;\n    const itemCount = animVectorSize[type];\n\n    res.Vector = parseArrayOrSingleItem(state, new Vector(itemCount));\n\n    strictParseSymbol(state, ',');\n\n    if (lineType === LineType.Hermite || lineType === LineType.Bezier) {\n        parseKeyword(state); // InTan\n        res.InTan = parseArrayOrSingleItem(state, new Vector(itemCount));\n        strictParseSymbol(state, ',');\n\n        parseKeyword(state); // OutTan\n        res.OutTan = parseArrayOrSingleItem(state, new Vector(itemCount));\n        strictParseSymbol(state, ',');\n    }\n\n    return res;\n}\n\nfunction parseAnimVector (state: State, type: AnimVectorType): AnimVector {\n    const animVector: AnimVector = {\n        LineType: LineType.DontInterp,\n        GlobalSeqId: null,\n        Keys: []\n    };\n\n    parseNumber(state); // count, not used\n\n    strictParseSymbol(state, '{');\n\n    const lineType: string = parseKeyword(state);\n    if (lineType === 'DontInterp' || lineType === 'Linear' || lineType === 'Hermite' || lineType === 'Bezier') {\n        animVector.LineType = LineType[lineType];\n    }\n\n    strictParseSymbol(state, ',');\n\n    while (state.char() !== '}') {\n        const keyword = parseKeyword(state);\n\n        if (keyword === 'GlobalSeqId') {\n            animVector[keyword] = parseNumber(state);\n            strictParseSymbol(state, ',');\n        } else {\n            const frame = parseNumber(state);\n\n            if (frame === null) {\n                throwError(state, 'expected frame number or GlobalSeqId');\n            }\n\n            strictParseSymbol(state, ':');\n\n            animVector.Keys.push(parseAnimKeyframe(state, frame, type, animVector.LineType));\n        }\n    }\n\n    strictParseSymbol(state, '}');\n\n    return animVector;\n}\n\nfunction parseLayer (state: State, model: Model): Layer {\n    const res: Layer = {\n        Alpha: null,\n        TVertexAnimId: null,\n        Shading: 0,\n        CoordId: 0\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        let keyword = parseKeyword(state);\n        let isStatic = false;\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'static') {\n            isStatic = true;\n            keyword = parseKeyword(state);\n        }\n\n        if (!isStatic && (keyword === 'TextureID' || model.Version >= 1100 && keyword in LAYER_TEXTURE_NAME_MAP)) {\n            res[keyword] = parseAnimVector(state, AnimVectorType.INT1);\n        } else if (!isStatic && (keyword === 'Alpha')) {\n            res[keyword] = parseAnimVector(state, AnimVectorType.FLOAT1);\n        } else if (\n            keyword === 'Unshaded' || keyword === 'SphereEnvMap' || keyword === 'TwoSided' ||\n            keyword === 'Unfogged' || keyword === 'NoDepthTest' || keyword === 'NoDepthSet'\n        ) {\n            res.Shading |= LayerShading[keyword];\n        } else if (keyword === 'FilterMode') {\n            const val = parseKeyword(state);\n\n            if (\n                val === 'None' || val === 'Transparent' || val === 'Blend' || val === 'Additive' ||\n                val === 'AddAlpha' || val === 'Modulate' || val === 'Modulate2x'\n            ) {\n                res.FilterMode = FilterMode[val];\n            }\n        } else if (keyword === 'TVertexAnimId') {\n            res.TVertexAnimId = parseNumber(state);\n        } else if (model.Version >= 900 && keyword === 'EmissiveGain') {\n            if (isStatic) {\n                res[keyword] = parseNumber(state);\n            } else {\n                res[keyword] = parseAnimVector(state, AnimVectorType.FLOAT1);\n            }\n        } else if (model.Version >= 1000 && keyword === 'FresnelColor') {\n            if (isStatic) {\n                const array = new Float32Array(3);\n                res[keyword] = parseArray(state, array, 0) as Float32Array;\n            } else {\n                res[keyword] = parseAnimVector(state, AnimVectorType.FLOAT3);\n            }\n        } else if (model.Version >= 1000 && (keyword === 'FresnelOpacity' || keyword === 'FresnelTeamColor')) {\n            if (isStatic) {\n                res[keyword] = parseNumber(state);\n            } else {\n                res[keyword] = parseAnimVector(state, AnimVectorType.FLOAT1);\n            }\n        } else {\n            let val: string|number = parseNumber(state);\n\n            if (val === null) {\n                val = parseKeyword(state);\n            }\n\n            res[keyword] = val;\n        }\n\n        parseSymbol(state, ',');\n\n        parseComment(state);\n        parseSpace(state);\n    }\n\n    strictParseSymbol(state, '}');\n\n    return res;\n}\n\nfunction parseMaterials (state: State, model: Model): void {\n    const res = [];\n\n    parseNumber(state); // count, not used\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const obj = {\n            RenderMode: 0,\n            Layers: []\n        };\n\n        parseKeyword(state); // Material\n\n        strictParseSymbol(state, '{');\n\n        while (state.char() !== '}') {\n            const keyword = parseKeyword(state);\n\n            if (!keyword) {\n                throwError(state);\n            }\n\n            if (keyword === 'Layer') {\n                obj.Layers.push(parseLayer(state, model));\n            } else if (keyword === 'PriorityPlane' || keyword === 'RenderMode') {\n                obj[keyword] = parseNumber(state);\n            } else if (keyword === 'ConstantColor' || keyword === 'SortPrimsFarZ' || keyword === 'FullResolution') {\n                obj.RenderMode |= MaterialRenderMode[keyword];\n            } else if (model.Version >= 900 && model.Version <= 1100 && keyword === 'Shader') {\n                obj[keyword] = parseString(state);\n            } else {\n                throw new Error('Unknown material property ' + keyword);\n            }\n\n            parseSymbol(state, ',');\n        }\n\n        strictParseSymbol(state, '}');\n\n        res.push(obj);\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.Materials = res;\n}\n\nenum GeosetPartType {\n    INT,\n    FLOAT\n}\n\nfunction parseGeosetPart (state: State, countPerObj: number, type: GeosetPartType) {\n    const count = parseNumber(state);\n    const arr = new (type === GeosetPartType.FLOAT ? Float32Array : Uint8Array)(count * countPerObj);\n\n    strictParseSymbol(state, '{');\n\n    for (let index = 0; index < count; ++index) {\n        parseArray(state, arr, index * countPerObj);\n        strictParseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    return arr;\n}\n\nfunction parseGeoset (state: State, model: Model): void {\n    const res: Geoset = {\n        Vertices: null,\n        Normals: null,\n        TVertices: [],\n        VertexGroup: new Uint8Array(0),\n        Faces: null,\n        Groups: null,\n        TotalGroupsCount: null,\n        MinimumExtent: null,\n        MaximumExtent: null,\n        BoundsRadius: 0,\n        Anims: [],\n        MaterialID: null,\n        SelectionGroup: null,\n        Unselectable: false\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const keyword = parseKeyword(state);\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'Vertices' || keyword === 'Normals' || keyword === 'TVertices') {\n            let countPerObj = 3;\n\n            if (keyword === 'TVertices') {\n                countPerObj = 2;\n            }\n\n            const arr = parseGeosetPart(state, countPerObj, GeosetPartType.FLOAT) as Float32Array;\n\n            if (keyword === 'TVertices') {\n                res.TVertices.push(arr);\n            } else {\n                res[keyword] = arr;\n            }\n        } else if (keyword === 'VertexGroup') {\n            res[keyword] = new Uint8Array(res.Vertices.length / 3);\n\n            parseArray(state, res[keyword], 0);\n        } else if (keyword === 'Faces') {\n            const groupCount = parseNumber(state); // group count, always 1 in the official models\n            const indexCount = parseNumber(state);\n\n            let pos = 0;\n            res.Faces = new Uint16Array(indexCount);\n\n            strictParseSymbol(state, '{');\n            const keyword = parseKeyword(state);\n            if (keyword !== 'Triangles') {\n                throwError(state, 'unexpected faces type');\n            }\n            strictParseSymbol(state, '{');\n            for (let g = 0; g < groupCount; ++g) {\n                const count = parseArrayCounted(state, res.Faces, pos);\n                if (!count) {\n                    throwError(state, 'expected array');\n                }\n                pos += count;\n\n                parseSymbol(state, ',');\n            }\n\n            if (pos !== indexCount || indexCount % 3 !== 0) {\n                throwError(state, 'mismatched faces array');\n            }\n\n            strictParseSymbol(state, '}');\n            strictParseSymbol(state, '}');\n        } else if (keyword === 'Groups') {\n            const groups = [];\n            parseNumber(state); // groups count, unused\n            res.TotalGroupsCount = parseNumber(state); // summed in subarrays\n\n            strictParseSymbol(state, '{');\n\n            while (state.char() !== '}') {\n                parseKeyword(state); // Matrices\n\n                groups.push(parseArray(state));\n\n                parseSymbol(state, ',');\n            }\n\n            strictParseSymbol(state, '}');\n\n            res.Groups = groups;\n        } else if (keyword === 'MinimumExtent' || keyword === 'MaximumExtent') {\n            const arr = new Float32Array(3);\n            res[keyword] = parseArray(state, arr, 0) as Float32Array;\n            strictParseSymbol(state, ',');\n        } else if (keyword === 'BoundsRadius' || keyword === 'MaterialID' || keyword === 'SelectionGroup') {\n            res[keyword] = parseNumber(state);\n            strictParseSymbol(state, ',');\n        } else if (keyword === 'Anim') {\n            const [_unused, obj] = parseObject(state);\n\n            if (obj.Alpha === undefined) {\n                obj.Alpha = 1;\n            }\n\n            res.Anims.push(obj as unknown as GeosetAnimInfo);\n        } else if (keyword === 'Unselectable') {\n            res.Unselectable = true;\n            strictParseSymbol(state, ',');\n        } else if (model.Version >= 900) {\n            if (keyword === 'LevelOfDetail') {\n                res.LevelOfDetail = parseNumber(state);\n                strictParseSymbol(state, ',');\n            } else if (keyword === 'Name') {\n                res.Name = parseString(state);\n                strictParseSymbol(state, ',');\n            } else if (keyword === 'Tangents') {\n                res.Tangents = parseGeosetPart(state, 4, GeosetPartType.FLOAT) as Float32Array;\n            } else if (keyword === 'SkinWeights') {\n                res.SkinWeights = parseGeosetPart(state, 8, GeosetPartType.INT) as Uint8Array;\n            }\n        }\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.Geosets.push(res);\n}\n\nfunction parseGeosetAnim (state: State, model: Model): void {\n    const res: GeosetAnim = {\n        GeosetId: -1,\n        Alpha: 1,\n        Color: null,\n        Flags: 0\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        let keyword = parseKeyword(state);\n        let isStatic = false;\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'static') {\n            isStatic = true;\n            keyword = parseKeyword(state);\n        }\n\n        if (keyword === 'Alpha') {\n            if (isStatic) {\n                res.Alpha = parseNumber(state);\n            } else {\n                res.Alpha = parseAnimVector(state, AnimVectorType.FLOAT1);\n            }\n        } else if (keyword === 'Color') {\n            if (isStatic) {\n                const array = new Float32Array(3);\n                res.Color = parseArray(state, array, 0) as Float32Array;\n                res.Color.reverse();\n            } else {\n                res.Color = parseAnimVector(state, AnimVectorType.FLOAT3);\n                for (const key of res.Color.Keys) {\n                    key.Vector.reverse();\n                    if (key.InTan) {\n                        key.InTan.reverse();\n                        key.OutTan.reverse();\n                    }\n                }\n            }\n        } else if (keyword === 'DropShadow') {\n            res.Flags |= GeosetAnimFlags[keyword];\n        } else {\n            res[keyword] = parseNumber(state);\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.GeosetAnims.push(res);\n}\n\nfunction parseNode (state: State, type: string, model: Model): Node {\n    const name = parseString(state);\n\n    const node: Node = {\n        Name: name,\n        ObjectId: null,\n        Parent: null,\n        PivotPoint: null,\n        Flags: NodeType[type]\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const keyword = parseKeyword(state);\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'Translation' || keyword === 'Rotation' || keyword === 'Scaling' || keyword === 'Visibility') {\n            let vectorType: AnimVectorType = AnimVectorType.FLOAT3;\n            if (keyword === 'Rotation') {\n                vectorType = AnimVectorType.FLOAT4;\n            } else if (keyword === 'Visibility') {\n                vectorType = AnimVectorType.FLOAT1;\n            }\n            node[keyword] = parseAnimVector(state, vectorType);\n        } else if (keyword === 'BillboardedLockZ' || keyword === 'BillboardedLockY' || keyword === 'BillboardedLockX' ||\n            keyword === 'Billboarded' || keyword === 'CameraAnchored') {\n            node.Flags |= NodeFlags[keyword];\n        } else if (keyword === 'DontInherit') {\n            strictParseSymbol(state, '{');\n\n            const val = parseKeyword(state);\n\n            if (val === 'Translation') {\n                node.Flags |= NodeFlags.DontInheritTranslation;\n            } else if (val === 'Rotation') {\n                node.Flags |= NodeFlags.DontInheritRotation;\n            } else if (val === 'Scaling') {\n                node.Flags |= NodeFlags.DontInheritScaling;\n            }\n\n            strictParseSymbol(state, '}');\n        } else if (keyword === 'Path') {\n            node[keyword] = parseString(state);\n        } else {\n            let val = parseKeyword(state) || parseNumber(state);\n\n            if (keyword === 'GeosetId' && val === 'Multiple' ||\n                keyword === 'GeosetAnimId' && val === 'None') {\n                val = null;\n            }\n\n            node[keyword] = val;\n        }\n\n        parseSymbol(state, ',');\n        parseComment(state);\n        parseSpace(state);\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.Nodes[node.ObjectId] = node;\n\n    return node;\n}\n\nfunction parseBone (state: State, model: Model): void {\n    const node = parseNode(state, 'Bone', model);\n\n    model.Bones.push(node);\n}\n\nfunction parseHelper (state: State, model: Model): void {\n    const node = parseNode(state, 'Helper', model);\n\n    model.Helpers.push(node);\n}\n\nfunction parseAttachment (state: State, model: Model): void {\n    const node = parseNode(state, 'Attachment', model);\n\n    model.Attachments.push(node);\n}\n\nfunction parsePivotPoints (state: State, model: Model): void {\n    const count = parseNumber(state);\n\n    const res = [];\n\n    strictParseSymbol(state, '{');\n\n    for (let i = 0; i < count; ++i) {\n        res.push(parseArray(state, new Float32Array(3), 0));\n        strictParseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.PivotPoints = res;\n}\n\nfunction parseEventObject (state: State, model: Model): void {\n    const name = parseString(state);\n\n    const res: EventObject = {\n        Name: name,\n        ObjectId: null,\n        Parent: null,\n        PivotPoint: null,\n        EventTrack: null,\n        Flags: NodeType.EventObject\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const keyword = parseKeyword(state);\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'EventTrack') {\n            const count = parseNumber(state); // EventTrack count\n\n            res.EventTrack = parseArray(state, new Uint32Array(count), 0) as Uint32Array;\n        } else if (keyword === 'Translation' || keyword === 'Rotation' || keyword === 'Scaling') {\n            const type: AnimVectorType = keyword === 'Rotation' ? AnimVectorType.FLOAT4 : AnimVectorType.FLOAT3;\n\n            res[keyword] = parseAnimVector(state, type);\n        } else {\n            res[keyword] = parseNumber(state);\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.EventObjects.push(res);\n    model.Nodes[res.ObjectId] = res;\n}\n\nfunction parseCollisionShape (state: State, model: Model): void {\n    const name = parseString(state);\n\n    const res: CollisionShape = {\n        Name: name,\n        ObjectId: null,\n        Parent: null,\n        PivotPoint: null,\n        Shape: CollisionShapeType.Box,\n        Vertices: null,\n        Flags: NodeType.CollisionShape\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const keyword = parseKeyword(state);\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'Sphere') {\n            res.Shape = CollisionShapeType.Sphere;\n        } else if (keyword === 'Box') {\n            res.Shape = CollisionShapeType.Box;\n        } else if (keyword === 'Vertices') {\n            const count = parseNumber(state);\n            const vertices = new Float32Array(count * 3);\n\n            strictParseSymbol(state, '{');\n\n            for (let i = 0; i < count; ++i) {\n                parseArray(state, vertices, i * 3);\n                strictParseSymbol(state, ',');\n            }\n\n            strictParseSymbol(state, '}');\n\n            res.Vertices = vertices;\n        } else if (keyword === 'Translation' || keyword === 'Rotation' || keyword === 'Scaling') {\n            const type: AnimVectorType = keyword === 'Rotation' ? AnimVectorType.FLOAT4 : AnimVectorType.FLOAT3;\n            res[keyword] = parseAnimVector(state, type);\n        } else {\n            res[keyword] = parseNumber(state);\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.CollisionShapes.push(res);\n    model.Nodes[res.ObjectId] = res;\n}\n\nfunction parseGlobalSequences (state: State, model: Model): void {\n    const res = [];\n\n    const count = parseNumber(state);\n\n    strictParseSymbol(state, '{');\n\n    for (let i = 0; i < count; ++i) {\n        const keyword = parseKeyword(state);\n\n        if (keyword === 'Duration') {\n            res.push(parseNumber(state));\n        }\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.GlobalSequences = res;\n}\n\nfunction parseUnknownBlock (state: State): void {\n    let opened;\n    while (state.char() !== undefined && state.char() !== '{') {\n        ++state.pos;\n    }\n    opened = 1;\n    ++state.pos;\n\n    while (state.char() !== undefined && opened > 0) {\n        if (state.char() === '{') {\n            ++opened;\n        } else if (state.char() === '}') {\n            --opened;\n        }\n        ++state.pos;\n    }\n    parseSpace(state);\n}\n\nfunction parseParticleEmitter (state: State, model: Model): void {\n    const res: ParticleEmitter = {\n        ObjectId: null,\n        Parent: null,\n        Name: null,\n        Flags: 0\n    } as ParticleEmitter;\n\n    res.Name = parseString(state);\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        let keyword = parseKeyword(state);\n        let isStatic = false;\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'static') {\n            isStatic = true;\n            keyword = parseKeyword(state);\n        }\n\n        if (keyword === 'ObjectId' || keyword === 'Parent') {\n            res[keyword] = parseNumber(state);\n        } else if (keyword === 'EmitterUsesMDL' || keyword === 'EmitterUsesTGA') {\n            res.Flags |= ParticleEmitterFlags[keyword];\n        } else if (!isStatic && (keyword === 'Visibility' || keyword === 'Translation' || keyword === 'Rotation' ||\n            keyword === 'Scaling' || keyword === 'EmissionRate' || keyword === 'Gravity' || keyword === 'Longitude' ||\n            keyword === 'Latitude')) {\n            let type: AnimVectorType = AnimVectorType.FLOAT3;\n            if (keyword === 'Visibility' || keyword === 'EmissionRate' || keyword === 'Gravity' ||\n                keyword === 'Longitude' || keyword === 'Latitude') {\n                type = AnimVectorType.FLOAT1;\n            } else if (keyword === 'Rotation') {\n                type = AnimVectorType.FLOAT4;\n            }\n            res[keyword] = parseAnimVector(state, type);\n        } else if (keyword === 'Particle') {\n            strictParseSymbol(state, '{');\n\n            while (state.char() !== '}') {\n                let keyword2 = parseKeyword(state);\n                let isStatic2 = false;\n\n                if (keyword2 === 'static') {\n                    isStatic2 = true;\n                    keyword2 = parseKeyword(state);\n                }\n\n                if (!isStatic2 && (keyword2 === 'LifeSpan' || keyword2 === 'InitVelocity')) {\n                    res[keyword2] = parseAnimVector(state, AnimVectorType.FLOAT1);\n                } else if (keyword2 === 'LifeSpan' || keyword2 === 'InitVelocity') {\n                    res[keyword2] = parseNumber(state);\n                } else if (keyword2 === 'Path') {\n                    res.Path = parseString(state);\n                }\n\n                parseSymbol(state, ',');\n            }\n\n            strictParseSymbol(state, '}');\n        } else {\n            res[keyword] = parseNumber(state);\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.ParticleEmitters.push(res);\n}\n\nfunction parseParticleEmitter2 (state: State, model: Model): void {\n    const name = parseString(state);\n\n    const res: ParticleEmitter2 = {\n        Name: name,\n        ObjectId: null,\n        Parent: null,\n        PivotPoint: null,\n        Flags: NodeType.ParticleEmitter,\n        FrameFlags: 0\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        let keyword = parseKeyword(state);\n        let isStatic = false;\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'static') {\n            isStatic = true;\n            keyword = parseKeyword(state);\n        }\n\n        if (!isStatic && (keyword === 'Speed' || keyword === 'Latitude' || keyword === 'Visibility' ||\n            keyword === 'EmissionRate' || keyword === 'Width' || keyword === 'Length' || keyword === 'Translation' ||\n            keyword === 'Rotation' || keyword === 'Scaling' || keyword === 'Gravity' || keyword === 'Variation')) {\n            let type: AnimVectorType = AnimVectorType.FLOAT3;\n            switch (keyword) {\n                case 'Rotation':\n                    type = AnimVectorType.FLOAT4;\n                    break;\n                case 'Speed':\n                case 'Latitude':\n                case 'Visibility':\n                case 'EmissionRate':\n                case 'Width':\n                case 'Length':\n                case 'Gravity':\n                case 'Variation':\n                    type = AnimVectorType.FLOAT1;\n                    break;\n            }\n            res[keyword] = parseAnimVector(state, type);\n        } else if (keyword === 'Variation' || keyword === 'Gravity' || keyword === 'ReplaceableId' || keyword === 'PriorityPlane') {\n            res[keyword] = parseNumber(state);\n        } else if (keyword === 'SortPrimsFarZ' || keyword === 'Unshaded' || keyword === 'LineEmitter' ||\n            keyword === 'Unfogged' || keyword === 'ModelSpace' || keyword === 'XYQuad') {\n            res.Flags |= ParticleEmitter2Flags[keyword];\n        } else if (keyword === 'Both') {\n            res.FrameFlags |= ParticleEmitter2FramesFlags.Head | ParticleEmitter2FramesFlags.Tail;\n        } else if (keyword === 'Head' || keyword === 'Tail') {\n            res.FrameFlags |= ParticleEmitter2FramesFlags[keyword];\n        } else if (keyword === 'Squirt') {\n            res[keyword] = true;\n        } else if (keyword === 'DontInherit') {\n            strictParseSymbol(state, '{');\n\n            const val = parseKeyword(state);\n\n            if (val === 'Translation') {\n                res.Flags |= NodeFlags.DontInheritTranslation;\n            } else if (val === 'Rotation') {\n                res.Flags |= NodeFlags.DontInheritRotation;\n            } else if (val === 'Scaling') {\n                res.Flags |= NodeFlags.DontInheritScaling;\n            }\n\n            strictParseSymbol(state, '}');\n        } else if (keyword === 'SegmentColor') {\n            const colors = [];\n\n            strictParseSymbol(state, '{');\n            while (state.char() !== '}') {\n                parseKeyword(state); // Color\n\n                const colorArr = new Float32Array(3);\n                parseArray(state, colorArr, 0);\n\n                // bgr order, inverse from mdx\n                const temp = colorArr[0];\n                colorArr[0] = colorArr[2];\n                colorArr[2] = temp;\n                colors.push(colorArr);\n\n                parseSymbol(state, ',');\n            }\n            strictParseSymbol(state, '}');\n\n            res.SegmentColor = colors;\n        } else if (keyword === 'Alpha') {\n            res.Alpha = new Uint8Array(3);\n            parseArray(state, res.Alpha, 0);\n        } else if (keyword === 'ParticleScaling') {\n            res[keyword] = new Float32Array(3);\n            parseArray(state, res[keyword], 0);\n        } else if (keyword === 'LifeSpanUVAnim' || keyword === 'DecayUVAnim' || keyword === 'TailUVAnim' ||\n                keyword === 'TailDecayUVAnim') {\n            res[keyword] = new Uint32Array(3);\n            parseArray(state, res[keyword], 0);\n        } else if (keyword === 'Transparent' || keyword === 'Blend' || keyword === 'Additive' ||\n                keyword === 'AlphaKey' || keyword === 'Modulate' || keyword === 'Modulate2x') {\n            res.FilterMode = ParticleEmitter2FilterMode[keyword];\n        } else {\n            res[keyword] = parseNumber(state);\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.ParticleEmitters2.push(res);\n    model.Nodes[res.ObjectId] = res;\n}\n\nfunction parseCamera (state: State, model: Model): void {\n    const res: Camera = {\n        Name: null,\n        Position: null,\n        FieldOfView: 0,\n        NearClip: 0,\n        FarClip: 0,\n        TargetPosition: null\n    };\n\n    res.Name = parseString(state);\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const keyword = parseKeyword(state);\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'Position') {\n            res.Position = new Float32Array(3);\n            parseArray(state, res.Position, 0);\n        } else if (keyword === 'FieldOfView' || keyword === 'NearClip' || keyword === 'FarClip') {\n            res[keyword] = parseNumber(state);\n        } else if (keyword === 'Target') {\n            strictParseSymbol(state, '{');\n\n            while (state.char() !== '}') {\n                const keyword2 = parseKeyword(state);\n\n                if (keyword2 === 'Position') {\n                    res.TargetPosition = new Float32Array(3);\n                    parseArray(state, res.TargetPosition, 0);\n                } else if (keyword2 === 'Translation') {\n                    res.TargetTranslation = parseAnimVector(state, AnimVectorType.FLOAT3);\n                }\n\n                parseSymbol(state, ',');\n            }\n\n            strictParseSymbol(state, '}');\n        } else if (keyword === 'Translation' || keyword === 'Rotation') {\n            res[keyword] = parseAnimVector(state, keyword === 'Rotation' ?\n                AnimVectorType.FLOAT1 :\n                AnimVectorType.FLOAT3\n            );\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.Cameras.push(res);\n}\n\nfunction parseLight (state: State, model: Model): void {\n    const name = parseString(state);\n\n    const res: Light = {\n        Name: name,\n        ObjectId: null,\n        Parent: null,\n        PivotPoint: null,\n        Flags: NodeType.Light,\n        LightType: 0\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        let keyword = parseKeyword(state);\n        let isStatic = false;\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'static') {\n            isStatic = true;\n            keyword = parseKeyword(state);\n        }\n\n        if (!isStatic && (keyword === 'Visibility' || keyword === 'Color' || keyword === 'Intensity' ||\n            keyword === 'AmbIntensity' || keyword === 'AmbColor' || keyword === 'Translation' ||\n            keyword === 'Rotation' || keyword === 'Scaling' || keyword === 'AttenuationStart' ||\n            keyword === 'AttenuationEnd')) {\n            let type: AnimVectorType = AnimVectorType.FLOAT3;\n            switch (keyword) {\n                case 'Rotation':\n                    type = AnimVectorType.FLOAT4;\n                    break;\n                case 'Visibility':\n                case 'Intensity':\n                case 'AmbIntensity':\n                case 'AttenuationStart':\n                case 'AttenuationEnd':\n                    type = AnimVectorType.FLOAT1;\n                    break;\n            }\n            res[keyword] = parseAnimVector(state, type);\n            if (keyword === 'Color' || keyword === 'AmbColor') {\n                for (const key of (res[keyword] as AnimVector).Keys) {\n                    key.Vector.reverse();\n                    if (key.InTan) {\n                        key.InTan.reverse();\n                        key.OutTan.reverse();\n                    }\n                }\n            }\n        } else if (keyword === 'Omnidirectional' || keyword === 'Directional' || keyword === 'Ambient') {\n            res.LightType = LightType[keyword];\n        } else if (keyword === 'Color' || keyword === 'AmbColor') {\n            const color = new Float32Array(3);\n            parseArray(state, color, 0);\n\n            // bgr order, inverse from mdx\n            const temp = color[0];\n            color[0] = color[2];\n            color[2] = temp;\n\n            res[keyword] = color;\n        } else {\n            res[keyword] = parseNumber(state);\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.Lights.push(res);\n    model.Nodes[res.ObjectId] = res;\n}\n\nfunction parseTextureAnims (state: State, model: Model): void {\n    const res = [];\n\n    parseNumber(state); // count, not used\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const obj: TVertexAnim = {};\n\n        parseKeyword(state); // TVertexAnim\n\n        strictParseSymbol(state, '{');\n\n        while (state.char() !== '}') {\n            const keyword = parseKeyword(state);\n\n            if (!keyword) {\n                throwError(state);\n            }\n\n            if (keyword === 'Translation' || keyword === 'Rotation' || keyword === 'Scaling') {\n                const type: AnimVectorType = keyword === 'Rotation' ? AnimVectorType.FLOAT4 : AnimVectorType.FLOAT3;\n                obj[keyword] = parseAnimVector(state, type);\n            } else {\n                throw new Error('Unknown texture anim property ' + keyword);\n            }\n\n            parseSymbol(state, ',');\n        }\n\n        strictParseSymbol(state, '}');\n\n        res.push(obj);\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.TextureAnims = res;\n}\n\nfunction parseRibbonEmitter (state: State, model: Model): void {\n    const name = parseString(state);\n\n    const res: RibbonEmitter = {\n        Name: name,\n        ObjectId: null,\n        Parent: null,\n        PivotPoint: null,\n        Flags: NodeType.RibbonEmitter,\n        HeightAbove: null,\n        HeightBelow: null,\n        Alpha: null,\n        Color: null,\n        LifeSpan: null,\n        TextureSlot: null,\n        EmissionRate: null,\n        Rows: null,\n        Columns: null,\n        MaterialID: 0,\n        Gravity: null,\n        Visibility: null\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        let keyword = parseKeyword(state);\n        let isStatic = false;\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'static') {\n            isStatic = true;\n            keyword = parseKeyword(state);\n        }\n\n        if (!isStatic && (keyword === 'Visibility' || keyword === 'HeightAbove' || keyword === 'HeightBelow' ||\n            keyword === 'Translation' || keyword === 'Rotation' || keyword === 'Scaling' || keyword === 'Alpha' ||\n            keyword === 'TextureSlot')) {\n            let type: AnimVectorType = AnimVectorType.FLOAT3;\n            switch (keyword) {\n                case 'Rotation':\n                    type = AnimVectorType.FLOAT4;\n                    break;\n                case 'Visibility':\n                case 'HeightAbove':\n                case 'HeightBelow':\n                case 'Alpha':\n                    type = AnimVectorType.FLOAT1;\n                    break;\n                case 'TextureSlot':\n                    type = AnimVectorType.INT1;\n                    break;\n            }\n            res[keyword] = parseAnimVector(state, type);\n        } else if (keyword === 'Color') {\n            const color = new Float32Array(3);\n            parseArray(state, color, 0);\n\n            // bgr order, inverse from mdx\n            const temp = color[0];\n            color[0] = color[2];\n            color[2] = temp;\n\n            res[keyword] = color;\n        } else {\n            res[keyword] = parseNumber(state);\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.RibbonEmitters.push(res);\n    model.Nodes[res.ObjectId] = res;\n}\n\nfunction parseFaceFX (state: State, model: Model): void {\n    if (model.Version < 900) {\n        throwError(state, 'Unexpected model chunk FaceFX');\n    }\n\n    const name = parseString(state);\n\n    const res: FaceFX = {\n        Name: name,\n        Path: ''\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        const keyword = parseKeyword(state);\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'Path') {\n            res.Path = parseString(state);\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.FaceFX = model.FaceFX || [];\n    model.FaceFX.push(res);\n}\n\nfunction parseBindPose (state: State, model: Model): void {\n    if (model.Version < 900) {\n        throwError(state, 'Unexpected model chunk BindPose');\n    }\n\n    const res: BindPose = {\n        Matrices: []\n    };\n\n    strictParseSymbol(state, '{');\n\n    parseKeyword(state); // Matrices\n\n    const count = parseNumber(state);\n\n    strictParseSymbol(state, '{');\n\n    for (let i = 0; i < count; ++i) {\n        const matrix = new Float32Array(12);\n        parseArray(state, matrix, 0);\n        parseSymbol(state, ',');\n        res.Matrices.push(matrix);\n    }\n\n    strictParseSymbol(state, '}');\n    strictParseSymbol(state, '}');\n\n    model.BindPoses = model.BindPoses || [];\n    model.BindPoses.push(res);\n}\n\nfunction parseParticleEmitterPopcorn (state: State, model: Model): void {\n    if (model.Version < 900) {\n        throwError(state, 'Unexpected model chunk ParticleEmitterPopcorn');\n    }\n\n    const name = parseString(state);\n\n    const res: ParticleEmitterPopcorn = {\n        Name: name,\n        ObjectId: null,\n        Parent: null,\n        PivotPoint: null,\n        Flags: NodeType.ParticleEmitter\n    };\n\n    strictParseSymbol(state, '{');\n\n    while (state.char() !== '}') {\n        let keyword = parseKeyword(state);\n        let isStatic = false;\n\n        if (!keyword) {\n            throwError(state);\n        }\n\n        if (keyword === 'static') {\n            isStatic = true;\n            keyword = parseKeyword(state);\n        }\n\n        if (\n            !isStatic && (\n                keyword === 'LifeSpan' || keyword === 'EmissionRate' || keyword === 'Speed' ||\n                keyword === 'Color' || keyword === 'Alpha' || keyword === 'Visibility' ||\n                keyword === 'Rotation' || keyword === 'Scaling' || keyword === 'Translation'\n            )\n        ) {\n            let type: AnimVectorType = AnimVectorType.FLOAT3;\n            switch (keyword) {\n                case 'LifeSpan':\n                case 'EmissionRate':\n                case 'Speed':\n                case 'Alpha':\n                case 'Visibility':\n                    type = AnimVectorType.FLOAT1;\n                    break;\n            }\n            res[keyword] = parseAnimVector(state, type);\n        } else if (keyword === 'LifeSpan' || keyword === 'EmissionRate' || keyword === 'Speed' || keyword === 'Alpha') {\n            res[keyword] = parseNumber(state);\n        } else if (keyword === 'Color') {\n            const array = new Float32Array(3);\n            res[keyword] = parseArray(state, array, 0) as Float32Array;\n        } else if (keyword === 'ReplaceableId') {\n            res[keyword] = parseNumber(state);\n        } else if (keyword === 'Path' || keyword === 'AnimVisibilityGuide') {\n            res[keyword] = parseString(state);\n        } else if (keyword === 'Unshaded' || keyword === 'SortPrimsFarZ' || keyword === 'Unfogged') {\n            if (keyword === 'Unshaded') {\n                res.Flags |= ParticleEmitterPopcornFlags.Unshaded;\n            } else if (keyword === 'Unfogged') {\n                res.Flags |= ParticleEmitterPopcornFlags.Unfogged;\n            } else if (keyword === 'SortPrimsFarZ') {\n                res.Flags |= ParticleEmitterPopcornFlags.SortPrimsFarZ;\n            }\n        } else {\n            res[keyword] = parseNumber(state);\n        }\n\n        parseSymbol(state, ',');\n    }\n\n    strictParseSymbol(state, '}');\n\n    model.ParticleEmitterPopcorns = model.ParticleEmitterPopcorns || [];\n    model.ParticleEmitterPopcorns.push(res);\n    model.Nodes[res.ObjectId] = res;\n}\n\nconst parsers = {\n    Version: parseVersion,\n    Model: parseModelInfo,\n    Sequences: parseSequences,\n    Textures: parseTextures,\n    Materials: parseMaterials,\n    Geoset: parseGeoset,\n    GeosetAnim: parseGeosetAnim,\n    Bone: parseBone,\n    Helper: parseHelper,\n    Attachment: parseAttachment,\n    PivotPoints: parsePivotPoints,\n    EventObject: parseEventObject,\n    CollisionShape: parseCollisionShape,\n    GlobalSequences: parseGlobalSequences,\n    ParticleEmitter: parseParticleEmitter,\n    ParticleEmitter2: parseParticleEmitter2,\n    Camera: parseCamera,\n    Light: parseLight,\n    TextureAnims: parseTextureAnims,\n    RibbonEmitter: parseRibbonEmitter,\n    FaceFX: parseFaceFX,\n    BindPose: parseBindPose,\n    ParticleEmitterPopcorn: parseParticleEmitterPopcorn\n};\n\nexport function parse (str: string): Model {\n    const state = new State(str);\n    const model: Model = {\n        // default\n        Version: 800,\n        Info: {\n            Name: '',\n            MinimumExtent: null,\n            MaximumExtent: null,\n            BoundsRadius: 0,\n            BlendTime: 150\n        },\n        Sequences: [],\n        GlobalSequences: [],\n        Textures: [],\n        Materials: [],\n        TextureAnims: [],\n        Geosets: [],\n        GeosetAnims: [],\n        Bones: [],\n        Helpers: [],\n        Attachments: [],\n        EventObjects: [],\n        ParticleEmitters: [],\n        ParticleEmitters2: [],\n        Cameras: [],\n        Lights: [],\n        RibbonEmitters: [],\n        CollisionShapes: [],\n        PivotPoints: [],\n        Nodes: []\n    };\n\n    while (state.pos < state.str.length) {\n        while (parseComment(state));\n        const keyword = parseKeyword(state);\n\n        if (keyword) {\n            if (keyword in parsers) {\n                parsers[keyword](state, model);\n            } else {\n                parseUnknownBlock(state);\n            }\n        } else {\n            break;\n        }\n    }\n\n    for (let i = 0; i < model.Nodes.length; ++i) {\n        if (model.PivotPoints[i]) {\n            model.Nodes[i].PivotPoint = model.PivotPoints[i];\n        }\n    }\n\n    return model;\n}\n","import {\n    Model, Sequence, Material, Layer, AnimVector, AnimKeyframe, LineType, Texture, Geoset,\n    GeosetAnimInfo, GeosetAnim, Node, Bone, Helper, Attachment, EventObject, CollisionShape, CollisionShapeType,\n    ParticleEmitter2, ParticleEmitter2FramesFlags, Camera, Light, TVertexAnim, RibbonEmitter, ParticleEmitter, FaceFX, BindPose, ParticleEmitterPopcorn\n} from '../model';\nimport { LAYER_TEXTURE_ID_MAP } from '../renderer/util';\n\nconst BIG_ENDIAN = true;\nconst NONE = -1;\n\nenum AnimVectorType {\n    INT1,\n    FLOAT1,\n    FLOAT3,\n    FLOAT4\n}\n\nconst animVectorSize = {\n    [AnimVectorType.INT1]: 1,\n    [AnimVectorType.FLOAT1]: 1,\n    [AnimVectorType.FLOAT3]: 3,\n    [AnimVectorType.FLOAT4]: 4\n};\n\nclass State {\n    // pos in bytes\n    public pos: number;\n    public length: number;\n\n    private readonly ab: ArrayBuffer;\n    private readonly view: DataView;\n    private readonly uint: Uint8Array;\n\n    constructor (arrayBuffer: ArrayBuffer) {\n        this.ab = arrayBuffer;\n        this.pos = 0;\n        this.length = arrayBuffer.byteLength;\n\n        this.view = new DataView(this.ab);\n        this.uint = new Uint8Array(this.ab);\n    }\n\n    public keyword (): string {\n        const res = String.fromCharCode(\n            this.uint[this.pos],\n            this.uint[this.pos + 1],\n            this.uint[this.pos + 2],\n            this.uint[this.pos + 3]\n        );\n\n        this.pos += 4;\n\n        return res;\n    }\n\n    public expectKeyword (keyword: string, errorText: string): void {\n        const curKeyword = this.keyword();\n        if (curKeyword !== keyword) {\n            throw new Error(errorText);\n        }\n    }\n\n    public uint8 (): number {\n        return this.view.getUint8(this.pos++);\n    }\n\n    public uint16 (): number {\n        const res = this.view.getUint16(this.pos, BIG_ENDIAN);\n\n        this.pos += 2;\n\n        return res;\n    }\n\n    public int32 (): number {\n        const res = this.view.getInt32(this.pos, BIG_ENDIAN);\n\n        this.pos += 4;\n\n        return res;\n    }\n\n    public float32 (): number {\n        const res = this.view.getFloat32(this.pos, BIG_ENDIAN);\n\n        this.pos += 4;\n\n        return res;\n    }\n\n    public float32Array (len: number): Float32Array {\n        const res = new Float32Array(len);\n\n        for (let i = 0; i < len; ++i) {\n            res[i] = this.float32();\n        }\n\n        return res;\n    }\n\n    public uint8Array (len: number): Uint8Array {\n        const res = new Uint8Array(len);\n\n        for (let i = 0; i < len; ++i) {\n            res[i] = this.uint8();\n        }\n\n        return res;\n    }\n\n    public str (length: number) {\n        // actual string length\n        // data may consist of ['a', 'b', 'c', 0, 0, 0]\n        let stringLength = length;\n\n        while (this.uint[this.pos + stringLength - 1] === 0 && stringLength > 0) {\n            --stringLength;\n        }\n\n        // ??\n        // TS2461:Type 'Uint8Array' is not an array type.\n        // let res = String.fromCharCode(...this.uint.slice(this.pos, this.pos + length));\n        // eslint-disable-next-line prefer-spread\n        const res = String.fromCharCode.apply(String, this.uint.slice(this.pos, this.pos + stringLength));\n\n        this.pos += length;\n\n        return res;\n    }\n\n    public animVector (type: AnimVectorType): AnimVector {\n        const res: AnimVector = {\n            Keys: []\n        } as AnimVector;\n\n        const isInt = type === AnimVectorType.INT1;\n\n        const vectorSize = animVectorSize[type];\n\n        const keysCount = this.int32();\n        res.LineType = this.int32();\n        res.GlobalSeqId = this.int32();\n\n        if (res.GlobalSeqId === NONE) {\n            res.GlobalSeqId = null;\n        }\n\n        for (let i = 0; i < keysCount; ++i) {\n            const animKeyFrame: AnimKeyframe = {} as AnimKeyframe;\n\n            animKeyFrame.Frame = this.int32();\n\n            if (isInt) {\n                animKeyFrame.Vector = new Int32Array(vectorSize);\n            } else {\n                animKeyFrame.Vector = new Float32Array(vectorSize);\n            }\n            for (let j = 0; j < vectorSize; ++j) {\n                if (isInt) {\n                    animKeyFrame.Vector[j] = this.int32();\n                } else {\n                    animKeyFrame.Vector[j] = this.float32();\n                }\n            }\n\n            if (res.LineType === LineType.Hermite || res.LineType === LineType.Bezier) {\n                for (const part of ['InTan', 'OutTan']) {\n                    animKeyFrame[part] = new Float32Array(vectorSize);\n                    for (let j = 0; j < vectorSize; ++j) {\n                        if (isInt) {\n                            animKeyFrame[part][j] = this.int32();\n                        } else {\n                            animKeyFrame[part][j] = this.float32();\n                        }\n                    }\n                }\n            }\n\n            res.Keys.push(animKeyFrame);\n        }\n\n        return res;\n    }\n}\n\ninterface ObjWithExtent {\n    BoundsRadius: number;\n    MinimumExtent: Float32Array;\n    MaximumExtent: Float32Array;\n}\n\nfunction parseExtent (obj: ObjWithExtent, state: State) {\n    obj.BoundsRadius = state.float32();\n\n    for (const key of ['MinimumExtent', 'MaximumExtent']) {\n        obj[key] = new Float32Array(3);\n        for (let i = 0; i < 3; ++i) {\n            obj[key][i] = state.float32();\n        }\n    }\n}\n\nfunction parseVersion (model: Model, state: State): void {\n    model.Version = state.int32();\n}\n\nconst MODEL_NAME_LENGTH = 0x150;\nfunction parseModelInfo (model: Model, state: State): void {\n    model.Info.Name = state.str(MODEL_NAME_LENGTH);\n    state.int32(); // unknown 4-byte sequence\n    parseExtent(model.Info, state);\n    model.Info.BlendTime = state.int32();\n}\n\nconst MODEL_SEQUENCE_NAME_LENGTH = 0x50;\nfunction parseSequences (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const name = state.str(MODEL_SEQUENCE_NAME_LENGTH);\n\n        const sequence: Sequence = {} as Sequence;\n\n        sequence.Name = name;\n\n        const interval = new Uint32Array(2);\n        interval[0] = state.int32();\n        interval[1] = state.int32();\n        sequence.Interval = interval;\n\n        sequence.MoveSpeed = state.float32();\n        sequence.NonLooping = state.int32() > 0;\n        sequence.Rarity = state.float32();\n        state.int32(); // unknown 4-byte sequence (syncPoint?)\n\n        parseExtent(sequence, state);\n\n        model.Sequences.push(sequence);\n    }\n}\n\nfunction parseMaterials (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        state.int32(); // material size inclusive\n\n        const material: Material = {\n            Layers: []\n        } as Material;\n\n        material.PriorityPlane = state.int32();\n        material.RenderMode = state.int32();\n\n        if (model.Version >= 900 && model.Version < 1100) {\n            material.Shader = state.str(80);\n        }\n\n        state.expectKeyword('LAYS', 'Incorrect materials format');\n\n        const layersCount = state.int32();\n\n        for (let i = 0; i < layersCount; ++i) {\n            const startPos2 = state.pos;\n            const size2 = state.int32();\n\n            const layer: Layer = {} as Layer;\n\n            layer.FilterMode = state.int32();\n            layer.Shading = state.int32();\n            layer.TextureID = state.int32();\n            layer.TVertexAnimId = state.int32();\n            if (layer.TVertexAnimId === NONE) {\n                layer.TVertexAnimId = null;\n            }\n            layer.CoordId = state.int32();\n            layer.Alpha = state.float32();\n\n            if (model.Version >= 900) {\n                layer.EmissiveGain = state.float32();\n\n                if (model.Version >= 1000) {\n                    layer.FresnelColor = state.float32Array(3);\n                    layer.FresnelOpacity = state.float32();\n                    layer.FresnelTeamColor = state.float32();\n                }\n            }\n\n            if (model.Version >= 1100) {\n                layer.ShaderTypeId = state.int32(); // hd flag\n                const textureCount = state.int32();\n\n                for (let j = 0; j < textureCount; ++j) {\n                    const textureId = state.int32(); //layer_texture.id\n                    // const textureType = state.int32();\n                    state.int32();\n                    const textureType = j;\n\n                    const keyword = state.keyword();\n                    if (keyword === 'KMTF') {\n                        layer[LAYER_TEXTURE_ID_MAP[textureType]] = state.animVector(AnimVectorType.INT1);\n                    } else {\n                        layer[LAYER_TEXTURE_ID_MAP[textureType]] = textureId;\n                        state.pos -= 4;\n                    }\n                }\n            }\n\n            while (state.pos < startPos2 + size2) {\n                const keyword = state.keyword();\n\n                if (keyword === 'KMTA') {\n                    layer.Alpha = state.animVector(AnimVectorType.FLOAT1);\n                } else if (keyword === 'KMTF') {\n                    layer.TextureID = state.animVector(AnimVectorType.INT1);\n                } else if (keyword === 'KMTE' && model.Version >= 900) {\n                    layer.EmissiveGain = state.animVector(AnimVectorType.FLOAT1);\n                } else if (keyword === 'KFC3' && model.Version >= 1000) {\n                    layer.FresnelColor = state.animVector(AnimVectorType.FLOAT3);\n                } else if (keyword === 'KFCA' && model.Version >= 1000) {\n                    layer.FresnelOpacity = state.animVector(AnimVectorType.FLOAT1);\n                } else if (keyword === 'KFTC' && model.Version >= 1000) {\n                    layer.FresnelTeamColor = state.animVector(AnimVectorType.FLOAT1);\n                } else {\n                    throw new Error('Unknown layer chunk data ' + keyword);\n                }\n            }\n\n            material.Layers.push(layer);\n        }\n\n        model.Materials.push(material);\n    }\n}\n\nconst MODEL_TEXTURE_PATH_LENGTH = 0x100;\nfunction parseTextures (model: Model, state: State, size: number) {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const texture: Texture = {} as Texture;\n\n        texture.ReplaceableId = state.int32();\n        texture.Image = state.str(MODEL_TEXTURE_PATH_LENGTH);\n        state.int32(); // unknown 4-byte sequence\n        texture.Flags = state.int32();\n\n        model.Textures.push(texture);\n    }\n}\n\nfunction parseGeosets (model: Model, state: State, size: number) {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const geoset: Geoset = {} as Geoset;\n\n        state.int32(); // geoset size, not used\n\n        state.expectKeyword('VRTX', 'Incorrect geosets format');\n        const verticesCount = state.int32();\n        geoset.Vertices = new Float32Array(verticesCount * 3);\n        for (let i = 0; i < verticesCount * 3; ++i) {\n            geoset.Vertices[i] = state.float32();\n        }\n\n        state.expectKeyword('NRMS', 'Incorrect geosets format');\n        const normalsCount = state.int32();\n        geoset.Normals = new Float32Array(normalsCount * 3);\n        for (let i = 0; i < normalsCount * 3; ++i) {\n            geoset.Normals[i] = state.float32();\n        }\n\n        state.expectKeyword('PTYP', 'Incorrect geosets format');\n        const primitiveCount = state.int32();\n        for (let i = 0; i < primitiveCount; ++i) {\n            if (state.int32() !== 4) {\n                throw new Error('Incorrect geosets format');\n            }\n        }\n\n        state.expectKeyword('PCNT', 'Incorrect geosets format');\n        const faceGroupCount = state.int32();\n        for (let i = 0; i < faceGroupCount; ++i) {\n            state.int32();\n        }\n\n        state.expectKeyword('PVTX', 'Incorrect geosets format');\n        const indicesCount = state.int32();\n        geoset.Faces = new Uint16Array(indicesCount);\n        for (let i = 0; i < indicesCount; ++i) {\n            geoset.Faces[i] = state.uint16();\n        }\n\n        state.expectKeyword('GNDX', 'Incorrect geosets format');\n        const verticesGroupCount = state.int32();\n        geoset.VertexGroup = new Uint8Array(verticesGroupCount);\n        for (let i = 0; i < verticesGroupCount; ++i) {\n            geoset.VertexGroup[i] = state.uint8();\n        }\n\n        state.expectKeyword('MTGC', 'Incorrect geosets format');\n        const groupsCount = state.int32();\n        geoset.Groups = [];\n        for (let i = 0; i < groupsCount; ++i) {\n            // new Array(array length)\n            geoset.Groups[i] = new Array(state.int32());\n        }\n\n        state.expectKeyword('MATS', 'Incorrect geosets format');\n        geoset.TotalGroupsCount = state.int32();\n        let groupIndex = 0;\n        let groupCounter = 0;\n        for (let i = 0; i < geoset.TotalGroupsCount; ++i) {\n            if (groupIndex >= geoset.Groups[groupCounter].length) {\n                groupIndex = 0;\n                groupCounter++;\n            }\n            geoset.Groups[groupCounter][groupIndex++] = state.int32();\n        }\n\n        geoset.MaterialID = state.int32();\n        geoset.SelectionGroup = state.int32();\n        geoset.Unselectable = state.int32() > 0;\n\n        if (model.Version >= 900) {\n            geoset.LevelOfDetail = state.int32();\n            geoset.Name = state.str(80);\n        }\n\n        parseExtent(geoset, state);\n\n        const geosetAnimCount = state.int32();\n        geoset.Anims = [];\n\n        for (let i = 0; i < geosetAnimCount; ++i) {\n            const geosetAnim: GeosetAnimInfo = {} as GeosetAnimInfo;\n\n            parseExtent(geosetAnim, state);\n\n            geoset.Anims.push(geosetAnim);\n        }\n\n        let keyword = state.keyword();\n        if (model.Version >= 900) {\n            // eslint-disable-next-line no-constant-condition\n            while (1) {\n                if (state.pos >= state.length) {\n                    throw new Error('Unexpected EOF');\n                }\n                if (keyword === 'TANG') {\n                    if (geoset.Tangents) {\n                        throw new Error('Incorrect geoset, multiple Tangents');\n                    }\n                    const len = state.int32();\n                    geoset.Tangents = state.float32Array(len * 4);\n                } else if (keyword === 'SKIN') {\n                    if (geoset.SkinWeights) {\n                        throw new Error('Incorrect geoset, multiple SkinWeights');\n                    }\n                    const len = state.int32();\n                    geoset.SkinWeights = state.uint8Array(len);\n                } else if (keyword === 'UVAS') {\n                    break;\n                }\n                keyword = state.keyword();\n            }\n        } else if (keyword !== 'UVAS') {\n            throw new Error('Incorrect geosets format');\n        }\n\n        const textureChunkCount = state.int32();\n        geoset.TVertices = [];\n\n        for (let i = 0; i < textureChunkCount; ++i) {\n            state.expectKeyword('UVBS', 'Incorrect geosets format');\n            const textureCoordsCount = state.int32();\n\n            const tvertices = new Float32Array(textureCoordsCount * 2);\n            for (let j = 0; j < textureCoordsCount * 2; ++j) {\n                tvertices[j] = state.float32();\n            }\n\n            geoset.TVertices.push(tvertices);\n        }\n\n        model.Geosets.push(geoset);\n    }\n}\n\nfunction parseGeosetAnims (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const animStartPos = state.pos;\n        const animSize = state.int32();\n\n        const geosetAnim: GeosetAnim = {} as GeosetAnim;\n\n        geosetAnim.Alpha = state.float32();\n        geosetAnim.Flags = state.int32();\n        geosetAnim.Color = new Float32Array(3);\n        for (let i = 0; i < 3; ++i) {\n            geosetAnim.Color[i] = state.float32();\n        }\n        geosetAnim.GeosetId = state.int32();\n        if (geosetAnim.GeosetId === NONE) {\n            geosetAnim.GeosetId = null;\n        }\n\n        while (state.pos < animStartPos + animSize) {\n            const keyword = state.keyword();\n\n            if (keyword === 'KGAO') {\n                geosetAnim.Alpha = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KGAC') {\n                geosetAnim.Color = state.animVector(AnimVectorType.FLOAT3);\n            } else {\n                throw new Error('Incorrect GeosetAnim chunk data ' + keyword);\n            }\n        }\n\n        model.GeosetAnims.push(geosetAnim);\n    }\n}\n\nconst MODEL_NODE_NAME_LENGTH = 0x50;\nfunction parseNode (model: Model, node: Node, state: State): void {\n    const startPos = state.pos;\n    const size = state.int32();\n\n    node.Name = state.str(MODEL_NODE_NAME_LENGTH);\n    node.ObjectId = state.int32();\n    if (node.ObjectId === NONE) {\n        node.ObjectId = null;\n    }\n    node.Parent = state.int32();\n    if (node.Parent === NONE) {\n        node.Parent = null;\n    }\n    node.Flags = state.int32();\n\n    while (state.pos < startPos + size) {\n        const keyword = state.keyword();\n\n        if (keyword === 'KGTR') {\n            node.Translation = state.animVector(AnimVectorType.FLOAT3);\n        } else if (keyword === 'KGRT') {\n            node.Rotation = state.animVector(AnimVectorType.FLOAT4);\n        } else if (keyword === 'KGSC') {\n            node.Scaling = state.animVector(AnimVectorType.FLOAT3);\n        } else {\n            throw new Error('Incorrect node chunk data ' + keyword);\n        }\n    }\n\n    model.Nodes[node.ObjectId] = node;\n}\n\nfunction parseBones (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const bone: Bone = {} as Bone;\n\n        parseNode(model, bone, state);\n\n        bone.GeosetId = state.int32();\n        if (bone.GeosetId === NONE) {\n            bone.GeosetId = null;\n        }\n        bone.GeosetAnimId = state.int32();\n        if (bone.GeosetAnimId === NONE) {\n            bone.GeosetAnimId = null;\n        }\n\n        model.Bones.push(bone);\n    }\n}\n\nfunction parseHelpers (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const helper: Helper = {} as Helper;\n\n        parseNode(model, helper, state);\n\n        model.Helpers.push(helper);\n    }\n}\n\nconst MODEL_ATTACHMENT_PATH_LENGTH = 0x100;\nfunction parseAttachments (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const attachmentStart = state.pos;\n        const attachmentSize = state.int32();\n        const attachment: Attachment = {} as Attachment;\n\n        parseNode(model, attachment, state);\n\n        attachment.Path = state.str(MODEL_ATTACHMENT_PATH_LENGTH);\n        state.int32(); // unknown 4-byte\n        attachment.AttachmentID = state.int32();\n\n        if (state.pos < attachmentStart + attachmentSize) {\n            state.expectKeyword('KATV', 'Incorrect attachment chunk data');\n\n            attachment.Visibility = state.animVector(AnimVectorType.FLOAT1);\n        }\n\n        model.Attachments.push(attachment);\n    }\n}\n\nfunction parsePivotPoints (model: Model, state: State, size: number): void {\n    const pointsCount = size / (4 * 3);\n\n    for (let i = 0; i < pointsCount; ++i) {\n        model.PivotPoints[i] = new Float32Array(3);\n        model.PivotPoints[i][0] = state.float32();\n        model.PivotPoints[i][1] = state.float32();\n        model.PivotPoints[i][2] = state.float32();\n    }\n}\n\nfunction parseEventObjects (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const eventObject: EventObject = {} as EventObject;\n\n        parseNode(model, eventObject, state);\n        state.expectKeyword('KEVT', 'Incorrect EventObject chunk data');\n\n        const eventTrackCount = state.int32();\n        eventObject.EventTrack = new Uint32Array(eventTrackCount);\n        state.int32(); // unused 4-byte?\n        for (let i = 0; i < eventTrackCount; ++i) {\n            eventObject.EventTrack[i] = state.int32();\n        }\n\n        model.EventObjects.push(eventObject);\n    }\n}\n\nfunction parseCollisionShapes (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const collisionShape: CollisionShape = {} as CollisionShape;\n\n        parseNode(model, collisionShape, state);\n\n        collisionShape.Shape = state.int32();\n\n        if (collisionShape.Shape === CollisionShapeType.Box) {\n            collisionShape.Vertices = new Float32Array(6);\n        } else {\n            collisionShape.Vertices = new Float32Array(3);\n        }\n\n        for (let i = 0; i < collisionShape.Vertices.length; ++i) {\n            collisionShape.Vertices[i] = state.float32();\n        }\n\n        if (collisionShape.Shape === CollisionShapeType.Sphere) {\n            collisionShape.BoundsRadius = state.float32();\n        }\n\n        model.CollisionShapes.push(collisionShape);\n    }\n}\n\nfunction parseGlobalSequences (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    model.GlobalSequences = [];\n\n    while (state.pos < startPos + size) {\n        model.GlobalSequences.push(state.int32());\n    }\n}\n\nconst MODEL_PARTICLE_EMITTER_PATH_LENGTH = 0x100;\nfunction parseParticleEmitters (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const emitterStart = state.pos;\n        const emitterSize = state.int32();\n        const emitter: ParticleEmitter = {} as ParticleEmitter;\n\n        parseNode(model, emitter, state);\n\n        emitter.EmissionRate = state.float32();\n        emitter.Gravity = state.float32();\n        emitter.Longitude = state.float32();\n        emitter.Latitude = state.float32();\n\n        emitter.Path = state.str(MODEL_PARTICLE_EMITTER_PATH_LENGTH);\n        state.int32();\n\n        emitter.LifeSpan = state.float32();\n        emitter.InitVelocity = state.float32();\n\n        while (state.pos < emitterStart + emitterSize) {\n            const keyword = state.keyword();\n\n            if (keyword === 'KPEV') {\n                emitter.Visibility = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KPEE') {\n                emitter.EmissionRate = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KPEG') {\n                emitter.Gravity = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KPLN') {\n                emitter.Longitude = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KPLT') {\n                emitter.Latitude = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KPEL') {\n                emitter.LifeSpan = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KPES') {\n                emitter.InitVelocity = state.animVector(AnimVectorType.FLOAT1);\n            } else {\n                throw new Error('Incorrect particle emitter chunk data ' + keyword);\n            }\n        }\n\n        model.ParticleEmitters.push(emitter);\n    }\n}\n\nfunction parseParticleEmitters2 (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const emitterStart = state.pos;\n        const emitterSize = state.int32();\n        const emitter: ParticleEmitter2 = {} as ParticleEmitter2;\n\n        parseNode(model, emitter, state);\n\n        emitter.Speed = state.float32();\n        emitter.Variation = state.float32();\n        emitter.Latitude = state.float32();\n        emitter.Gravity = state.float32();\n        emitter.LifeSpan = state.float32();\n        emitter.EmissionRate = state.float32();\n        emitter.Width = state.float32();\n        emitter.Length = state.float32();\n\n        emitter.FilterMode = state.int32();\n        emitter.Rows = state.int32();\n        emitter.Columns = state.int32();\n\n        const frameFlags = state.int32();\n        emitter.FrameFlags = 0;\n        if (frameFlags === 0 || frameFlags === 2) {\n            emitter.FrameFlags |= ParticleEmitter2FramesFlags.Head;\n        }\n        if (frameFlags === 1 || frameFlags === 2) {\n            emitter.FrameFlags |= ParticleEmitter2FramesFlags.Tail;\n        }\n\n        emitter.TailLength = state.float32();\n        emitter.Time = state.float32();\n\n        emitter.SegmentColor = [];\n        // always 3 segments\n        for (let i = 0; i < 3; ++i) {\n            emitter.SegmentColor[i] = new Float32Array(3);\n            //  rgb order, inverse from mdl\n            for (let j = 0; j < 3; ++j) {\n                emitter.SegmentColor[i][j] = state.float32();\n            }\n        }\n\n        emitter.Alpha = new Uint8Array(3);\n        for (let i = 0; i < 3; ++i) {\n            emitter.Alpha[i] = state.uint8();\n        }\n\n        emitter.ParticleScaling = new Float32Array(3);\n        for (let i = 0; i < 3; ++i) {\n            emitter.ParticleScaling[i] = state.float32();\n        }\n\n        for (const part of ['LifeSpanUVAnim', 'DecayUVAnim', 'TailUVAnim', 'TailDecayUVAnim']) {\n            emitter[part] = new Uint32Array(3);\n            for (let i = 0; i < 3; ++i) {\n                emitter[part][i] = state.int32();\n            }\n        }\n\n        emitter.TextureID = state.int32();\n        if (emitter.TextureID === NONE) {\n            emitter.TextureID = null;\n        }\n        emitter.Squirt = state.int32() > 0;\n        emitter.PriorityPlane = state.int32();\n        emitter.ReplaceableId = state.int32();\n\n        while (state.pos < emitterStart + emitterSize) {\n            const keyword = state.keyword();\n\n            if (keyword === 'KP2V') {\n                emitter.Visibility = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KP2E') {\n                emitter.EmissionRate = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KP2W') {\n                emitter.Width = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KP2N') {\n                emitter.Length = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KP2S') {\n                emitter.Speed = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KP2L') {\n                emitter.Latitude = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KP2G') {\n                emitter.Gravity = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KP2R') {\n                emitter.Variation = state.animVector(AnimVectorType.FLOAT1);\n            } else {\n                throw new Error('Incorrect particle emitter2 chunk data ' + keyword);\n            }\n        }\n\n        model.ParticleEmitters2.push(emitter);\n    }\n}\n\nconst MODEL_CAMERA_NAME_LENGTH = 0x50;\nfunction parseCameras (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const cameraStart = state.pos;\n        const cameraSize = state.int32();\n\n        const camera: Camera = {} as Camera;\n\n        camera.Name = state.str(MODEL_CAMERA_NAME_LENGTH);\n\n        camera.Position = new Float32Array(3);\n        camera.Position[0] = state.float32();\n        camera.Position[1] = state.float32();\n        camera.Position[2] = state.float32();\n\n        camera.FieldOfView = state.float32();\n        camera.FarClip = state.float32();\n        camera.NearClip = state.float32();\n\n        camera.TargetPosition = new Float32Array(3);\n        camera.TargetPosition[0] = state.float32();\n        camera.TargetPosition[1] = state.float32();\n        camera.TargetPosition[2] = state.float32();\n\n        while (state.pos < cameraStart + cameraSize) {\n            const keyword = state.keyword();\n\n            if (keyword === 'KCTR') {\n                camera.Translation = state.animVector(AnimVectorType.FLOAT3);\n            } else if (keyword === 'KTTR') {\n                camera.TargetTranslation = state.animVector(AnimVectorType.FLOAT3);\n            } else if (keyword === 'KCRL') {\n                camera.Rotation = state.animVector(AnimVectorType.FLOAT1);\n            } else {\n                throw new Error('Incorrect camera chunk data ' + keyword);\n            }\n        }\n\n        model.Cameras.push(camera);\n    }\n}\n\nfunction parseLights (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const lightStart = state.pos;\n        const lightSize = state.int32();\n\n        const light: Light = {} as Light;\n\n        parseNode(model, light, state);\n\n        light.LightType = state.int32();\n        light.AttenuationStart = state.float32();\n        light.AttenuationEnd = state.float32();\n\n        light.Color = new Float32Array(3);\n        //  rgb order, inverse from mdl\n        for (let j = 0; j < 3; ++j) {\n            light.Color[j] = state.float32();\n        }\n\n        light.Intensity = state.float32();\n\n        light.AmbColor = new Float32Array(3);\n        //  rgb order, inverse from mdl\n        for (let j = 0; j < 3; ++j) {\n            light.AmbColor[j] = state.float32();\n        }\n\n        light.AmbIntensity = state.float32();\n\n        while (state.pos < lightStart + lightSize) {\n            const keyword = state.keyword();\n\n            if (keyword === 'KLAV') {\n                light.Visibility = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KLAC') {\n                light.Color = state.animVector(AnimVectorType.FLOAT3);\n            } else if (keyword === 'KLAI') {\n                light.Intensity = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KLBC') {\n                light.AmbColor = state.animVector(AnimVectorType.FLOAT3);\n            } else if (keyword === 'KLBI') {\n                light.AmbIntensity = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KLAS') {\n                light.AttenuationStart = state.animVector(AnimVectorType.INT1);\n            } else if (keyword === 'KLAE') {\n                light.AttenuationEnd = state.animVector(AnimVectorType.INT1);\n            } else {\n                throw new Error('Incorrect light chunk data ' + keyword);\n            }\n        }\n\n        model.Lights.push(light);\n    }\n}\n\nfunction parseTextureAnims (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const animStart = state.pos;\n        const animSize = state.int32();\n\n        const anim: TVertexAnim = {} as TVertexAnim;\n\n        while (state.pos < animStart + animSize) {\n            const keyword = state.keyword();\n\n            if (keyword === 'KTAT') {\n                anim.Translation = state.animVector(AnimVectorType.FLOAT3);\n            } else if (keyword === 'KTAR') {\n                anim.Rotation = state.animVector(AnimVectorType.FLOAT4);\n            } else if (keyword === 'KTAS') {\n                anim.Scaling = state.animVector(AnimVectorType.FLOAT3);\n            } else {\n                throw new Error('Incorrect light chunk data ' + keyword);\n            }\n        }\n\n        model.TextureAnims.push(anim);\n    }\n}\n\nfunction parseRibbonEmitters (model: Model, state: State, size: number): void {\n    const startPos = state.pos;\n\n    while (state.pos < startPos + size) {\n        const emitterStart = state.pos;\n        const emitterSize = state.int32();\n\n        const emitter: RibbonEmitter = {} as RibbonEmitter;\n\n        parseNode(model, emitter, state);\n\n        emitter.HeightAbove = state.float32();\n        emitter.HeightBelow = state.float32();\n        emitter.Alpha = state.float32();\n\n        emitter.Color = new Float32Array(3);\n        //  rgb order, inverse from mdl\n        for (let j = 0; j < 3; ++j) {\n            emitter.Color[j] = state.float32();\n        }\n\n        emitter.LifeSpan = state.float32();\n        emitter.TextureSlot = state.int32();\n\n        emitter.EmissionRate = state.int32();\n        emitter.Rows = state.int32();\n        emitter.Columns = state.int32();\n        emitter.MaterialID = state.int32();\n        emitter.Gravity = state.float32();\n\n        while (state.pos < emitterStart + emitterSize) {\n            const keyword = state.keyword();\n\n            if (keyword === 'KRVS') {\n                emitter.Visibility = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KRHA') {\n                emitter.HeightAbove = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KRHB') {\n                emitter.HeightBelow = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KRAL') {\n                emitter.Alpha = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KRTX') {\n                emitter.TextureSlot = state.animVector(AnimVectorType.INT1);\n            } else {\n                throw new Error('Incorrect ribbon emitter chunk data ' + keyword);\n            }\n        }\n\n        model.RibbonEmitters.push(emitter);\n    }\n}\n\nfunction parseFaceFX (model: Model, state: State, size: number): void {\n    if (model.Version < 900) {\n        throw new Error('Mismatched version chunk');\n    }\n\n    const startPos = state.pos;\n\n    model.FaceFX = model.FaceFX || [];\n\n    while (state.pos < startPos + size) {\n        const faceFX: FaceFX = {\n            Name: '',\n            Path: ''\n        };\n\n        faceFX.Name = state.str(80);\n        faceFX.Path = state.str(260);\n\n        model.FaceFX.push(faceFX);\n    }\n}\n\nfunction parseBindPose (model: Model, state: State, size: number): void {\n    if (model.Version < 900) {\n        throw new Error('Mismatched version chunk');\n    }\n\n    const startPos = state.pos;\n\n    model.BindPoses = model.BindPoses || [];\n\n    const len = state.int32();\n    const bindPose: BindPose = {\n        Matrices: []\n    };\n\n    for (let i = 0; i < len; ++i) {\n        const matrix = state.float32Array(12);\n        bindPose.Matrices.push(matrix);\n    }\n    model.BindPoses.push(bindPose);\n\n    if (state.pos !== startPos + size) {\n        throw new Error('Mismatched BindPose data');\n    }\n}\n\nfunction parseParticleEmitterPopcorn (model: Model, state: State, size: number): void {\n    if (model.Version < 900) {\n        throw new Error('Mismatched version chunk');\n    }\n\n    const startPos = state.pos;\n\n    model.ParticleEmitterPopcorns = model.ParticleEmitterPopcorns || [];\n\n    while (state.pos < startPos + size) {\n        const emitterStart = state.pos;\n        const emitterSize = state.int32();\n\n        const emitter: ParticleEmitterPopcorn = {} as ParticleEmitterPopcorn;\n\n        parseNode(model, emitter, state);\n\n        emitter.LifeSpan = state.float32();\n        emitter.EmissionRate = state.float32();\n        emitter.Speed = state.float32();\n        emitter.Color = state.float32Array(3);\n        emitter.Alpha = state.float32();\n        emitter.ReplaceableId = state.int32();\n        emitter.Path = state.str(260);\n        emitter.AnimVisibilityGuide = state.str(260);\n\n        while (state.pos < emitterStart + emitterSize) {\n            const keyword = state.keyword();\n\n            if (keyword === 'KPPA') {\n                emitter.Alpha = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KPPC') {\n                emitter.Color = state.animVector(AnimVectorType.FLOAT3);\n            } else if (keyword === 'KPPE') {\n                emitter.EmissionRate = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KPPL') {\n                emitter.LifeSpan = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KPPS') {\n                emitter.Speed = state.animVector(AnimVectorType.FLOAT1);\n            } else if (keyword === 'KPPV') {\n                emitter.Visibility = state.animVector(AnimVectorType.FLOAT1);\n            } else {\n                throw new Error('Incorrect particle emitter popcorn chunk data ' + keyword);\n            }\n        }\n\n        model.ParticleEmitterPopcorns.push(emitter);\n    }\n}\n\nconst parsers: {[key: string]: (model: Model, state: State, size: number) => void} = {\n    VERS: parseVersion,\n    MODL: parseModelInfo,\n    SEQS: parseSequences,\n    MTLS: parseMaterials,\n    TEXS: parseTextures,\n    GEOS: parseGeosets,\n    GEOA: parseGeosetAnims,\n    BONE: parseBones,\n    HELP: parseHelpers,\n    ATCH: parseAttachments,\n    PIVT: parsePivotPoints,\n    EVTS: parseEventObjects,\n    CLID: parseCollisionShapes,\n    GLBS: parseGlobalSequences,\n    PREM: parseParticleEmitters,\n    PRE2: parseParticleEmitters2,\n    CAMS: parseCameras,\n    LITE: parseLights,\n    TXAN: parseTextureAnims,\n    RIBB: parseRibbonEmitters,\n    FAFX: parseFaceFX,\n    BPOS: parseBindPose,\n    CORN: parseParticleEmitterPopcorn\n};\n\nexport function parse (arrayBuffer: ArrayBuffer): Model {\n    const state = new State(arrayBuffer);\n\n    if (state.keyword() !== 'MDLX') {\n        throw new Error('Not a mdx model');\n    }\n\n    const model: Model = {\n        // default\n        Version: 800,\n        Info: {\n            Name: '',\n            MinimumExtent: null,\n            MaximumExtent: null,\n            BoundsRadius: 0,\n            BlendTime: 150\n        },\n        Sequences: [],\n        GlobalSequences: [],\n        Textures: [],\n        Materials: [],\n        TextureAnims: [],\n        Geosets: [],\n        GeosetAnims: [],\n        Bones: [],\n        Helpers: [],\n        Attachments: [],\n        EventObjects: [],\n        ParticleEmitters: [],\n        ParticleEmitters2: [],\n        Cameras: [],\n        Lights: [],\n        RibbonEmitters: [],\n        CollisionShapes: [],\n        PivotPoints: [],\n        Nodes: []\n    };\n\n    while (state.pos < state.length) {\n        const keyword = state.keyword();\n        const size = state.int32();\n\n        if (keyword in parsers) {\n            parsers[keyword](model, state, size);\n        } else {\n            // throw new Error('Unknown group ' + keyword);\n            state.pos += size;\n        }\n    }\n\n    for (let i = 0; i < model.Nodes.length; ++i) {\n        if (model.Nodes[i] && model.PivotPoints[i]) {\n            model.Nodes[i].PivotPoint = model.PivotPoints[i];\n        }\n    }\n\n    model.Info.NumGeosets = model.Geosets.length;\n    model.Info.NumGeosetAnims = model.GeosetAnims.length;\n    model.Info.NumBones = model.Bones.length;\n    model.Info.NumLights = model.Lights.length;\n    model.Info.NumAttachments = model.Attachments.length;\n    model.Info.NumEvents = model.EventObjects.length;\n    model.Info.NumParticleEmitters = model.ParticleEmitters.length;\n    model.Info.NumParticleEmitters2 = model.ParticleEmitters2.length;\n    model.Info.NumRibbonEmitters = model.RibbonEmitters.length;\n\n    return model;\n}\n","import {\n    Model, Sequence, Texture, TextureFlags, Material, MaterialRenderMode, Layer, FilterMode, Node,\n    AnimVector, LineType, AnimKeyframe, LayerShading, TVertexAnim, Geoset, GeosetAnimInfo, GeosetAnim, GeosetAnimFlags,\n    NodeFlags, Bone, Light, LightType, Helper, Attachment, ParticleEmitter2, ParticleEmitter2FilterMode,\n    ParticleEmitter2Flags, ParticleEmitter2FramesFlags, RibbonEmitter, EventObject, Camera, CollisionShape,\n    CollisionShapeType, ParticleEmitter, ParticleEmitterFlags, FaceFX, BindPose, ParticleEmitterPopcorn, ParticleEmitterPopcornFlags\n} from '../model';\nimport { LAYER_TEXTURE_ID_MAP } from '../renderer/util';\n\nconst FLOAT_PRESICION = 6;\nconst EPSILON = 1e-6;\n\nfunction isNotEmptyVec3 (vec: Float32Array, val = 0) {\n    return Math.abs(vec[0] - val) > EPSILON ||\n        Math.abs(vec[1] - val) > EPSILON ||\n        Math.abs(vec[2] - val) > EPSILON;\n}\n\nfunction generateTab (tabSize = 1): string {\n    if (tabSize === 0) {\n        return '';\n    }\n\n    let res = '\\t';\n\n    for (let i = 1; i < tabSize; ++i) {\n        res += '\\t';\n    }\n\n    return res;\n}\n\nfunction generateWrappedString (val: string): string {\n    return `\"${val}\"`;\n}\n\nfunction generateWrappedStringOrNumber (val: string|number): string {\n    if (typeof val === 'number') {\n        return String(val);\n    }\n    return generateWrappedString(val);\n}\n\nfunction generateBlockStart (blockName: string, subInfo: string|number|null = null, tabSize = 0): string {\n    return generateTab(tabSize) +\n            blockName + ' ' +\n            (subInfo !== null ? generateWrappedStringOrNumber(subInfo) + ' ' : '') +\n            '{\\n';\n}\n\nfunction generateBlockEnd (tabSize = 0) {\n    return generateTab(tabSize) + '}\\n';\n}\n\nconst trailingZeroRegExp = /(\\..+?)0+$/;\nconst trailingZeroRegExp2 = /\\.0+$/;\nconst negativeZeroRegExp = /^-0$/;\nfunction generateNumber (val: number): string {\n    return val.toFixed(FLOAT_PRESICION)\n        .replace(trailingZeroRegExp, '$1')\n        .replace(trailingZeroRegExp2, '')\n        .replace(negativeZeroRegExp, '0');\n}\n\nfunction generateArray (arr: Float32Array|Int32Array|Uint32Array|Uint8Array, reverse = false): string {\n    let middle = '';\n\n    if (reverse) {\n        for (let i = arr.length - 1; i >= 0; --i) {\n            if (i < arr.length - 1) {\n                middle += ', ';\n            }\n\n            middle += generateNumber(arr[i]);\n        }\n    } else {\n        for (let i = 0; i < arr.length; ++i) {\n            if (i > 0) {\n                middle += ', ';\n            }\n\n            middle += generateNumber(arr[i]);\n        }\n    }\n\n    return '{ ' + middle + ' }';\n}\n\nfunction generateUIntArray (arr: number[]|Uint8Array|Uint16Array|Uint32Array): string {\n    let middle = '';\n\n    for (let i = 0; i < arr.length; ++i) {\n        if (i > 0) {\n            middle += ', ';\n        }\n\n        middle += String(arr[i]);\n    }\n\n    return '{ ' + middle + ' }';\n}\n\nfunction generateStatic (isStatic: boolean|null) {\n    return isStatic ? 'static ' : '';\n}\n\nfunction generateProp (name: string, val: string, isStatic: boolean|null, tabSize = 1): string {\n    return `${generateTab(tabSize) + generateStatic(isStatic) + name} ${val},\\n`;\n}\n\nfunction generateIntProp (name: string, val: number, isStatic: boolean|null = null, tabSize = 1): string {\n    return generateProp(name, String(val), isStatic, tabSize);\n}\n\nfunction generateFloatProp (name: string, val: number, isStatic: boolean|null = null, tabSize = 1): string {\n    return generateProp(name, generateNumber(val), isStatic, tabSize);\n}\n\nfunction generateStringProp (name: string, val: string, isStatic: boolean|null = null, tabSize = 1): string {\n    return generateProp(name, val, isStatic, tabSize);\n}\n\nfunction generateWrappedStringProp (name: string, val: string, isStatic: boolean|null = null,\n                                    tabSize = 1): string {\n    return generateProp(name, generateWrappedString(val), isStatic, tabSize);\n}\n\nfunction generateFloatArrayProp (name: string, val: Uint32Array|Float32Array, isStatic: boolean|null = null,\n                                 tabSize = 1): string {\n    return generateProp(name, generateArray(val), isStatic, tabSize);\n}\n\nfunction generateUIntArrayProp (name: string, val: Uint8Array|Uint32Array, isStatic: boolean|null = null,\n                                tabSize = 1): string {\n    return generateProp(name, generateUIntArray(val), isStatic, tabSize);\n}\n\nfunction generateBooleanProp (name: string, tabSize = 1): string {\n    return generateTab(tabSize) + name + ',\\n';\n}\n\nfunction generateIntPropIfNotEmpty (name: string, val: number|null|undefined, defaultVal = 0,\n                                    isStatic: boolean|null = null, tabSize = 1): string {\n    if (val !== defaultVal && val !== null && val !== undefined) {\n        return generateIntProp(name, val, isStatic, tabSize);\n    }\n    return '';\n}\n\nfunction generateFloatPropIfNotEmpty (name: string, val: number, defaultVal = 0, isStatic: boolean|null = null,\n                                      tabSize = 1): string {\n    if (Math.abs(val - defaultVal) > EPSILON) {\n        return generateFloatProp(name, val, isStatic, tabSize);\n    }\n    return '';\n}\n\nfunction generateLineType (lineType: LineType): string {\n    switch (lineType) {\n        case LineType.DontInterp:\n            return 'DontInterp';\n        case LineType.Linear:\n            return 'Linear';\n        case LineType.Bezier:\n            return 'Bezier';\n        case LineType.Hermite:\n            return 'Hermite';\n    }\n\n    return '';\n}\n\nfunction generateAnimKeyFrame (key: AnimKeyframe, tabSize = 2, reverse = false) {\n    let res = generateTab(tabSize) + key.Frame + ': ' +\n        (key.Vector.length === 1 ? generateNumber(key.Vector[0]) : generateArray(key.Vector, reverse)) + ',\\n';\n\n    if (key.InTan/* or OutTan */) {\n        res += generateTab(tabSize + 1) + 'InTan ' +\n            (key.InTan.length === 1 ? generateNumber(key.InTan[0]) : generateArray(key.InTan, reverse)) + ',\\n';\n        res += generateTab(tabSize + 1) + 'OutTan ' +\n            (key.OutTan.length === 1 ? generateNumber(key.OutTan[0]) : generateArray(key.OutTan, reverse)) + ',\\n';\n    }\n\n    return res;\n}\n\nfunction generateAnimVectorProp (\n    name: string,\n    val: AnimVector|number,\n    defaultVal: number|null = 0,\n    tabSize = 1,\n    reverse = false\n): string {\n    if (val === null || val === undefined) {\n        return '';\n    }\n\n    if (typeof val === 'number') {\n        if (typeof defaultVal === 'number' && Math.abs(val - defaultVal) < EPSILON) {\n            return '';\n        } else {\n            return generateFloatProp(name, val, true, tabSize);\n        }\n    } else {\n        return generateBlockStart(name, val.Keys.length, tabSize) +\n            generateBooleanProp(generateLineType(val.LineType), tabSize + 1) +\n            (val.GlobalSeqId !== null ? generateIntProp('GlobalSeqId', val.GlobalSeqId, null, tabSize + 1) : '') +\n            val.Keys.map(key => generateAnimKeyFrame(key, tabSize + 1, reverse)).join('') +\n            generateBlockEnd(tabSize);\n    }\n}\n\nfunction generateVersion (model: Model): string {\n    return generateBlockStart('Version') +\n            generateIntProp('FormatVersion', model.Version) +\n            generateBlockEnd();\n}\n\nfunction generateModel (model: Model): string {\n    return generateBlockStart('Model', model.Info.Name) +\n        generateIntPropIfNotEmpty('NumGeosets', model.Geosets.length) +\n        generateIntPropIfNotEmpty('NumGeosetAnims', model.GeosetAnims.length) +\n        generateIntPropIfNotEmpty('NumHelpers', model.Helpers.length) +\n        generateIntPropIfNotEmpty('NumBones', model.Bones.length) +\n        (model.Lights.length ? generateIntPropIfNotEmpty('NumLights', model.Lights.length) : '') +\n        generateIntPropIfNotEmpty('NumAttachments', model.Attachments.length) +\n        generateIntPropIfNotEmpty('NumEvents', model.EventObjects.length) +\n        generateIntPropIfNotEmpty('NumParticleEmitters', model.ParticleEmitters.length) +\n        (model.ParticleEmitters2.length ?\n            generateIntPropIfNotEmpty('NumParticleEmitters2', model.ParticleEmitters2.length) :\n            '') +\n        (model.RibbonEmitters.length ?\n            generateIntPropIfNotEmpty('NumRibbonEmitters', model.RibbonEmitters.length) :\n            '') +\n        generateIntProp('BlendTime', model.Info.BlendTime) +\n        generateFloatArrayProp('MinimumExtent', model.Info.MinimumExtent) +\n        generateFloatArrayProp('MaximumExtent', model.Info.MaximumExtent) +\n        generateFloatPropIfNotEmpty('BoundsRadius', model.Info.BoundsRadius) +\n        generateBlockEnd();\n}\n\nfunction generateSequences (model: Model): string {\n    return generateBlockStart('Sequences', model.Sequences.length) +\n            model.Sequences.map(generateSequenceChunk).join('') +\n            generateBlockEnd();\n}\n\nfunction generateSequenceChunk (sequence: Sequence): string {\n    return generateBlockStart('Anim', sequence.Name, 1) +\n        generateUIntArrayProp('Interval', sequence.Interval, null, 2) +\n        generateFloatPropIfNotEmpty('Rarity', sequence.Rarity, 0, null, 2) +\n        generateFloatPropIfNotEmpty('MoveSpeed', sequence.MoveSpeed, 0, null, 2) +\n        (sequence.NonLooping ? generateBooleanProp('NonLooping', 2) : '') +\n        generateFloatArrayProp('MinimumExtent', sequence.MinimumExtent, null, 2) +\n        generateFloatArrayProp('MaximumExtent', sequence.MaximumExtent, null, 2) +\n        generateFloatPropIfNotEmpty('BoundsRadius', sequence.BoundsRadius, 0, null, 2) +\n        generateBlockEnd(1);\n}\n\nfunction generateGlobalSequences (model: Model): string {\n    if (!model.GlobalSequences || !model.GlobalSequences.length) {\n        return '';\n    }\n\n    return generateBlockStart('GlobalSequences', model.GlobalSequences.length) +\n        model.GlobalSequences.map(duration => generateIntProp('Duration', duration)).join('') +\n        generateBlockEnd();\n}\n\nfunction generateTextures (model: Model): string {\n    if (!model.Textures.length) {\n        return '';\n    }\n\n    return generateBlockStart('Textures', model.Textures.length) +\n        model.Textures.map(generateTextureChunk).join('') +\n        generateBlockEnd();\n}\n\nfunction generateTextureChunk (texture: Texture): string {\n    return generateBlockStart('Bitmap', null, 1) +\n        generateWrappedStringProp('Image', texture.Image, null, 2) +\n        generateIntPropIfNotEmpty('ReplaceableId', texture.ReplaceableId, 0, null, 2) +\n        (texture.Flags & TextureFlags.WrapWidth ? generateBooleanProp('WrapWidth', 2) : '') +\n        (texture.Flags & TextureFlags.WrapHeight ? generateBooleanProp('WrapHeight', 2) : '') +\n        generateBlockEnd(1);\n}\n\nfunction generateMaterials (model: Model): string {\n    if (!model.Materials.length) {\n        return '';\n    }\n\n    return generateBlockStart('Materials', model.Materials.length) +\n        model.Materials.map(it => generateMaterialChunk(model, it)).join('') +\n        generateBlockEnd();\n}\n\nfunction generateMaterialChunk (model: Model, material: Material): string {\n    let shader = '';\n\n    if (model.Version >= 900 && model.Version < 1100 && material.Shader) {\n        shader = generateWrappedStringProp('Shader', material.Shader, false, 2);\n    }\n\n    return generateBlockStart('Material', null, 1) +\n        (material.RenderMode & MaterialRenderMode.ConstantColor ? generateBooleanProp('ConstantColor', 2) : '') +\n        (material.RenderMode & MaterialRenderMode.SortPrimsFarZ ? generateBooleanProp('SortPrimsFarZ', 2) : '') +\n        (material.RenderMode & MaterialRenderMode.FullResolution ? generateBooleanProp('FullResolution', 2) : '') +\n        generateIntPropIfNotEmpty('PriorityPlane', material.PriorityPlane, 0, null, 2) +\n        generateIntPropIfNotEmpty('RenderMode', material.RenderMode, 0, null, 2) +\n        shader +\n        material.Layers.map(it => generateLayerChunk(model, it)).join('') +\n        generateBlockEnd(1);\n}\n\nfunction generateFilterMode (filterMode: FilterMode): string {\n    switch (filterMode) {\n        case FilterMode.None:\n            return 'None';\n        case FilterMode.Transparent:\n            return 'Transparent';\n        case FilterMode.Blend:\n            return 'Blend';\n        case FilterMode.Additive:\n            return 'Additive';\n        case FilterMode.AddAlpha:\n            return 'AddAlpha';\n        case FilterMode.Modulate:\n            return 'Modulate';\n        case FilterMode.Modulate2x:\n            return 'Modulate2x';\n    }\n    return '';\n}\n\nfunction generateLayerChunk (model: Model, layer: Layer) {\n    let middle = '';\n\n    if (model.Version >= 900) {\n        middle += (layer.EmissiveGain !== undefined ? generateAnimVectorProp('EmissiveGain', layer.EmissiveGain, 1, 3) : '');\n        if (model.Version >= 1000) {\n            middle += (layer.FresnelColor !== undefined ? generateColorProp('FresnelColor', layer.FresnelColor, true, 3) : '');\n            middle += (layer.FresnelOpacity !== undefined ? generateAnimVectorProp('FresnelOpacity', layer.FresnelOpacity, 0, 3) : '');\n            middle += (layer.FresnelTeamColor !== undefined ? generateAnimVectorProp('FresnelTeamColor', layer.FresnelTeamColor, 0, 3) : '');\n        }\n    }\n    if (model.Version >= 1100) {\n        middle += generateIntProp('ShaderTypeId', layer.ShaderTypeId || 0, null, 3);\n\n        LAYER_TEXTURE_ID_MAP.slice(1).forEach(name => {\n            const val = layer[name];\n            if (val !== undefined) {\n                middle += generateAnimVectorProp(name, val, null, 3);\n            }\n        });\n    }\n\n    return generateBlockStart('Layer', null, 2) +\n        generateStringProp('FilterMode', generateFilterMode(layer.FilterMode), null, 3) +\n        (layer.Alpha !== undefined ? generateAnimVectorProp('Alpha', layer.Alpha, 1, 3) : '') +\n        (layer.TextureID !== undefined ? generateAnimVectorProp('TextureID', layer.TextureID, null, 3) : '') +\n        (layer.Shading & LayerShading.TwoSided ? generateBooleanProp('TwoSided', 3) : '') +\n        (layer.Shading & LayerShading.Unshaded ? generateBooleanProp('Unshaded', 3) : '') +\n        (layer.Shading & LayerShading.Unfogged ? generateBooleanProp('Unfogged', 3) : '') +\n        (layer.Shading & LayerShading.SphereEnvMap ? generateBooleanProp('SphereEnvMap', 3) : '') +\n        (layer.Shading & LayerShading.NoDepthTest ? generateBooleanProp('NoDepthTest', 3) : '') +\n        (layer.Shading & LayerShading.NoDepthSet ? generateBooleanProp('NoDepthSet', 3) : '') +\n        generateIntPropIfNotEmpty('CoordId', layer.CoordId, 0, null, 3) +\n        generateIntPropIfNotEmpty('TVertexAnimId', layer.TVertexAnimId, null, null, 3) +\n        middle +\n        generateBlockEnd(2);\n}\n\nfunction generateTextureAnims (model: Model): string {\n    if (!model.TextureAnims.length) {\n        return '';\n    }\n\n    return generateBlockStart('TextureAnims', model.TextureAnims.length) +\n        model.TextureAnims.map(generateTextureAnimChunk).join('') +\n        generateBlockEnd();\n}\n\nfunction generateTextureAnimChunk (textureAnim: TVertexAnim): string {\n    return generateBlockStart('TVertexAnim', null, 1) +\n        (textureAnim.Translation ? generateAnimVectorProp('Translation', textureAnim.Translation, null, 2) : '') +\n        (textureAnim.Rotation ? generateAnimVectorProp('Rotation', textureAnim.Rotation, null, 2) : '') +\n        (textureAnim.Scaling ? generateAnimVectorProp('Scaling', textureAnim.Scaling, null, 2) : '') +\n        generateBlockEnd(1);\n}\n\nfunction generateGeosets (model: Model): string {\n    if (!model.Geosets.length) {\n        return '';\n    }\n\n    return model.Geosets.map(it => generateGeosetChunk(model, it)).join('');\n}\n\nfunction generateGeosetChunk (model: Model, geoset: Geoset): string {\n    let middle = '';\n\n    if (model.Version >= 900) {\n        middle += (geoset.LevelOfDetail !== undefined ? generateIntProp('LevelOfDetail', geoset.LevelOfDetail) : '') +\n            (geoset.Name ? generateWrappedStringProp('Name', geoset.Name) : '') +\n            (geoset.Tangents ? generateGeosetArray('Tangents', geoset.Tangents, 4) : '') +\n            (geoset.SkinWeights ? generateGeosetArray('SkinWeights', geoset.SkinWeights, 8) : '');\n    }\n\n    return generateBlockStart('Geoset') +\n        generateGeosetArray('Vertices', geoset.Vertices, 3) +\n        generateGeosetArray('Normals', geoset.Normals, 3) +\n        generateGeosetArray('TVertices', geoset.TVertices[0], 2) +\n        generateGeosetVertexGroup(geoset.VertexGroup) +\n        generateGeosetFaces(geoset.Faces) +\n        generateGeosetGroups(geoset.Groups) +\n        generateFloatArrayProp('MinimumExtent', geoset.MinimumExtent) +\n        generateFloatArrayProp('MaximumExtent', geoset.MaximumExtent) +\n        generateFloatPropIfNotEmpty('BoundsRadius', geoset.BoundsRadius) +\n        generateGeosetAnimInfos(geoset.Anims) +\n        generateIntProp('MaterialID', geoset.MaterialID) +\n        generateIntProp('SelectionGroup', geoset.SelectionGroup) +\n        (geoset.Unselectable ? generateBooleanProp('Unselectable') : '') +\n        middle +\n        generateBlockEnd();\n}\n\nfunction generateGeosetArray (name: string, arr: Float32Array|Uint8Array, elemLength: number): string {\n    let middle = '';\n    const elemCount = arr.length / elemLength;\n\n    for (let i = 0; i < elemCount; ++i) {\n        middle += generateTab(2) + generateArray(arr.slice(i * elemLength, (i + 1) * elemLength)) + ',\\n';\n    }\n\n    return generateBlockStart(name, elemCount, 1) +\n        middle +\n        generateBlockEnd(1);\n}\n\nfunction generateGeosetVertexGroup (arr: Uint8Array|Uint16Array): string {\n    if (!arr.length) {\n        return '';\n    }\n\n    let middle = '';\n\n    for (let i = 0; i < arr.length; ++i) {\n        middle += generateTab(2) + arr[i] + ',\\n';\n    }\n\n    return generateBlockStart('VertexGroup', null, 1) +\n        middle +\n        generateBlockEnd(1);\n}\n\nfunction generateGeosetFaces (arr: Uint16Array): string {\n    return generateBlockStart(`Faces 1 ${arr.length}`, null, 1) +\n        generateBlockStart('Triangles', null, 2) +\n        generateTab(3) + generateUIntArray(arr) + ',\\n' +\n        generateBlockEnd(2) +\n        generateBlockEnd(1);\n}\n\nfunction generateGeosetGroups (groups: number[][]): string {\n    let totalMatrices = 0;\n    let middle = '';\n\n    for (const group of groups) {\n        totalMatrices += group.length;\n        middle += generateTab(2) + 'Matrices ' + generateUIntArray(group) + ',\\n';\n    }\n\n    return generateBlockStart(`Groups ${groups.length} ${totalMatrices}`, null, 1) +\n        middle +\n        generateBlockEnd(1);\n}\n\nfunction generateGeosetAnimInfos (anims: GeosetAnimInfo[]): string {\n    if (!anims) {\n        return '';\n    }\n\n    return anims.map(generateGeosetAnimInfoChunk).join('');\n}\n\nfunction generateGeosetAnimInfoChunk (anim: GeosetAnimInfo): string {\n    return generateBlockStart('Anim', null, 1) +\n        generateFloatArrayProp('MinimumExtent', anim.MinimumExtent, null, 2) +\n        generateFloatArrayProp('MaximumExtent', anim.MaximumExtent, null, 2) +\n        generateFloatPropIfNotEmpty('BoundsRadius', anim.BoundsRadius, 0, null, 2) +\n        generateBlockEnd(1);\n}\n\nfunction generateGeosetAnims (model: Model): string {\n    if (!model.GeosetAnims.length) {\n        return '';\n    }\n\n    return model.GeosetAnims.map(generateGeosetAnimChunk).join('');\n}\n\nfunction generateColorProp (name: string, color: AnimVector|Float32Array, isStatic: boolean|null,\n                            tabSize = 1): string {\n    if (color) {\n        if (color instanceof Float32Array) {\n            if (!isStatic || isNotEmptyVec3(color, 1)) {\n                let middle = '';\n\n                for (let i = 2; i >= 0; --i) {\n                    if (i < 2) {\n                        middle += ', ';\n                    }\n                    middle += generateNumber(color[i]);\n                }\n\n                return `${generateTab(tabSize)}${isStatic ? 'static ' : ''}${name} { ${middle} },\\n`;\n            }\n        } else {\n            return generateAnimVectorProp(name, color, null, tabSize, true);\n        }\n    }\n\n    return '';\n}\n\nfunction generateGeosetAnimChunk (geosetAnim: GeosetAnim): string {\n    return generateBlockStart('GeosetAnim') +\n        generateIntProp('GeosetId', geosetAnim.GeosetId) +\n        generateAnimVectorProp('Alpha', geosetAnim.Alpha, 1) +\n        generateColorProp('Color', geosetAnim.Color, true) +\n        (geosetAnim.Flags & GeosetAnimFlags.DropShadow ? generateBooleanProp('DropShadow') : '') +\n        generateBlockEnd();\n}\n\nfunction generateNodeProps (node: Node): string {\n    return generateIntProp('ObjectId', node.ObjectId) +\n        generateIntPropIfNotEmpty('Parent', node.Parent, null) +\n        generateNodeDontInherit(node.Flags) +\n        (node.Flags & NodeFlags.Billboarded ? generateBooleanProp('Billboarded') : '') +\n        (node.Flags & NodeFlags.BillboardedLockX ? generateBooleanProp('BillboardedLockX') : '') +\n        (node.Flags & NodeFlags.BillboardedLockY ? generateBooleanProp('BillboardedLockY') : '') +\n        (node.Flags & NodeFlags.BillboardedLockZ ? generateBooleanProp('BillboardedLockZ') : '') +\n        (node.Flags & NodeFlags.CameraAnchored ? generateBooleanProp('CameraAnchored') : '') +\n        (node.Translation !== undefined ? generateAnimVectorProp('Translation', node.Translation) : '') +\n        (node.Rotation !== undefined ? generateAnimVectorProp('Rotation', node.Rotation) : '') +\n        (node.Scaling !== undefined ? generateAnimVectorProp('Scaling', node.Scaling) : '');\n}\n\nfunction generateNodeDontInherit (flags: NodeFlags) {\n    const flagsStrs: string[] = [];\n\n    if (flags & NodeFlags.DontInheritTranslation) {\n        flagsStrs.push('Translation');\n    }\n    if (flags & NodeFlags.DontInheritRotation) {\n        flagsStrs.push('Rotation');\n    }\n    if (flags & NodeFlags.DontInheritScaling) {\n        flagsStrs.push('Scaling');\n    }\n\n    if (!flagsStrs.length) {\n        return '';\n    }\n\n    return generateTab(1) + 'DontInherit { ' + flagsStrs.join(', ') + ' },\\n';\n}\n\nfunction generateBones (model: Model): string {\n    if (!model.Bones.length) {\n        return '';\n    }\n\n    return model.Bones.map(generateBoneChunk).join('');\n}\n\nfunction generateBoneChunk (bone: Bone): string {\n    return generateBlockStart('Bone', bone.Name) +\n        generateNodeProps(bone) +\n        (bone.GeosetId !== null ?\n            generateIntProp('GeosetId', bone.GeosetId) :\n            generateStringProp('GeosetId', 'Multiple')) +\n        (bone.GeosetAnimId !== null ?\n            generateIntProp('GeosetAnimId', bone.GeosetAnimId) :\n            generateStringProp('GeosetAnimId', 'None')) +\n        generateBlockEnd();\n}\n\nfunction generateLights (model: Model): string {\n    if (!model.Lights.length) {\n        return '';\n    }\n\n    return model.Lights.map(generateLightChunk).join('');\n}\n\nfunction generateLightChunk (light: Light): string {\n    return generateBlockStart('Light', light.Name) +\n        generateNodeProps(light) +\n        generateBooleanProp(generateLightType(light.LightType)) +\n        generateAnimVectorProp('AttenuationStart', light.AttenuationStart) +\n        generateAnimVectorProp('AttenuationEnd', light.AttenuationEnd) +\n        generateColorProp('Color', light.Color, true) +\n        generateAnimVectorProp('Intensity', light.Intensity, null) +\n        generateColorProp('AmbColor', light.AmbColor, true) +\n        generateAnimVectorProp('AmbIntensity', light.AmbIntensity, null) +\n        generateAnimVectorProp('Visibility', light.Visibility, 1) +\n        generateBlockEnd();\n}\n\nfunction generateLightType (lightType: LightType): string {\n    switch (lightType) {\n        case LightType.Omnidirectional:\n            return 'Omnidirectional';\n        case LightType.Directional:\n            return 'Directional';\n        case LightType.Ambient:\n            return 'Ambient';\n    }\n\n    return '';\n}\n\nfunction generateHelpers (model: Model): string {\n    return model.Helpers.map(generateHelperChunk).join('');\n}\n\nfunction generateHelperChunk (helper: Helper): string {\n    return generateBlockStart('Helper', helper.Name) +\n        generateNodeProps(helper) +\n        generateBlockEnd();\n}\n\nfunction generateAttachments (model: Model): string {\n    return model.Attachments.map(generateAttachmentChunk).join('');\n}\n\nfunction generateAttachmentChunk (attachment: Attachment): string {\n    return generateBlockStart('Attachment', attachment.Name) +\n        generateNodeProps(attachment) +\n        generateIntProp('AttachmentID', attachment.AttachmentID) +\n        (attachment.Path ? generateWrappedStringProp('Path', attachment.Path) : '') +\n        generateAnimVectorProp('Visibility', attachment.Visibility, 1) +\n        generateBlockEnd();\n}\n\nfunction generatePivotPoints (model: Model): string {\n    return generateBlockStart('PivotPoints', model.PivotPoints.length) +\n        model.PivotPoints.map(point => `${generateTab()}${generateArray(point)},\\n`).join('') +\n        generateBlockEnd();\n}\n\nfunction generateParticleEmitters (model: Model): string {\n    return model.ParticleEmitters.map(generateParticleEmitterChunk).join('');\n}\n\nfunction generateParticleEmitterChunk (emitter: ParticleEmitter): string {\n    return generateBlockStart('ParticleEmitter', emitter.Name) +\n        generateNodeProps(emitter) +\n        (emitter.Flags & ParticleEmitterFlags.EmitterUsesMDL ? generateBooleanProp('EmitterUsesMDL') : '') +\n        (emitter.Flags & ParticleEmitterFlags.EmitterUsesTGA ? generateBooleanProp('EmitterUsesTGA') : '') +\n        generateAnimVectorProp('EmissionRate', emitter.EmissionRate) +\n        generateAnimVectorProp('Gravity', emitter.Gravity) +\n        generateAnimVectorProp('Longitude', emitter.Longitude) +\n        generateAnimVectorProp('Latitude', emitter.Latitude) +\n        generateAnimVectorProp('Visibility', emitter.Visibility) +\n        generateBlockStart('Particle', null, 1) +\n        generateAnimVectorProp('LifeSpan', emitter.LifeSpan, null, 2) +\n        generateAnimVectorProp('InitVelocity', emitter.InitVelocity, null, 2) +\n        generateWrappedStringProp('Path', emitter.Path, false, 2) +\n        generateBlockEnd(1) +\n        generateBlockEnd();\n}\n\nfunction generateParticleEmitters2 (model: Model): string {\n    return model.ParticleEmitters2.map(generateParticleEmitter2Chunk).join('');\n}\n\nfunction generateParticleEmitters2FilterMode (filterMode: ParticleEmitter2FilterMode): string {\n    switch (filterMode) {\n        case ParticleEmitter2FilterMode.Blend:\n            return 'Blend';\n        case ParticleEmitter2FilterMode.Additive:\n            return 'Additive';\n        case ParticleEmitter2FilterMode.Modulate:\n            return 'Modulate';\n        case ParticleEmitter2FilterMode.Modulate2x:\n            return 'Modulate2x';\n        case ParticleEmitter2FilterMode.AlphaKey:\n            return 'AlphaKey';\n    }\n\n    return '';\n}\n\nfunction generateSegmentColor (colors: Float32Array[]): string {\n    return generateBlockStart('SegmentColor', null, 1) +\n        colors.map(color => generateColorProp('Color', color, false, 2)).join('') +\n        generateTab() + '},\\n';\n}\n\nfunction generateParticleEmitter2FrameFlags (frameFlags: ParticleEmitter2FramesFlags): string {\n    if (frameFlags & ParticleEmitter2FramesFlags.Head && frameFlags & ParticleEmitter2FramesFlags.Tail) {\n        return 'Both';\n    } else if (frameFlags & ParticleEmitter2FramesFlags.Head) {\n        return 'Head';\n    } else if (frameFlags & ParticleEmitter2FramesFlags.Tail) {\n        return 'Tail';\n    }\n    return '';\n}\n\nfunction generateParticleEmitter2Chunk (particleEmitter2: ParticleEmitter2) {\n    return generateBlockStart('ParticleEmitter2', particleEmitter2.Name) +\n        generateNodeProps(particleEmitter2) +\n        generateBooleanProp(generateParticleEmitters2FilterMode(particleEmitter2.FilterMode)) +\n        generateAnimVectorProp('Speed', particleEmitter2.Speed, null) +\n        generateAnimVectorProp('Variation', particleEmitter2.Variation, null) +\n        generateAnimVectorProp('Latitude', particleEmitter2.Latitude, null) +\n        generateAnimVectorProp('Gravity', particleEmitter2.Gravity, null) +\n        generateAnimVectorProp('EmissionRate', particleEmitter2.EmissionRate, null) +\n        generateAnimVectorProp('Width', particleEmitter2.Width, null) +\n        generateAnimVectorProp('Length', particleEmitter2.Length, null) +\n        generateAnimVectorProp('Visibility', particleEmitter2.Visibility, 1) +\n        generateSegmentColor(particleEmitter2.SegmentColor) +\n        generateUIntArrayProp('Alpha', particleEmitter2.Alpha) +\n        generateFloatArrayProp('ParticleScaling', particleEmitter2.ParticleScaling) +\n        generateFloatArrayProp('LifeSpanUVAnim', particleEmitter2.LifeSpanUVAnim) +\n        generateFloatArrayProp('DecayUVAnim', particleEmitter2.DecayUVAnim) +\n        generateFloatArrayProp('TailUVAnim', particleEmitter2.TailUVAnim) +\n        generateFloatArrayProp('TailDecayUVAnim', particleEmitter2.TailDecayUVAnim) +\n        generateIntPropIfNotEmpty('Rows', particleEmitter2.Rows, 0) +\n        generateIntPropIfNotEmpty('Columns', particleEmitter2.Columns, 0) +\n        generateIntProp('TextureID', particleEmitter2.TextureID) +\n        generateIntPropIfNotEmpty('Time', particleEmitter2.Time, 0) +\n        generateIntPropIfNotEmpty('LifeSpan', particleEmitter2.LifeSpan, 0) +\n        generateIntPropIfNotEmpty('TailLength', particleEmitter2.TailLength, 0) +\n        generateIntPropIfNotEmpty('PriorityPlane', particleEmitter2.PriorityPlane, 0) +\n        generateIntPropIfNotEmpty('ReplaceableId', particleEmitter2.ReplaceableId, null) +\n        (particleEmitter2.Flags & ParticleEmitter2Flags.SortPrimsFarZ ? generateBooleanProp('SortPrimsFarZ') : '') +\n        (particleEmitter2.Flags & ParticleEmitter2Flags.LineEmitter ? generateBooleanProp('LineEmitter') : '') +\n        (particleEmitter2.Flags & ParticleEmitter2Flags.ModelSpace ? generateBooleanProp('ModelSpace') : '') +\n        (particleEmitter2.Flags & ParticleEmitter2Flags.Unshaded ? generateBooleanProp('Unshaded') : '') +\n        (particleEmitter2.Flags & ParticleEmitter2Flags.Unfogged ? generateBooleanProp('Unfogged') : '') +\n        (particleEmitter2.Flags & ParticleEmitter2Flags.XYQuad ? generateBooleanProp('XYQuad') : '') +\n        (particleEmitter2.Squirt ? generateBooleanProp('Squirt') : '') +\n        generateBooleanProp(generateParticleEmitter2FrameFlags(particleEmitter2.FrameFlags)) +\n        generateBlockEnd();\n}\n\nfunction generateRibbonEmitters (model: Model): string {\n    return model.RibbonEmitters.map(generateRibbonEmitterChunk).join('');\n}\n\nfunction generateRibbonEmitterChunk (ribbonEmitter: RibbonEmitter): string {\n    return generateBlockStart('RibbonEmitter', ribbonEmitter.Name) +\n        generateNodeProps(ribbonEmitter) +\n        generateAnimVectorProp('HeightAbove', ribbonEmitter.HeightAbove, null) +\n        generateAnimVectorProp('HeightBelow', ribbonEmitter.HeightBelow, null) +\n        generateAnimVectorProp('Alpha', ribbonEmitter.Alpha, null) +\n        generateColorProp('Color', ribbonEmitter.Color, true) +\n        generateAnimVectorProp('TextureSlot', ribbonEmitter.TextureSlot, null) +\n        generateAnimVectorProp('Visibility', ribbonEmitter.Visibility, 1) +\n        generateIntProp('EmissionRate', ribbonEmitter.EmissionRate) +\n        generateIntProp('LifeSpan', ribbonEmitter.LifeSpan) +\n        generateIntPropIfNotEmpty('Gravity', ribbonEmitter.Gravity, 0) +\n        generateIntProp('Rows', ribbonEmitter.Rows) +\n        generateIntProp('Columns', ribbonEmitter.Columns) +\n        generateIntProp('MaterialID', ribbonEmitter.MaterialID) +\n        generateBlockEnd();\n}\n\nfunction generateEventObjects (model: Model): string {\n    return model.EventObjects.map(generateEventObjectChunk).join('');\n}\n\nfunction generateEventTrack (eventTrack: Uint32Array): string {\n    let middle = '';\n\n    for (let i = 0; i < eventTrack.length; ++i) {\n        middle += generateTab(2) + eventTrack[i] + ',\\n';\n    }\n\n    return generateBlockStart('EventTrack', eventTrack.length, 1) +\n        middle +\n        generateBlockEnd(1);\n}\n\nfunction generateEventObjectChunk (eventObject: EventObject): string {\n    return generateBlockStart('EventObject', eventObject.Name) +\n        generateNodeProps(eventObject) +\n        generateEventTrack(eventObject.EventTrack) +\n        generateBlockEnd();\n}\n\nfunction generateCameras (model: Model): string {\n    return model.Cameras.map(generateCameraChunk).join('');\n}\n\nfunction generateCameraChunk (camera: Camera): string {\n    return generateBlockStart('Camera', camera.Name) +\n        generateFloatProp('FieldOfView', camera.FieldOfView) +\n        generateFloatProp('FarClip', camera.FarClip) +\n        generateFloatProp('NearClip', camera.NearClip) +\n        generateFloatArrayProp('Position', camera.Position) +\n        generateAnimVectorProp('Translation', camera.Translation) +\n        generateAnimVectorProp('Rotation', camera.Rotation) +\n        generateBlockStart('Target', null, 1) +\n        generateFloatArrayProp('Position', camera.TargetPosition, null, 2) +\n        generateAnimVectorProp('Translation', camera.TargetTranslation, null, 2) +\n        generateBlockEnd(1) +\n        generateBlockEnd();\n}\n\nfunction generateCollisionShapes (model: Model): string {\n    return model.CollisionShapes.map(generateCollisionShapeChunk).join('');\n}\n\nfunction generateCollisionShapeChunk (collisionShape: CollisionShape): string {\n    let middle;\n\n    if (collisionShape.Shape === CollisionShapeType.Box) {\n        middle = generateBooleanProp('Box');\n        middle += generateBlockStart('Vertices', 2, 1) +\n            generateTab(2) + generateArray(collisionShape.Vertices.slice(0, 3)) + ',\\n' +\n            generateTab(2) + generateArray(collisionShape.Vertices.slice(3, 6)) + ',\\n' +\n            generateBlockEnd(1);\n    } else {\n        middle = generateBooleanProp('Sphere');\n        middle += generateBlockStart('Vertices', 1, 1) +\n            generateTab(2) + generateArray(collisionShape.Vertices) + ',\\n' +\n            generateBlockEnd(1) +\n            generateFloatProp('BoundsRadius', collisionShape.BoundsRadius);\n    }\n\n    return generateBlockStart('CollisionShape', collisionShape.Name) +\n        generateNodeProps(collisionShape) +\n        middle +\n        generateBlockEnd();\n}\n\nfunction generateFaceFX (model: Model): string {\n    if (model.Version < 900 || !model.FaceFX) {\n        return '';\n    }\n    return model.FaceFX.map(generateFaceFXChunk).join('');\n}\n\nfunction generateFaceFXChunk (faceFX: FaceFX): string {\n    return generateBlockStart('FaceFX', faceFX.Name) +\n        generateWrappedStringProp('Path', faceFX.Path) +\n        generateBlockEnd();\n}\n\nfunction generateBindPose (model: Model): string {\n    if (model.Version < 900 || !model.BindPoses) {\n        return '';\n    }\n    return model.BindPoses.map(generateBindPoseChunk).join('');\n}\n\nfunction generateBindPoseChunk (bindPose: BindPose): string {\n    const middle = generateBlockStart('Matrices', bindPose.Matrices.length, 1) +\n        bindPose.Matrices.map(item => {\n            return generateTab(2) + generateArray(item) + ',';\n        }).join('\\n') + '\\n' +\n        generateBlockEnd(1);\n\n    return generateBlockStart('BindPose') +\n        middle +\n        generateBlockEnd();\n}\n\nfunction generateParticleEmitterPopcorn (model: Model): string {\n    if (model.Version < 900 || !model.ParticleEmitterPopcorns) {\n        return '';\n    }\n    return model.ParticleEmitterPopcorns.map(generateParticleEmitterPopcornChunk).join('');\n}\n\nfunction generateParticleEmitterPopcornChunk (emitter: ParticleEmitterPopcorn): string {\n    return generateBlockStart('ParticleEmitterPopcorn', emitter.Name) +\n        generateNodeProps(emitter) +\n        (emitter.Flags & ParticleEmitterPopcornFlags.Unshaded ? generateBooleanProp('Unshaded') : '') +\n        (emitter.Flags & ParticleEmitterPopcornFlags.SortPrimsFarZ ? generateBooleanProp('SortPrimsFarZ') : '') +\n        (emitter.Flags & ParticleEmitterPopcornFlags.Unfogged ? generateBooleanProp('Unfogged') : '') +\n        generateAnimVectorProp('LifeSpan', emitter.LifeSpan, null) +\n        generateAnimVectorProp('EmissionRate', emitter.EmissionRate, 0) +\n        generateAnimVectorProp('Speed', emitter.Speed, 0) +\n        generateColorProp('Color', emitter.Color, true) +\n        generateAnimVectorProp('Alpha', emitter.Alpha, 1) +\n        generateIntPropIfNotEmpty('ReplaceableId', emitter.ReplaceableId, 0, null) +\n        generateWrappedStringProp('Path', emitter.Path, false) +\n        generateWrappedStringProp('AnimVisibilityGuide', emitter.AnimVisibilityGuide, false) +\n        generateAnimVectorProp('Visibility', emitter.Visibility) +\n        generateBlockEnd();\n}\n\nconst generators: ((model: Model) => string)[] = [\n    generateVersion,\n    generateModel,\n    generateSequences,\n    generateGlobalSequences,\n    generateTextures,\n    generateMaterials,\n    generateTextureAnims,\n    generateGeosets,\n    generateGeosetAnims,\n    generateBones,\n    generateLights,\n    generateHelpers,\n    generateAttachments,\n    generatePivotPoints,\n    generateParticleEmitters,\n    generateParticleEmitters2,\n    generateRibbonEmitters,\n    generateEventObjects,\n    generateCameras,\n    generateCollisionShapes,\n    generateFaceFX,\n    generateBindPose,\n    generateParticleEmitterPopcorn\n];\n\nexport function generate (model: Model): string {\n    let res = '';\n\n    for (const generator of generators) {\n        res += generator(model);\n    }\n\n    return res;\n}\n","import {\n    Model, Material, Layer, AnimVector, LineType, TVertexAnim, Geoset, GeosetAnim, Node,\n    Bone, Light, Attachment, ParticleEmitter2, ParticleEmitter2FramesFlags, RibbonEmitter, Camera, EventObject,\n    CollisionShape, CollisionShapeType, ParticleEmitter, BindPose, ParticleEmitterPopcorn\n} from '../model';\nimport { LAYER_TEXTURE_ID_MAP } from '../renderer/util';\n\nconst BIG_ENDIAN = true;\nconst NONE = -1;\n\nclass Stream {\n    private readonly ab: ArrayBuffer;\n    private readonly uint: Uint8Array;\n    private readonly view: DataView;\n    private pos: number;\n\n    constructor (arrayBuffer: ArrayBuffer) {\n        this.ab = arrayBuffer;\n        this.uint = new Uint8Array(this.ab);\n        this.view = new DataView(this.ab);\n        this.pos = 0;\n    }\n\n    public keyword (keyword: string): void {\n        this.uint[this.pos    ] = keyword.charCodeAt(0);\n        this.uint[this.pos + 1] = keyword.charCodeAt(1);\n        this.uint[this.pos + 2] = keyword.charCodeAt(2);\n        this.uint[this.pos + 3] = keyword.charCodeAt(3);\n\n        this.pos += 4;\n    }\n\n    public uint8 (num: number): void {\n        this.view.setUint8(this.pos, num);\n        this.pos += 1;\n    }\n\n    public uint16 (num: number): void {\n        this.view.setUint16(this.pos, num, BIG_ENDIAN);\n        this.pos += 2;\n    }\n\n    public int32 (num: number): void {\n        this.view.setInt32(this.pos, num, BIG_ENDIAN);\n        this.pos += 4;\n    }\n\n    public uint32 (num: number): void {\n        this.view.setUint32(this.pos, num, BIG_ENDIAN);\n        this.pos += 4;\n    }\n\n    public float32 (num: number): void {\n        this.view.setFloat32(this.pos, num, BIG_ENDIAN);\n        this.pos += 4;\n    }\n\n    public float32Array (arr: Float32Array): void {\n        for (let i = 0; i < arr.length; ++i) {\n            this.float32(arr[i]);\n        }\n    }\n\n    public uint8Array (arr: Uint8Array): void {\n        for (let i = 0; i < arr.length; ++i) {\n            this.uint8(arr[i]);\n        }\n    }\n\n    public uint16Array (arr: Uint16Array): void {\n        for (let i = 0; i < arr.length; ++i) {\n            this.uint16(arr[i]);\n        }\n    }\n\n    public int32Array (arr: Int32Array): void {\n        for (let i = 0; i < arr.length; ++i) {\n            this.int32(arr[i]);\n        }\n    }\n\n    public uint32Array (arr: Uint32Array): void {\n        for (let i = 0; i < arr.length; ++i) {\n            this.uint32(arr[i]);\n        }\n    }\n\n    public str (str: string, len: number): void {\n        for (let i = 0; i < len; ++i, ++this.pos) {\n            this.uint[this.pos] = i < str.length ? str.charCodeAt(i) : 0;\n        }\n    }\n\n    public animVector (animVector: AnimVector, type: AnimVectorType): void {\n        const isInt = type === AnimVectorType.INT1;\n\n        this.int32(animVector.Keys.length);\n        this.int32(animVector.LineType);\n        this.int32(animVector.GlobalSeqId !== null ? animVector.GlobalSeqId : NONE);\n\n        for (const keyFrame of animVector.Keys) {\n            this.int32(keyFrame.Frame);\n            if (isInt) {\n                this.int32Array(keyFrame.Vector as Int32Array);\n            } else {\n                this.float32Array(keyFrame.Vector as Float32Array);\n            }\n            if (animVector.LineType === LineType.Hermite || animVector.LineType === LineType.Bezier) {\n                if (isInt) {\n                    this.int32Array(keyFrame.InTan as Int32Array);\n                    this.int32Array(keyFrame.OutTan as Int32Array);\n                } else {\n                    this.float32Array(keyFrame.InTan as Float32Array);\n                    this.float32Array(keyFrame.OutTan as Float32Array);\n                }\n            }\n        }\n    }\n}\n\ninterface ObjWithExtent {\n    BoundsRadius: number;\n    MinimumExtent: Float32Array;\n    MaximumExtent: Float32Array;\n}\n\nfunction generateExtent (obj: ObjWithExtent, stream: Stream): void {\n    stream.float32(obj.BoundsRadius || 0);\n\n    for (const key of ['MinimumExtent', 'MaximumExtent']) {\n        stream.float32Array(obj[key]);\n    }\n}\n\n\nenum AnimVectorType {\n    INT1,\n    FLOAT1,\n    FLOAT3,\n    FLOAT4\n}\n\nconst animVectorSize = {\n    [AnimVectorType.INT1]: 1,\n    [AnimVectorType.FLOAT1]: 1,\n    [AnimVectorType.FLOAT3]: 3,\n    [AnimVectorType.FLOAT4]: 4\n};\n\nfunction byteLengthAnimVector (animVector: AnimVector, type: AnimVectorType): number {\n    return 4 /* key count */ +\n        4 /* LineType */ +\n        4 /* GlobalSeqId */ +\n        animVector.Keys.length * (\n            4 /* frame */ +\n            4 * animVectorSize[type] *\n                (animVector.LineType === LineType.Hermite || animVector.LineType === LineType.Bezier ? 3 : 1)\n        );\n}\n\n\nfunction sum (arr) {\n    return arr.reduce((a, b) => {\n        return a + b;\n    }, 0);\n}\n\n\nfunction byteLengthVersion (): number {\n    return 4 /* keyword */ +\n        4 /* size */ +\n        4 /* version */;\n}\n\nfunction generateVersion (model: Model, stream: Stream): void {\n    stream.keyword('VERS');\n    stream.int32(4);\n    stream.int32(model.Version);\n}\n\n\nconst MODEL_NAME_LENGTH = 0x150;\nfunction byteLengthModelInfo (): number {\n    return 4 /* keyword */ +\n        4 /* size */ +\n        MODEL_NAME_LENGTH +\n        4 /* 4-byte zero ? */ +\n        4 * 7 /* extent */ +\n        4; /* blend time */\n}\n\nfunction generateModelInfo (model: Model, stream: Stream): void {\n    stream.keyword('MODL');\n    stream.int32(byteLengthModelInfo() - 8);\n    stream.str(model.Info.Name, MODEL_NAME_LENGTH);\n    stream.int32(0);\n    generateExtent(model.Info, stream);\n    stream.int32(model.Info.BlendTime);\n}\n\n\nconst MODEL_SEQUENCE_NAME_LENGTH = 0x50;\nfunction byteLengthSequence (): number {\n    return MODEL_SEQUENCE_NAME_LENGTH +\n        4 * 2 /* interval */ +\n        4 /* MoveSpeed */ +\n        4 /* NonLooping */ +\n        4 /* Rarity */ +\n        4 +\n        4 * 7; /* extent */\n}\n\nfunction byteLengthSequences (model: Model): number {\n    if (!model.Sequences.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.Sequences.map(byteLengthSequence));\n}\n\nfunction generateSequences (model: Model, stream: Stream): void {\n    if (!model.Sequences.length) {\n        return;\n    }\n\n    stream.keyword('SEQS');\n    stream.int32(byteLengthSequences(model) - 8);\n\n    for (const sequence of model.Sequences) {\n        stream.str(sequence.Name, MODEL_SEQUENCE_NAME_LENGTH);\n        stream.int32(sequence.Interval[0]);\n        stream.int32(sequence.Interval[1]);\n        stream.float32(sequence.MoveSpeed);\n        stream.int32(sequence.NonLooping ? 1 : 0);\n        stream.float32(sequence.Rarity);\n        stream.int32(0);\n        generateExtent(sequence, stream);\n    }\n}\n\n\nfunction byteLengthGlobalSequences (model: Model): number {\n    if (!model.GlobalSequences || !model.GlobalSequences.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        4 * model.GlobalSequences.length;\n}\n\nfunction generateGlobalSequences (model: Model, stream: Stream): void {\n    if (!model.GlobalSequences || !model.GlobalSequences.length) {\n        return;\n    }\n\n    stream.keyword('GLBS');\n    stream.int32(model.GlobalSequences.length * 4);\n    for (const duration of model.GlobalSequences) {\n        stream.int32(duration);\n    }\n}\n\n\nfunction byteLengthLayer (model: Model, layer: Layer): number {\n    return 4 /* size */ +\n        4 /* FilterMode */ +\n        4 /* Shading */ +\n        4 /* static TextureID */ +\n        4 /* TVertexAnimId */ +\n        4 +\n        4 /* static Alpha */ +\n        (model.Version >= 900 ? 4 : 0) /* EmissiveGain */ +\n        (model.Version >= 1000 ?\n            4 * 3 /* FresnelColor */ +\n            4 /* FresnelOpacity */ +\n            4 /* FresnelTeamColor */ :\n            0\n        ) +\n        (model.Version >= 1100 ?\n            4 /* ShaderTypeId */ +\n            4 /* textureCount */ +\n            LAYER_TEXTURE_ID_MAP.reduce((acc, name) => {\n                return acc + (\n                    typeof layer[name] !== 'undefined' ?\n                        4 /* textureId */ +\n                        4 /* textureType */ +\n                        (typeof layer[name] === 'object' ?\n                            4 /* keyword */ + byteLengthAnimVector(layer[name] as AnimVector, AnimVectorType.INT1) :\n                            0\n                        ) :\n                    0\n                );\n            }, 0) :\n            0\n        ) +\n        (layer.Alpha !== null && typeof layer.Alpha !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(layer.Alpha as AnimVector, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (model.Version < 1100 && layer.TextureID !== null && typeof layer.TextureID !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(layer.TextureID as AnimVector, AnimVectorType.INT1) :\n            0\n        ) +\n        (model.Version >= 900 && layer.EmissiveGain !== undefined && layer.EmissiveGain !== null && typeof layer.EmissiveGain !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(layer.EmissiveGain as AnimVector, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (model.Version >= 1000 && layer.FresnelColor !== undefined && layer.FresnelColor !== null && !(layer.FresnelColor instanceof Float32Array) ?\n            4 /* keyword */ + byteLengthAnimVector(layer.FresnelColor as AnimVector, AnimVectorType.FLOAT3) :\n            0\n        ) +\n        (model.Version >= 1000 && layer.FresnelOpacity !== undefined && layer.FresnelOpacity !== null && typeof layer.FresnelOpacity !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(layer.FresnelOpacity as AnimVector, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (model.Version >= 1000 && layer.FresnelTeamColor !== undefined && layer.FresnelTeamColor !== null && typeof layer.FresnelTeamColor !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(layer.FresnelTeamColor as AnimVector, AnimVectorType.FLOAT1) :\n            0\n        );\n}\n\nfunction byteLengthMaterial (model: Model, material: Material): number {\n    return 4 /* size */ +\n        4 /* PriorityPlane */ +\n        4 /* RenderMode */ +\n        4 /* LAYS keyword */ +\n        4 /* layer count */ +\n        (model.Version >= 900 && model.Version < 1100 ? 80 : 0) /* Shader */ +\n        sum(material.Layers.map(layer => byteLengthLayer(model, layer)));\n}\n\nfunction byteLengthMaterials (model: Model): number {\n    if (!model.Materials.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.Materials.map(material => byteLengthMaterial(model, material)));\n}\n\nfunction generateMaterials (model: Model, stream: Stream): void {\n    if (!model.Materials.length) {\n        return;\n    }\n\n    stream.keyword('MTLS');\n    stream.int32(byteLengthMaterials(model) - 8);\n\n    for (const material of model.Materials) {\n        stream.int32(byteLengthMaterial(model, material));\n        stream.int32(material.PriorityPlane);\n        stream.int32(material.RenderMode);\n        if (model.Version >= 900 && model.Version < 1100) {\n            stream.str(material.Shader || '', 80);\n        }\n        stream.keyword('LAYS');\n        stream.int32(material.Layers.length);\n\n        for (const layer of material.Layers) {\n            stream.int32(byteLengthLayer(model, layer));\n            stream.int32(layer.FilterMode);\n            stream.int32(layer.Shading);\n            stream.int32(model.Version < 1100 && typeof layer.TextureID === 'number' ? layer.TextureID : 0);\n            stream.int32(layer.TVertexAnimId !== null ? layer.TVertexAnimId : NONE);\n            stream.int32(layer.CoordId);\n            stream.float32(typeof layer.Alpha === 'number' ? layer.Alpha : 1);\n\n            if (model.Version >= 900) {\n                stream.float32(typeof layer.EmissiveGain === 'number' ? layer.EmissiveGain : 1);\n\n                if (model.Version >= 1000) {\n                    stream.float32Array(layer.FresnelColor instanceof Float32Array ? layer.FresnelColor : new Float32Array([1, 1, 1]));\n                    stream.float32(typeof layer.FresnelOpacity === 'number' ? layer.FresnelOpacity : 0);\n                    stream.float32(typeof layer.FresnelTeamColor === 'number' ? layer.FresnelTeamColor : 0);\n                }\n            }\n\n            if (model.Version >= 1100) {\n                stream.int32(layer.ShaderTypeId || 0);\n                const textures = LAYER_TEXTURE_ID_MAP.filter(name => layer[name] !== undefined).length;\n                stream.int32(textures);\n                for (let i = 0; i < LAYER_TEXTURE_ID_MAP.length; ++i) {\n                    const id = layer[LAYER_TEXTURE_ID_MAP[i]];\n                    if (id === undefined) {\n                        continue;\n                    }\n                    stream.int32(typeof id === 'number' ? id : 0);\n                    stream.int32(typeof id === 'number' ? i : 0); // ?\n                    if (typeof id === 'object') {\n                        stream.keyword('KMTF');\n                        stream.animVector(id, AnimVectorType.INT1);\n                    }\n                }\n            }\n\n            if (layer.Alpha && typeof layer.Alpha !== 'number') {\n                stream.keyword('KMTA');\n                stream.animVector(layer.Alpha, AnimVectorType.FLOAT1);\n            }\n            if (model.Version < 1100 && layer.TextureID && typeof layer.TextureID !== 'number') {\n                stream.keyword('KMTF');\n                stream.animVector(layer.TextureID, AnimVectorType.INT1);\n            }\n            if (model.Version >= 900 && layer.EmissiveGain && typeof layer.EmissiveGain !== 'number') {\n                stream.keyword('KMTE');\n                stream.animVector(layer.EmissiveGain, AnimVectorType.FLOAT1);\n            }\n            if (model.Version >= 1000 && layer.FresnelColor && !(layer.FresnelColor instanceof Float32Array)) {\n                stream.keyword('KFC3');\n                stream.animVector(layer.FresnelColor, AnimVectorType.FLOAT3);\n            }\n            if (model.Version >= 1000 && layer.FresnelOpacity && typeof layer.FresnelOpacity !== 'number') {\n                stream.keyword('KFCA');\n                stream.animVector(layer.FresnelOpacity, AnimVectorType.FLOAT1);\n            }\n            if (model.Version >= 1000 && layer.FresnelTeamColor && typeof layer.FresnelTeamColor !== 'number') {\n                stream.keyword('KFTC');\n                stream.animVector(layer.FresnelTeamColor, AnimVectorType.FLOAT1);\n            }\n        }\n    }\n}\n\n\nconst MODEL_TEXTURE_PATH_LENGTH = 0x100;\nfunction byteLengthTexture (): number {\n    return 4 /* ReplaceableId */ +\n        MODEL_TEXTURE_PATH_LENGTH +\n        4 /* str trailing zero ? */ +\n        4 /* Flags */;\n}\n\nfunction byteLengthTextures (model: Model): number {\n    if (!model.Textures.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.Textures.map(_texture => byteLengthTexture()));\n}\n\nfunction generateTextures (model: Model, stream: Stream): void {\n    if (!model.Textures.length) {\n        return;\n    }\n\n    stream.keyword('TEXS');\n    stream.int32(byteLengthTextures(model) - 8);\n\n    for (const texture of model.Textures) {\n        stream.int32(texture.ReplaceableId);\n        stream.str(texture.Image, MODEL_TEXTURE_PATH_LENGTH);\n        stream.int32(0);\n        stream.int32(texture.Flags);\n    }\n}\n\n\nfunction byteLengthTextureAnim (anim: TVertexAnim): number {\n    return 4 /* size */ +\n        (anim.Translation ? 4 /* keyword */ + byteLengthAnimVector(anim.Translation, AnimVectorType.FLOAT3) : 0) +\n        (anim.Rotation ? 4 /* keyword */ + byteLengthAnimVector(anim.Rotation, AnimVectorType.FLOAT4) : 0) +\n        (anim.Scaling ? 4 /* keyword */ + byteLengthAnimVector(anim.Scaling, AnimVectorType.FLOAT3) : 0);\n}\n\nfunction byteLengthTextureAnims (model: Model): number {\n    if (!model.TextureAnims || !model.TextureAnims.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.TextureAnims.map(anim => byteLengthTextureAnim(anim)));\n}\n\nfunction generateTextureAnims (model: Model, stream: Stream): void {\n    if (!model.TextureAnims || !model.TextureAnims.length) {\n        return;\n    }\n\n    stream.keyword('TXAN');\n    stream.int32(byteLengthTextureAnims(model) - 8);\n\n    for (const anim of model.TextureAnims) {\n        stream.int32(byteLengthTextureAnim(anim));\n\n        if (anim.Translation) {\n            stream.keyword('KTAT');\n            stream.animVector(anim.Translation, AnimVectorType.FLOAT3);\n        }\n        if (anim.Rotation) {\n            stream.keyword('KTAR');\n            stream.animVector(anim.Rotation, AnimVectorType.FLOAT4);\n        }\n        if (anim.Scaling) {\n            stream.keyword('KTAS');\n            stream.animVector(anim.Scaling, AnimVectorType.FLOAT3);\n        }\n    }\n}\n\n\nfunction byteLengthGeoset (model: Model, geoset: Geoset): number {\n    return 4 /* size */ +\n        4 /* VRTX keyword */ +\n        4 /* vertices count */ +\n        4 * geoset.Vertices.length /* vertices data */ +\n        4 /* NRMS keyword */ +\n        4 /* normals count */ +\n        4 * geoset.Normals.length /* normals data */ +\n        4 /* PTYP keyword */ +\n        4 /* primitive count */ +\n        4 /* int \"4\" */ +\n        4 /* PCNT keyword */ +\n        4 /* face group count */ +\n        4 /* faces count */ +\n        4 /* PVTX keyword */ +\n        4 /* indices count */ +\n        2 * geoset.Faces.length /* indices data */ +\n        4 /* GNDX keyword */ +\n        4 /* vertex group count */ +\n        geoset.VertexGroup.length /* vertex group data */ +\n        4 /* MTGC keyword */ +\n        4 /* group count */ +\n        4 * geoset.Groups.length /* group data */ +\n        4 /* MATS keyword */ +\n        4 /* total group count */ +\n        4 * geoset.TotalGroupsCount /* groups data */ +\n        4 /* MaterialID */ +\n        4 /* SelectionGroup */ +\n        4 /* Unselectable */ +\n        (model.Version >= 900 ?\n            4 /* LevelOfDetail */ +\n            80 /* Name */ :\n            0\n        ) +\n        ((model.Version >= 900 && geoset.Tangents?.length) ?\n            4 /* TANG keyword */ +\n            4 /* Tangents count */ +\n            4 * geoset.Tangents.length /* Tangents data */ :\n            0\n        ) +\n        ((model.Version >= 900 && geoset.SkinWeights?.length) ?\n            4 /* SKIN keyword */ +\n            4 /* SkinWeights count */ +\n            geoset.SkinWeights.length /* SkinWeights data */ :\n            0\n        ) +\n        4 * 7 /* extent */ +\n        4 /* geoset anim count */ +\n        4 * 7 * geoset.Anims.length /* geoset anim data */ +\n        4 /* UVAS keyword */ +\n        4 /* TVertices count */ +\n        sum(geoset.TVertices.map(tvertices =>\n            4 /* UVBS keyword */ +\n            4 /* texture coord count */ +\n            4 * tvertices.length /* texture coord data */\n        ));\n}\n\nfunction byteLengthGeosets (model: Model): number {\n    if (!model.Geosets.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.Geosets.map(geoset => byteLengthGeoset(model, geoset)));\n}\n\nfunction generateGeosets (model: Model, stream: Stream): void {\n    if (!model.Geosets.length) {\n        return;\n    }\n\n    stream.keyword('GEOS');\n    stream.int32(byteLengthGeosets(model) - 8);\n\n    for (const geoset of model.Geosets) {\n        stream.int32(byteLengthGeoset(model, geoset));\n\n        stream.keyword('VRTX');\n        stream.int32(geoset.Vertices.length / 3);\n        stream.float32Array(geoset.Vertices);\n\n        stream.keyword('NRMS');\n        stream.int32(geoset.Normals.length / 3);\n        stream.float32Array(geoset.Normals);\n\n        stream.keyword('PTYP');\n        stream.int32(1);\n        stream.int32(4);\n\n        stream.keyword('PCNT');\n        stream.int32(1);\n        stream.int32(geoset.Faces.length);\n\n        stream.keyword('PVTX');\n        stream.int32(geoset.Faces.length);\n        stream.uint16Array(geoset.Faces);\n\n        stream.keyword('GNDX');\n        stream.int32(geoset.VertexGroup.length);\n        stream.uint8Array(geoset.VertexGroup);\n\n        stream.keyword('MTGC');\n        stream.int32(geoset.Groups.length);\n        for (let i = 0; i < geoset.Groups.length; ++i) {\n            stream.int32(geoset.Groups[i].length);\n        }\n\n        stream.keyword('MATS');\n        stream.int32(geoset.TotalGroupsCount);\n        for (const group of geoset.Groups) {\n            for (const index of group) {\n                stream.int32(index);\n            }\n        }\n\n        stream.int32(geoset.MaterialID);\n        stream.int32(geoset.SelectionGroup);\n        stream.int32(geoset.Unselectable ? 4 : 0);\n\n        if (model.Version >= 900) {\n            stream.int32(typeof geoset.LevelOfDetail === 'number' ? geoset.LevelOfDetail : -1);\n            stream.str(geoset.Name || '', 80);\n        }\n\n        generateExtent(geoset, stream);\n\n        stream.int32(geoset.Anims.length);\n        for (const anim of geoset.Anims) {\n            generateExtent(anim, stream);\n        }\n\n        if (model.Version >= 900) {\n            if (geoset.Tangents && geoset.Tangents.length) {\n                stream.keyword('TANG');\n                stream.int32(geoset.Tangents.length / 4);\n                stream.float32Array(geoset.Tangents);\n            }\n            if (geoset.SkinWeights && geoset.SkinWeights.length) {\n                stream.keyword('SKIN');\n                stream.int32(geoset.SkinWeights.length);\n                stream.uint8Array(geoset.SkinWeights);\n            }\n        }\n\n        stream.keyword('UVAS');\n        stream.int32(geoset.TVertices.length);\n\n        for (const tvertices of geoset.TVertices) {\n            stream.keyword('UVBS');\n            stream.int32(tvertices.length / 2);\n            stream.float32Array(tvertices);\n        }\n    }\n}\n\n\nfunction byteLengthGeosetAnim (anim: GeosetAnim): number {\n    return 4 /* size */ +\n        4 /* static Alpha */ +\n        4 /* Flags */ +\n        4 * 3 /* static Color */ +\n        4 /* GeosetId */ +\n        (typeof anim.Alpha !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(anim.Alpha, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (anim.Color && !(anim.Color instanceof Float32Array) ?\n            4 /* keyword */ + byteLengthAnimVector(anim.Color, AnimVectorType.FLOAT3) :\n            0\n        );\n}\n\nfunction byteLengthGeosetAnims (model: Model): number {\n    if (!model.GeosetAnims.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.GeosetAnims.map(anim => byteLengthGeosetAnim(anim)));\n}\n\nfunction generateGeosetAnims (model: Model, stream: Stream): void {\n    if (!model.GeosetAnims.length) {\n        return;\n    }\n\n    stream.keyword('GEOA');\n    stream.int32(byteLengthGeosetAnims(model) - 8);\n\n    for (const anim of model.GeosetAnims) {\n        stream.int32(byteLengthGeosetAnim(anim));\n        stream.float32(typeof anim.Alpha === 'number' ? anim.Alpha : 1);\n        stream.int32(anim.Flags);\n        if (anim.Color && anim.Color instanceof Float32Array) {\n            stream.float32(anim.Color[0]);\n            stream.float32(anim.Color[1]);\n            stream.float32(anim.Color[2]);\n        } else {\n            stream.float32(1);\n            stream.float32(1);\n            stream.float32(1);\n        }\n        stream.int32(anim.GeosetId !== null ? anim.GeosetId : NONE);\n\n        if (anim.Alpha !== null && typeof anim.Alpha !== 'number') {\n            stream.keyword('KGAO');\n            stream.animVector(anim.Alpha, AnimVectorType.FLOAT1);\n        }\n        if (anim.Color && !(anim.Color instanceof Float32Array)) {\n            stream.keyword('KGAC');\n            stream.animVector(anim.Color, AnimVectorType.FLOAT3);\n        }\n    }\n}\n\n\nconst MODEL_NODE_NAME_LENGTH = 0x50;\nfunction byteLengthNode (node: Node): number {\n    return 4 /* size */ +\n        MODEL_NODE_NAME_LENGTH +\n        4 /* ObjectId */ +\n        4 /* Parent */ +\n        4 /* Flags */ +\n        (node.Translation ? 4 /*keyword */ + byteLengthAnimVector(node.Translation, AnimVectorType.FLOAT3) : 0) +\n        (node.Rotation ? 4 /*keyword */ + byteLengthAnimVector(node.Rotation, AnimVectorType.FLOAT4) : 0) +\n        (node.Scaling ? 4 /*keyword */ + byteLengthAnimVector(node.Scaling, AnimVectorType.FLOAT3) : 0);\n}\n\nfunction byteLengthBone (bone: Bone): number {\n    return byteLengthNode(bone) +\n        4 /* GeosetId */ +\n        4; /* GeosetAnimId */\n}\n\nfunction byteLengthBones (model: Model): number {\n    if (!model.Bones.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.Bones.map(byteLengthBone));\n}\n\nfunction generateNode (node: Node, stream: Stream): void {\n    stream.int32(byteLengthNode(node));\n    stream.str(node.Name, MODEL_NODE_NAME_LENGTH);\n    stream.int32(node.ObjectId !== null ? node.ObjectId : NONE);\n    stream.int32(node.Parent !== null ? node.Parent : NONE);\n    stream.int32(node.Flags);\n\n    if (node.Translation) {\n        stream.keyword('KGTR');\n        stream.animVector(node.Translation, AnimVectorType.FLOAT3);\n    }\n\n    if (node.Rotation) {\n        stream.keyword('KGRT');\n        stream.animVector(node.Rotation, AnimVectorType.FLOAT4);\n    }\n\n    if (node.Scaling) {\n        stream.keyword('KGSC');\n        stream.animVector(node.Scaling, AnimVectorType.FLOAT3);\n    }\n}\n\nfunction generateBones (model: Model, stream: Stream): void {\n    if (!model.Bones.length) {\n        return;\n    }\n\n    stream.keyword('BONE');\n    stream.int32(byteLengthBones(model) - 8);\n\n    for (const bone of model.Bones) {\n        generateNode(bone, stream);\n        stream.int32(bone.GeosetId !== null ? bone.GeosetId : NONE);\n        stream.int32(bone.GeosetAnimId !== null ? bone.GeosetAnimId : NONE);\n    }\n}\n\n\nfunction byteLengthLight (light: Light): number {\n    return 4 /* size */ +\n        byteLengthNode(light) +\n        4 /* LightType */ +\n        4 /* AttenuationStart */ +\n        4 /* AttenuationEnd */ +\n        4 * 3 /* static Color */ +\n        4 /* static Intensity */ +\n        4 * 3 /* static AmbColor */ +\n        4 /* static AmbIntensity */ +\n        (light.Visibility ? 4 /* keyword */ + byteLengthAnimVector(light.Visibility, AnimVectorType.FLOAT1) : 0) +\n        (light.Color && !(light.Color instanceof Float32Array) ?\n            4 /* keyword */ + byteLengthAnimVector(light.Color as AnimVector, AnimVectorType.FLOAT3) :\n            0\n        ) +\n        (light.Intensity && typeof light.Intensity !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(light.Intensity, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (light.AttenuationStart && typeof light.AttenuationStart !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(light.AttenuationStart, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (light.AttenuationEnd && typeof light.AttenuationEnd !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(light.AttenuationEnd, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (light.AmbColor && !(light.AmbColor instanceof Float32Array) ?\n            4 /* keyword */ + byteLengthAnimVector(light.AmbColor as AnimVector, AnimVectorType.FLOAT3) :\n            0\n        ) +\n        (light.AmbIntensity && typeof light.AmbIntensity !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(light.AmbIntensity, AnimVectorType.FLOAT1) :\n            0\n        );\n}\n\nfunction byteLengthLights (model: Model): number {\n    if (!model.Lights.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.Lights.map(byteLengthLight));\n}\n\nfunction generateLights (model: Model, stream: Stream): void {\n    if (!model.Lights.length) {\n        return;\n    }\n\n    stream.keyword('LITE');\n    stream.int32(byteLengthLights(model) - 8);\n\n    for (const light of model.Lights) {\n        stream.int32(byteLengthLight(light));\n        generateNode(light, stream);\n        stream.int32(light.LightType);\n        stream.float32(typeof light.AttenuationStart === 'number' ? light.AttenuationStart : 0);\n        stream.float32(typeof light.AttenuationEnd === 'number' ? light.AttenuationEnd : 0);\n\n        if (light.Color instanceof Float32Array) {\n            stream.float32(light.Color[0]);\n            stream.float32(light.Color[1]);\n            stream.float32(light.Color[2]);\n        } else {\n            stream.float32(1);\n            stream.float32(1);\n            stream.float32(1);\n        }\n\n        stream.float32(typeof light.Intensity === 'number' ? light.Intensity : 0);\n\n        if (light.AmbColor instanceof Float32Array) {\n            stream.float32(light.AmbColor[0]);\n            stream.float32(light.AmbColor[1]);\n            stream.float32(light.AmbColor[2]);\n        } else {\n            stream.float32(1);\n            stream.float32(1);\n            stream.float32(1);\n        }\n\n        stream.float32(typeof light.AmbIntensity === 'number' ? light.AmbIntensity : 0);\n\n        if (light.Intensity && typeof light.Intensity !== 'number') {\n            stream.keyword('KLAI');\n            stream.animVector(light.Intensity, AnimVectorType.FLOAT1);\n        }\n        if (light.Visibility) {\n            stream.keyword('KLAV');\n            stream.animVector(light.Visibility, AnimVectorType.FLOAT1);\n        }\n        if (light.Color && !(light.Color instanceof Float32Array)) {\n            stream.keyword('KLAC');\n            stream.animVector(light.Color, AnimVectorType.FLOAT3);\n        }\n        if (light.AmbColor && !(light.AmbColor instanceof Float32Array)) {\n            stream.keyword('KLBC');\n            stream.animVector(light.AmbColor, AnimVectorType.FLOAT3);\n        }\n        if (light.AmbIntensity && typeof light.AmbIntensity !== 'number') {\n            stream.keyword('KLBI');\n            stream.animVector(light.AmbIntensity, AnimVectorType.FLOAT1);\n        }\n        if (light.AttenuationStart && typeof light.AttenuationStart !== 'number') {\n            stream.keyword('KLAS');\n            stream.animVector(light.AttenuationStart, AnimVectorType.INT1);\n        }\n        if (light.AttenuationEnd && typeof light.AttenuationEnd !== 'number') {\n            stream.keyword('KLAE');\n            stream.animVector(light.AttenuationEnd, AnimVectorType.INT1);\n        }\n    }\n}\n\n\nfunction byteLengthHelpers (model: Model): number {\n    if (model.Helpers.length === 0) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.Helpers.map(byteLengthNode));\n}\n\nfunction generateHelpers (model: Model, stream: Stream): void {\n    if (model.Helpers.length === 0) {\n        return;\n    }\n\n    stream.keyword('HELP');\n    stream.int32(byteLengthHelpers(model) - 8);\n\n    for (const helper of model.Helpers) {\n        generateNode(helper, stream);\n    }\n}\n\n\nconst MODEL_ATTACHMENT_PATH_LENGTH = 0x100;\nfunction byteLengthAttachment (attachment: Attachment): number {\n    return 4 /* size */ +\n        byteLengthNode(attachment) +\n        MODEL_ATTACHMENT_PATH_LENGTH +\n        4 /* zero ? */ +\n        4 /* AttachmentID */ +\n        (attachment.Visibility ?\n            4 /* keyword */ + byteLengthAnimVector(attachment.Visibility, AnimVectorType.FLOAT1) :\n            0\n        );\n}\n\nfunction byteLengthAttachments (model: Model): number {\n    if (model.Attachments.length === 0) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.Attachments.map(byteLengthAttachment));\n}\n\nfunction generateAttachments (model: Model, stream: Stream): void {\n    if (model.Attachments.length === 0) {\n        return;\n    }\n\n    stream.keyword('ATCH');\n    stream.int32(byteLengthAttachments(model) - 8);\n\n    for (const attachment of model.Attachments) {\n        stream.int32(byteLengthAttachment(attachment));\n        generateNode(attachment, stream);\n\n        stream.str(attachment.Path || '', MODEL_ATTACHMENT_PATH_LENGTH);\n        stream.int32(0);\n        stream.int32(attachment.AttachmentID);\n\n        if (attachment.Visibility) {\n            stream.keyword('KATV');\n            stream.animVector(attachment.Visibility, AnimVectorType.FLOAT1);\n        }\n    }\n}\n\n\nfunction byteLengthPivotPoints (model: Model): number {\n    if (!model.PivotPoints.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        4 * 3 * model.PivotPoints.length;\n}\n\nfunction generatePivotPoints (model: Model, stream: Stream): void {\n    if (!model.PivotPoints.length) {\n        return;\n    }\n\n    stream.keyword('PIVT');\n    stream.int32(model.PivotPoints.length * 4 * 3);\n\n    for (const point of model.PivotPoints) {\n        stream.float32Array(point);\n    }\n}\n\n\nconst MODEL_PARTICLE_EMITTER_PATH_LENGTH = 0x100;\nfunction byteLengthParticleEmitter (emitter: ParticleEmitter): number {\n    return 4 /* size */ +\n        byteLengthNode(emitter) +\n        4 /* EmissionRate */ +\n        4 /* Gravity */ +\n        4 /* Longitude */ +\n        4 /* Latitude */ +\n        MODEL_PARTICLE_EMITTER_PATH_LENGTH +\n        4 +\n        4 /* LifeSpan */ +\n        4 /* InitVelocity */ +\n        (emitter.Visibility && typeof emitter.Visibility !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Visibility, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.EmissionRate && typeof emitter.EmissionRate !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.EmissionRate, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Gravity && typeof emitter.Gravity !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Gravity, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Longitude && typeof emitter.Longitude !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Longitude, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Latitude && typeof emitter.Latitude !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Latitude, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.LifeSpan && typeof emitter.LifeSpan !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.LifeSpan, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.InitVelocity && typeof emitter.InitVelocity !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.InitVelocity, AnimVectorType.FLOAT1) :\n            0\n        );\n}\n\nfunction byteLengthParticleEmitters (model: Model): number {\n    if (!model.ParticleEmitters.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.ParticleEmitters.map(byteLengthParticleEmitter));\n}\n\nfunction generateParticleEmitters (model: Model, stream: Stream): void {\n    if (!model.ParticleEmitters.length) {\n        return;\n    }\n\n    stream.keyword('PREM');\n    stream.int32(byteLengthParticleEmitters(model) - 8);\n\n    for (const emitter of model.ParticleEmitters) {\n        stream.int32(byteLengthParticleEmitter(emitter));\n        generateNode(emitter, stream);\n\n        stream.float32(typeof emitter.EmissionRate === 'number' ? emitter.EmissionRate : 0);\n        stream.float32(typeof emitter.Gravity === 'number' ? emitter.Gravity : 0);\n        stream.float32(typeof emitter.Longitude === 'number' ? emitter.Longitude : 0);\n        stream.float32(typeof emitter.Latitude === 'number' ? emitter.Latitude : 0);\n        stream.str(emitter.Path, MODEL_PARTICLE_EMITTER_PATH_LENGTH);\n        stream.int32(0);\n        stream.float32(typeof emitter.LifeSpan === 'number' ? emitter.LifeSpan : 0);\n        stream.float32(typeof emitter.InitVelocity === 'number' ? emitter.InitVelocity : 0);\n\n        if (emitter.Visibility && typeof emitter.Visibility !== 'number') {\n            stream.keyword('KPEV');\n            stream.animVector(emitter.Visibility, AnimVectorType.FLOAT1);\n        }\n        if (emitter.EmissionRate && typeof emitter.EmissionRate !== 'number') {\n            stream.keyword('KPEE');\n            stream.animVector(emitter.EmissionRate, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Gravity && typeof emitter.Gravity !== 'number') {\n            stream.keyword('KPEG');\n            stream.animVector(emitter.Gravity, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Longitude && typeof emitter.Longitude !== 'number') {\n            stream.keyword('KPLN');\n            stream.animVector(emitter.Longitude, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Latitude && typeof emitter.Latitude !== 'number') {\n            stream.keyword('KPLT');\n            stream.animVector(emitter.Latitude, AnimVectorType.FLOAT1);\n        }\n        if (emitter.LifeSpan && typeof emitter.LifeSpan !== 'number') {\n            stream.keyword('KPEL');\n            stream.animVector(emitter.LifeSpan, AnimVectorType.FLOAT1);\n        }\n        if (emitter.InitVelocity && typeof emitter.InitVelocity !== 'number') {\n            stream.keyword('KPES');\n            stream.animVector(emitter.InitVelocity, AnimVectorType.FLOAT1);\n        }\n    }\n}\n\n\nfunction byteLengthParticleEmitter2 (emitter: ParticleEmitter2): number {\n    return 4 /* size */ +\n        byteLengthNode(emitter) +\n        4 /* static Speed */ +\n        4 /* Variation */ +\n        4 /* static Latitude */ +\n        4 /* Gravity */ +\n        4 /* LifeSpan */ +\n        4 /* static EmissionRate */ +\n        4 /* static Length */ +\n        4 /* static Width */ +\n        4 /* FilterMode */ +\n        4 /* Rows */ +\n        4 /* Columns */ +\n        4 /* FrameFlags */ +\n        4 /* TailLength */ +\n        4 /* Time */ +\n        4 * 3 * 3 /* SegmentColor */ +\n        3 /* Alpha uint * 3 */ +\n        4 * 3 /* ParticleScaling */ +\n        4 * 3 /* LifeSpanUVAnim */ +\n        4 * 3 /* DecayUVAnim */ +\n        4 * 3 /* TailUVAnim */ +\n        4 * 3 /* TailDecayUVAnim */ +\n        4 /* TextureID */ +\n        4 /* Squirt */ +\n        4 /* PriorityPlane */ +\n        4 /* ReplaceableId */ +\n        (emitter.Visibility && typeof emitter.Visibility !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Visibility, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.EmissionRate && typeof emitter.EmissionRate !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.EmissionRate, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Width && typeof emitter.Width !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Width, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Length && typeof emitter.Length !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Length, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Speed && typeof emitter.Speed !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Speed, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Latitude && typeof emitter.Latitude !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Latitude, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Gravity && typeof emitter.Gravity !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Gravity, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Variation && typeof emitter.Variation !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Variation, AnimVectorType.FLOAT1) :\n            0\n        );\n}\n\nfunction byteLengthParticleEmitters2 (model: Model): number {\n    if (!model.ParticleEmitters2.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.ParticleEmitters2.map(byteLengthParticleEmitter2));\n}\n\nfunction generateParticleEmitters2 (model: Model, stream: Stream): void {\n    if (!model.ParticleEmitters2.length) {\n        return;\n    }\n\n    stream.keyword('PRE2');\n    stream.int32(byteLengthParticleEmitters2(model) - 8);\n\n    for (const emitter of model.ParticleEmitters2) {\n        stream.int32(byteLengthParticleEmitter2(emitter));\n        generateNode(emitter, stream);\n\n        stream.float32(typeof emitter.Speed === 'number' ? emitter.Speed : 0);\n        stream.float32(typeof emitter.Variation === 'number' ? emitter.Variation : 0);\n        stream.float32(typeof emitter.Latitude === 'number' ? emitter.Latitude : 0);\n        stream.float32(typeof emitter.Gravity === 'number' ? emitter.Gravity : 0);\n        stream.float32(emitter.LifeSpan);\n        stream.float32(typeof emitter.EmissionRate === 'number' ? emitter.EmissionRate : 0);\n        stream.float32(typeof emitter.Width === 'number' ? emitter.Width : 0);\n        stream.float32(typeof emitter.Length === 'number' ? emitter.Length : 0);\n\n        stream.int32(emitter.FilterMode);\n        stream.int32(emitter.Rows);\n        stream.int32(emitter.Columns);\n\n        if (emitter.FrameFlags & ParticleEmitter2FramesFlags.Head &&\n            emitter.FrameFlags & ParticleEmitter2FramesFlags.Tail) {\n            stream.int32(2);\n        } else if (emitter.FrameFlags & ParticleEmitter2FramesFlags.Tail) {\n            stream.int32(1);\n        } else if (emitter.FrameFlags & ParticleEmitter2FramesFlags.Head) {\n            stream.int32(0);\n        }\n\n        stream.float32(emitter.TailLength);\n        stream.float32(emitter.Time);\n\n        for (let i = 0; i < 3; ++i) {\n            for (let j = 0; j < 3; ++j) {\n                stream.float32(emitter.SegmentColor[i][j]);\n            }\n        }\n\n        for (let i = 0; i < 3; ++i) {\n            stream.uint8(emitter.Alpha[i]);\n        }\n\n        for (let i = 0; i < 3; ++i) {\n            stream.float32(emitter.ParticleScaling[i]);\n        }\n\n        for (const part of ['LifeSpanUVAnim', 'DecayUVAnim', 'TailUVAnim', 'TailDecayUVAnim']) {\n            for (let i = 0; i < 3; ++i) {\n                stream.int32(emitter[part][i]);\n            }\n        }\n\n        stream.int32(emitter.TextureID !== null ? emitter.TextureID : NONE);\n        stream.int32(emitter.Squirt ? 1 : 0);\n        stream.int32(emitter.PriorityPlane);\n        stream.int32(emitter.ReplaceableId);\n\n        if (emitter.Speed && typeof emitter.Speed !== 'number') {\n            stream.keyword('KP2S');\n            stream.animVector(emitter.Speed, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Latitude && typeof emitter.Latitude !== 'number') {\n            stream.keyword('KP2L');\n            stream.animVector(emitter.Latitude, AnimVectorType.FLOAT1);\n        }\n        if (emitter.EmissionRate && typeof emitter.EmissionRate !== 'number') {\n            stream.keyword('KP2E');\n            stream.animVector(emitter.EmissionRate, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Visibility && typeof emitter.Visibility !== 'number') {\n            stream.keyword('KP2V');\n            stream.animVector(emitter.Visibility, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Length && typeof emitter.Length !== 'number') {\n            stream.keyword('KP2N');\n            stream.animVector(emitter.Length, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Width && typeof emitter.Width !== 'number') {\n            stream.keyword('KP2W');\n            stream.animVector(emitter.Width, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Gravity && typeof emitter.Gravity !== 'number') {\n            stream.keyword('KP2G');\n            stream.animVector(emitter.Gravity, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Variation && typeof emitter.Variation !== 'number') {\n            stream.keyword('KP2R');\n            stream.animVector(emitter.Variation, AnimVectorType.FLOAT1);\n        }\n    }\n}\n\n\nfunction byteLengthRibbonEmitter (emitter: RibbonEmitter): number {\n    return 4 /* size */ +\n        byteLengthNode(emitter) +\n        4 /* static HeightAbove */ +\n        4 /* static HeightBelow */ +\n        4 /* Alpha */ +\n        4 * 3 /* Color */ +\n        4 /* LifeSpan */ +\n        4 /* TextureSlot */ +\n        4 /* EmissionRate */ +\n        4 /* Rows */ +\n        4 /* Columns */ +\n        4 /* MaterialID */ +\n        4 /* Gravity */ +\n        (emitter.Visibility ? 4 /* keyword */ + byteLengthAnimVector(emitter.Visibility, AnimVectorType.FLOAT1) : 0) +\n        (typeof emitter.HeightAbove !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.HeightAbove, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (typeof emitter.HeightBelow !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.HeightBelow, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (typeof emitter.Alpha !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Alpha, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (typeof emitter.TextureSlot !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.TextureSlot, AnimVectorType.FLOAT1) :\n            0\n        );\n}\n\nfunction byteLengthRibbonEmitters (model: Model): number {\n    if (!model.RibbonEmitters.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.RibbonEmitters.map(byteLengthRibbonEmitter));\n}\n\nfunction generateRibbonEmitters (model: Model, stream: Stream): void {\n    if (!model.RibbonEmitters.length) {\n        return;\n    }\n\n    stream.keyword('RIBB');\n    stream.int32(byteLengthRibbonEmitters(model) - 8);\n\n    for (const emitter of model.RibbonEmitters) {\n        stream.int32(byteLengthRibbonEmitter(emitter));\n        generateNode(emitter, stream);\n\n        stream.float32(typeof emitter.HeightAbove === 'number' ? emitter.HeightAbove : 0);\n        stream.float32(typeof emitter.HeightBelow === 'number' ? emitter.HeightBelow : 0);\n        stream.float32(typeof emitter.Alpha === 'number' ? emitter.Alpha : 0);\n        if (emitter.Color) {\n            stream.float32Array(emitter.Color);\n        } else {\n            stream.float32(1);\n            stream.float32(1);\n            stream.float32(1);\n        }\n        stream.float32(emitter.LifeSpan);\n        stream.int32(typeof emitter.TextureSlot === 'number' ? emitter.TextureSlot : 0);\n        stream.int32(emitter.EmissionRate);\n        stream.int32(emitter.Rows);\n        stream.int32(emitter.Columns);\n        stream.int32(emitter.MaterialID);\n        stream.float32(emitter.Gravity);\n\n        if (emitter.Visibility) {\n            stream.keyword('KRVS');\n            stream.animVector(emitter.Visibility, AnimVectorType.FLOAT1);\n        }\n        if (typeof emitter.HeightAbove !== 'number') {\n            stream.keyword('KRHA');\n            stream.animVector(emitter.HeightAbove, AnimVectorType.FLOAT1);\n        }\n        if (typeof emitter.HeightBelow !== 'number') {\n            stream.keyword('KRHB');\n            stream.animVector(emitter.HeightBelow, AnimVectorType.FLOAT1);\n        }\n        if (typeof emitter.Alpha !== 'number') {\n            stream.keyword('KRAL');\n            stream.animVector(emitter.Alpha, AnimVectorType.FLOAT1);\n        }\n        if (typeof emitter.TextureSlot !== 'number') {\n            stream.keyword('KRTX');\n            stream.animVector(emitter.TextureSlot, AnimVectorType.INT1);\n        }\n    }\n}\n\n\nconst MODEL_CAMERA_NAME_LENGTH = 0x50;\nfunction byteLengthCamera (camera: Camera): number {\n    return 4 /* size */ +\n        MODEL_CAMERA_NAME_LENGTH +\n        4 * 3 /* Position */ +\n        4 /* FieldOfView */ +\n        4 /* FarClip */ +\n        4 /* NearClip */ +\n        4 * 3 /* TargetPosition */ +\n        (camera.Translation ? 4 /* keyword */ + byteLengthAnimVector(camera.Translation, AnimVectorType.FLOAT3) : 0) +\n        (camera.TargetTranslation ?\n            4 /* keyword */ + byteLengthAnimVector(camera.TargetTranslation, AnimVectorType.FLOAT3) :\n            0\n        ) +\n        (camera.Rotation ? 4 /* keyword */ + byteLengthAnimVector(camera.Rotation, AnimVectorType.FLOAT1) : 0);\n}\n\nfunction byteLengthCameras (model: Model): number {\n    if (!model.Cameras.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.Cameras.map(byteLengthCamera));\n}\n\nfunction generateCameras (model: Model, stream: Stream): void {\n    if (!model.Cameras.length) {\n        return;\n    }\n\n    stream.keyword('CAMS');\n    stream.int32(byteLengthCameras(model) - 8);\n\n    for (const camera of model.Cameras) {\n        stream.int32(byteLengthCamera(camera));\n        stream.str(camera.Name, MODEL_CAMERA_NAME_LENGTH);\n        stream.float32Array(camera.Position);\n        stream.float32(camera.FieldOfView);\n        stream.float32(camera.FarClip);\n        stream.float32(camera.NearClip);\n        stream.float32Array(camera.TargetPosition);\n\n        if (camera.Translation) {\n            stream.keyword('KCTR');\n            stream.animVector(camera.Translation, AnimVectorType.FLOAT3);\n        }\n        if (camera.Rotation) {\n            stream.keyword('KCRL');\n            stream.animVector(camera.Rotation, AnimVectorType.FLOAT1);\n        }\n        if (camera.TargetTranslation) {\n            stream.keyword('KTTR');\n            stream.animVector(camera.TargetTranslation, AnimVectorType.FLOAT3);\n        }\n    }\n}\n\n\nfunction byteLengthEventObject (eventObject: EventObject): number {\n    return byteLengthNode(eventObject) +\n        4 /* KEVT keyword */ +\n        4 /* count */ +\n        4 +\n        4 * eventObject.EventTrack.length;\n}\n\nfunction byteLengthEventObjects (model: Model): number {\n    if (model.EventObjects.length === 0) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.EventObjects.map(byteLengthEventObject));\n}\n\nfunction generateEventObjects (model: Model, stream: Stream): void {\n    if (model.EventObjects.length === 0) {\n        return;\n    }\n\n    stream.keyword('EVTS');\n    stream.int32(byteLengthEventObjects(model) - 8);\n\n    for (const eventObject of model.EventObjects) {\n        generateNode(eventObject, stream);\n        stream.keyword('KEVT');\n        stream.int32(eventObject.EventTrack.length);\n        // todo GlobalSequenceId\n        stream.int32(NONE); // GlobalSequenceId ?\n        stream.uint32Array(eventObject.EventTrack);\n    }\n}\n\n\nfunction byteLengthCollisionShape (collisionShape: CollisionShape): number {\n    return byteLengthNode(collisionShape) +\n        4 /* Shape */ +\n        (collisionShape.Shape === CollisionShapeType.Box ? 6 : 3) * 4 /* Vertices */ +\n        (collisionShape.Shape === CollisionShapeType.Sphere ? 4 : 0); /* BoundsRadius */\n}\n\nfunction byteLengthCollisionShapes (model: Model): number {\n    if (model.CollisionShapes.length === 0) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.CollisionShapes.map(byteLengthCollisionShape));\n}\n\nfunction generateCollisionShapes (model: Model, stream: Stream): void {\n    if (model.CollisionShapes.length === 0) {\n        return;\n    }\n\n    stream.keyword('CLID');\n    stream.int32(byteLengthCollisionShapes(model) - 8);\n\n    for (const collisionShape of model.CollisionShapes) {\n        generateNode(collisionShape, stream);\n        stream.int32(collisionShape.Shape);\n        stream.float32Array(collisionShape.Vertices);\n        if (collisionShape.Shape === CollisionShapeType.Sphere) {\n            stream.float32(collisionShape.BoundsRadius);\n        }\n    }\n}\n\n\nfunction byteLengthFaceFX (model: Model): number {\n    if (model.Version < 900 || !model.FaceFX) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n    (\n        80 /* Name */ +\n        260 /* Path */\n    ) * model.FaceFX.length;\n}\n\nfunction generateFaceFX (model: Model, stream: Stream): void {\n    if (model.Version < 900 || !model.FaceFX) {\n        return;\n    }\n\n    stream.keyword('FAFX');\n    stream.int32(byteLengthFaceFX(model) - 8);\n\n    for (const faceFx of model.FaceFX) {\n        stream.str(faceFx.Name, 80);\n        stream.str(faceFx.Path, 260);\n    }\n}\n\n\nfunction byteLengthBindPoseObject (bindPose: BindPose): number {\n    return 4 * 12 /* Matrices */ * bindPose.Matrices.length;\n}\n\nfunction byteLengthBindPoses (model: Model): number {\n    if (model.Version < 900 || !model.BindPoses) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        4 /* count */ +\n        sum(model.BindPoses.map(byteLengthBindPoseObject));\n}\n\nfunction generateBindPoses (model: Model, stream: Stream): void {\n    if (model.Version < 900 || !model.BindPoses?.length) {\n        return;\n    }\n\n    stream.keyword('BPOS');\n    stream.int32(byteLengthBindPoses(model) - 8);\n\n    const totalCount = model.BindPoses.reduce((acc, bindPose) => {\n        return acc + bindPose.Matrices.length;\n    }, 0);\n\n    stream.int32(totalCount);\n\n    for (const bindPose of model.BindPoses) {\n        for (const matrix of bindPose.Matrices) {\n            stream.float32Array(matrix);\n        }\n    }\n}\n\nfunction byteLengthParticleEmitterPopcorn (emitter: ParticleEmitterPopcorn): number {\n    return 4 /* size */ +\n        byteLengthNode(emitter) +\n        4 /* static LifeSpan */ +\n        4 /* static EmissionRate */ +\n        4 /* static Speed */ +\n        4 * 3 /* static Color */ +\n        4 /* static Alpha */ +\n        4 /* ReplaceableId */ +\n        260 /* Path */ +\n        260 /* AnimVisibilityGuide */ +\n        (emitter.Alpha && typeof emitter.Alpha !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Alpha, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Visibility && typeof emitter.Visibility !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Visibility, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.EmissionRate && typeof emitter.EmissionRate !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.EmissionRate, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Color && !(emitter.Color instanceof Float32Array) ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Color, AnimVectorType.FLOAT3) :\n            0\n        ) +\n        (emitter.LifeSpan && typeof emitter.LifeSpan !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.LifeSpan, AnimVectorType.FLOAT1) :\n            0\n        ) +\n        (emitter.Speed && typeof emitter.Speed !== 'number' ?\n            4 /* keyword */ + byteLengthAnimVector(emitter.Speed, AnimVectorType.FLOAT1) :\n            0\n        );\n}\n\nfunction byteLengthParticleEmitterPopcorns (model: Model): number {\n    if (model.Version < 900 || !model.ParticleEmitterPopcorns?.length) {\n        return 0;\n    }\n\n    return 4 /* keyword */ +\n        4 /* size */ +\n        sum(model.ParticleEmitterPopcorns.map(byteLengthParticleEmitterPopcorn));\n}\n\nfunction generateParticleEmitterPopcorns (model: Model, stream: Stream): void {\n    if (model.Version < 900 || !model.ParticleEmitterPopcorns?.length) {\n        return;\n    }\n\n    stream.keyword('CORN');\n    stream.int32(byteLengthParticleEmitterPopcorns(model) - 8);\n\n    for (const emitter of model.ParticleEmitterPopcorns) {\n        stream.int32(byteLengthParticleEmitterPopcorn(emitter));\n        generateNode(emitter, stream);\n\n        stream.float32(typeof emitter.LifeSpan === 'number' ? emitter.LifeSpan : 0);\n        stream.float32(typeof emitter.EmissionRate === 'number' ? emitter.EmissionRate : 1);\n        stream.float32(typeof emitter.Speed === 'number' ? emitter.Speed : 0);\n\n        if (emitter.Color instanceof Float32Array) {\n            stream.float32(emitter.Color[0]);\n            stream.float32(emitter.Color[1]);\n            stream.float32(emitter.Color[2]);\n        } else {\n            stream.float32(1);\n            stream.float32(1);\n            stream.float32(1);\n        }\n\n        stream.float32(typeof emitter.Alpha === 'number' ? emitter.Alpha : 1);\n        stream.int32(typeof emitter.ReplaceableId === 'number' ? emitter.ReplaceableId : 0);\n        stream.str(emitter.Path, 260);\n        stream.str(emitter.AnimVisibilityGuide, 260);\n\n        if (emitter.Alpha && typeof emitter.Alpha !== 'number') {\n            stream.keyword('KPPA');\n            stream.animVector(emitter.Alpha, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Color && !(emitter.Color instanceof Float32Array)) {\n            stream.keyword('KPPC');\n            stream.animVector(emitter.Color, AnimVectorType.FLOAT3);\n        }\n        if (emitter.EmissionRate && typeof emitter.EmissionRate !== 'number') {\n            stream.keyword('KPPE');\n            stream.animVector(emitter.EmissionRate, AnimVectorType.FLOAT1);\n        }\n        if (emitter.LifeSpan && typeof emitter.LifeSpan !== 'number') {\n            stream.keyword('KPPL');\n            stream.animVector(emitter.LifeSpan, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Speed && typeof emitter.Speed !== 'number') {\n            stream.keyword('KPPS');\n            stream.animVector(emitter.Speed, AnimVectorType.FLOAT1);\n        }\n        if (emitter.Visibility && typeof emitter.Visibility !== 'number') {\n            stream.keyword('KPPV');\n            stream.animVector(emitter.Visibility, AnimVectorType.FLOAT1);\n        }\n    }\n}\n\n\nconst byteLength: ((model: Model) => number)[] = [\n    byteLengthVersion,\n    byteLengthModelInfo,\n    byteLengthSequences,\n    byteLengthGlobalSequences,\n    byteLengthMaterials,\n    byteLengthTextures,\n    byteLengthTextureAnims,\n    byteLengthGeosets,\n    byteLengthGeosetAnims,\n    byteLengthBones,\n    byteLengthLights,\n    byteLengthHelpers,\n    byteLengthAttachments,\n    byteLengthPivotPoints,\n    byteLengthParticleEmitters,\n    byteLengthParticleEmitters2,\n    byteLengthParticleEmitterPopcorns,\n    byteLengthRibbonEmitters,\n    byteLengthCameras,\n    byteLengthEventObjects,\n    byteLengthCollisionShapes,\n    byteLengthFaceFX,\n    byteLengthBindPoses\n];\n\nconst generators: ((model: Model, stream: Stream) => void)[] = [\n    generateVersion,\n    generateModelInfo,\n    generateSequences,\n    generateGlobalSequences,\n    generateMaterials,\n    generateTextures,\n    generateTextureAnims,\n    generateGeosets,\n    generateGeosetAnims,\n    generateBones,\n    generateLights,\n    generateHelpers,\n    generateAttachments,\n    generatePivotPoints,\n    generateParticleEmitters,\n    generateParticleEmitters2,\n    generateParticleEmitterPopcorns,\n    generateRibbonEmitters,\n    generateCameras,\n    generateEventObjects,\n    generateCollisionShapes,\n    generateFaceFX,\n    generateBindPoses\n];\n\nexport function generate (model: Model): ArrayBuffer {\n    let totalLength = 4 /* format keyword */;\n\n    for (const lenFunc of byteLength) {\n        totalLength += lenFunc(model);\n    }\n\n    const res = new ArrayBuffer(totalLength);\n    const stream = new Stream(res);\n\n    stream.keyword('MDLX');\n\n    for (const generator of generators) {\n        generator(model, stream);\n    }\n\n    return res;\n}\n","export enum BLPType {\n    BLP0,\n    BLP1,\n    BLP2\n}\n\nexport enum BLPContent {\n    JPEG = 0,\n    Direct = 1\n}\n\nexport interface BLPMipMap {\n    offset: number;\n    size: number;\n}\n\nexport interface BLPImage {\n    type: BLPType;\n    width: number;\n    height: number;\n    content: BLPContent;\n    alphaBits: number;\n    mipmaps: BLPMipMap[];\n    data: ArrayBuffer;\n}\n","/*\n Copyright 2011 notmasteryet\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n */\n\n// - The JPEG specification can be found in the ITU CCITT Recommendation T.81\n//   (www.w3.org/Graphics/JPEG/itu-t81.pdf)\n// - The JFIF specification can be found in the JPEG File Interchange Format\n//   (www.w3.org/Graphics/JPEG/jfif3.pdf)\n// - The Adobe Application-Specific JPEG markers in the Supporting the DCT Filters\n//   in PostScript Level 2, Technical Note #5116\n//   (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)\n\n// NOTE: This file was edited to match the crude usage of the JPG format by Blizzard for their BLP1 format.\n\nvar JpegImage = (function jpegImage() {\n    \"use strict\";\n    var dctZigZag = new Int32Array([\n        0,\n        1,  8,\n        16,  9,  2,\n        3, 10, 17, 24,\n        32, 25, 18, 11, 4,\n        5, 12, 19, 26, 33, 40,\n        48, 41, 34, 27, 20, 13,  6,\n        7, 14, 21, 28, 35, 42, 49, 56,\n        57, 50, 43, 36, 29, 22, 15,\n        23, 30, 37, 44, 51, 58,\n        59, 52, 45, 38, 31,\n        39, 46, 53, 60,\n        61, 54, 47,\n        55, 62,\n        63\n    ]);\n\n    var dctCos1  =  4017   // cos(pi/16)\n    var dctSin1  =   799   // sin(pi/16)\n    var dctCos3  =  3406   // cos(3*pi/16)\n    var dctSin3  =  2276   // sin(3*pi/16)\n    var dctCos6  =  1567   // cos(6*pi/16)\n    var dctSin6  =  3784   // sin(6*pi/16)\n    var dctSqrt2 =  5793   // sqrt(2)\n    var dctSqrt1d2 = 2896  // sqrt(2) / 2\n\n    function constructor() {\n    }\n\n    function buildHuffmanTable(codeLengths, values) {\n        var k = 0, code = [], i, j, length = 16;\n        while (length > 0 && !codeLengths[length - 1])\n            length--;\n        code.push({children: [], index: 0});\n        var p = code[0], q;\n        for (i = 0; i < length; i++) {\n            for (j = 0; j < codeLengths[i]; j++) {\n                p = code.pop();\n                p.children[p.index] = values[k];\n                while (p.index > 0) {\n                    p = code.pop();\n                }\n                p.index++;\n                code.push(p);\n                while (code.length <= i) {\n                    code.push(q = {children: [], index: 0});\n                    p.children[p.index] = q.children;\n                    p = q;\n                }\n                k++;\n            }\n            if (i + 1 < length) {\n                // p here points to last code\n                code.push(q = {children: [], index: 0});\n                p.children[p.index] = q.children;\n                p = q;\n            }\n        }\n        return code[0].children;\n    }\n\n    function getBlockBufferOffset(component, row, col) {\n        return 64 * ((component.blocksPerLine + 1) * row + col);\n    }\n\n    function decodeScan(data, offset,\n                        frame, components, resetInterval,\n                        spectralStart, spectralEnd,\n                        successivePrev, successive) {\n        var precision = frame.precision;\n        var samplesPerLine = frame.samplesPerLine;\n        var scanLines = frame.scanLines;\n        var mcusPerLine = frame.mcusPerLine;\n        var progressive = frame.progressive;\n        var maxH = frame.maxH, maxV = frame.maxV;\n\n        var startOffset = offset, bitsData = 0, bitsCount = 0;\n\n        function readBit() {\n            if (bitsCount > 0) {\n                bitsCount--;\n                return (bitsData >> bitsCount) & 1;\n            }\n            bitsData = data[offset++];\n            if (bitsData == 0xFF) {\n                var nextByte = data[offset++];\n                if (nextByte) {\n                    throw \"unexpected marker: \" + ((bitsData << 8) | nextByte).toString(16);\n                }\n                // unstuff 0\n            }\n            bitsCount = 7;\n            return bitsData >>> 7;\n        }\n\n        function decodeHuffman(tree) {\n            var node = tree;\n            var bit;\n            while ((bit = readBit()) !== null) {\n                node = node[bit];\n                if (typeof node === 'number')\n                    return node;\n                if (typeof node !== 'object')\n                    throw \"invalid huffman sequence\";\n            }\n            return null;\n        }\n\n        function receive(length) {\n            var n = 0;\n            while (length > 0) {\n                var bit = readBit();\n                if (bit === null) return;\n                n = (n << 1) | bit;\n                length--;\n            }\n            return n;\n        }\n\n        function receiveAndExtend(length) {\n            var n = receive(length);\n            if (n >= 1 << (length - 1))\n                return n;\n            return n + (-1 << length) + 1;\n        }\n\n        function decodeBaseline(component, offset) {\n            var t = decodeHuffman(component.huffmanTableDC);\n            var diff = t === 0 ? 0 : receiveAndExtend(t);\n            component.blockData[offset] = (component.pred += diff);\n            var k = 1;\n            while (k < 64) {\n                var rs = decodeHuffman(component.huffmanTableAC);\n                var s = rs & 15, r = rs >> 4;\n                if (s === 0) {\n                    if (r < 15)\n                        break;\n                    k += 16;\n                    continue;\n                }\n                k += r;\n                var z = dctZigZag[k];\n                component.blockData[offset + z] = receiveAndExtend(s);\n                k++;\n            }\n        }\n\n        function decodeDCFirst(component, offset) {\n            var t = decodeHuffman(component.huffmanTableDC);\n            var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive);\n            component.blockData[offset] = (component.pred += diff);\n        }\n\n        function decodeDCSuccessive(component, offset) {\n            component.blockData[offset] |= readBit() << successive;\n        }\n\n        var eobrun = 0;\n        function decodeACFirst(component, offset) {\n            if (eobrun > 0) {\n                eobrun--;\n                return;\n            }\n            var k = spectralStart, e = spectralEnd;\n            while (k <= e) {\n                var rs = decodeHuffman(component.huffmanTableAC);\n                var s = rs & 15, r = rs >> 4;\n                if (s === 0) {\n                    if (r < 15) {\n                        eobrun = receive(r) + (1 << r) - 1;\n                        break;\n                    }\n                    k += 16;\n                    continue;\n                }\n                k += r;\n                var z = dctZigZag[k];\n                component.blockData[offset + z] = receiveAndExtend(s) * (1 << successive);\n                k++;\n            }\n        }\n\n        var successiveACState = 0, successiveACNextValue;\n        function decodeACSuccessive(component, offset) {\n            var k = spectralStart, e = spectralEnd, r = 0;\n            while (k <= e) {\n                var z = dctZigZag[k];\n                switch (successiveACState) {\n                    case 0: // initial state\n                        var rs = decodeHuffman(component.huffmanTableAC);\n                        var s = rs & 15, r = rs >> 4;\n                        if (s === 0) {\n                            if (r < 15) {\n                                eobrun = receive(r) + (1 << r);\n                                successiveACState = 4;\n                            } else {\n                                r = 16;\n                                successiveACState = 1;\n                            }\n                        } else {\n                            if (s !== 1)\n                                throw \"invalid ACn encoding\";\n                            successiveACNextValue = receiveAndExtend(s);\n                            successiveACState = r ? 2 : 3;\n                        }\n                        continue;\n                    case 1: // skipping r zero items\n                    case 2:\n                        if (component.blockData[offset + z]) {\n                            component.blockData[offset + z] += (readBit() << successive);\n                        } else {\n                            r--;\n                            if (r === 0)\n                                successiveACState = successiveACState == 2 ? 3 : 0;\n                        }\n                        break;\n                    case 3: // set value for a zero item\n                        if (component.blockData[offset + z]) {\n                            component.blockData[offset + z] += (readBit() << successive);\n                        } else {\n                            component.blockData[offset + z] = successiveACNextValue << successive;\n                            successiveACState = 0;\n                        }\n                        break;\n                    case 4: // eob\n                        if (component.blockData[offset + z]) {\n                            component.blockData[offset + z] += (readBit() << successive);\n                        }\n                        break;\n                }\n                k++;\n            }\n            if (successiveACState === 4) {\n                eobrun--;\n                if (eobrun === 0)\n                    successiveACState = 0;\n            }\n        }\n\n        function decodeMcu(component, decode, mcu, row, col) {\n            var mcuRow = (mcu / mcusPerLine) | 0;\n            var mcuCol = mcu % mcusPerLine;\n            var blockRow = mcuRow * component.v + row;\n            var blockCol = mcuCol * component.h + col;\n            var offset = getBlockBufferOffset(component, blockRow, blockCol);\n            decode(component, offset);\n        }\n\n        function decodeBlock(component, decode, mcu) {\n            var blockRow = (mcu / component.blocksPerLine) | 0;\n            var blockCol = mcu % component.blocksPerLine;\n            var offset = getBlockBufferOffset(component, blockRow, blockCol);\n            decode(component, offset);\n        }\n\n        var componentsLength = components.length;\n        var component, i, j, k, n;\n        var decodeFn;\n        if (progressive) {\n            if (spectralStart === 0)\n                decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;\n            else\n                decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;\n        } else {\n            decodeFn = decodeBaseline;\n        }\n\n        var mcu = 0, marker;\n        var mcuExpected;\n        if (componentsLength == 1) {\n            mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;\n        } else {\n            mcuExpected = mcusPerLine * frame.mcusPerColumn;\n        }\n        if (!resetInterval) {\n            resetInterval = mcuExpected;\n        }\n\n        var h, v;\n        while (mcu < mcuExpected) {\n            // reset interval stuff\n            for (i = 0; i < componentsLength; i++) {\n                components[i].pred = 0;\n            }\n            eobrun = 0;\n\n            if (componentsLength == 1) {\n                component = components[0];\n                for (n = 0; n < resetInterval; n++) {\n                    decodeBlock(component, decodeFn, mcu);\n                    mcu++;\n                }\n            } else {\n                for (n = 0; n < resetInterval; n++) {\n                    for (i = 0; i < componentsLength; i++) {\n                        component = components[i];\n                        h = component.h;\n                        v = component.v;\n                        for (j = 0; j < v; j++) {\n                            for (k = 0; k < h; k++) {\n                                decodeMcu(component, decodeFn, mcu, j, k);\n                            }\n                        }\n                    }\n                    mcu++;\n                }\n            }\n\n            // find marker\n            bitsCount = 0;\n            marker = (data[offset] << 8) | data[offset + 1];\n            if (marker <= 0xFF00) {\n                throw \"marker was not found\";\n            }\n\n            if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx\n                offset += 2;\n            } else {\n                break;\n            }\n        }\n\n        return offset - startOffset;\n    }\n\n    // A port of poppler's IDCT method which in turn is taken from:\n    //   Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,\n    //   \"Practical Fast 1-D DCT Algorithms with 11 Multiplications\",\n    //   IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,\n    //   988-991.\n    function quantizeAndInverse(component, blockBufferOffset, p) {\n        var qt = component.quantizationTable;\n        var v0, v1, v2, v3, v4, v5, v6, v7, t;\n        var i;\n\n        // dequant\n        for (i = 0; i < 64; i++) {\n            p[i] = component.blockData[blockBufferOffset + i] * qt[i];\n        }\n\n        // inverse DCT on rows\n        for (i = 0; i < 8; ++i) {\n            var row = 8 * i;\n\n            // check for all-zero AC coefficients\n            if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 &&\n                p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 &&\n                p[7 + row] == 0) {\n                t = (dctSqrt2 * p[0 + row] + 512) >> 10;\n                p[0 + row] = t;\n                p[1 + row] = t;\n                p[2 + row] = t;\n                p[3 + row] = t;\n                p[4 + row] = t;\n                p[5 + row] = t;\n                p[6 + row] = t;\n                p[7 + row] = t;\n                continue;\n            }\n\n            // stage 4\n            v0 = (dctSqrt2 * p[0 + row] + 128) >> 8;\n            v1 = (dctSqrt2 * p[4 + row] + 128) >> 8;\n            v2 = p[2 + row];\n            v3 = p[6 + row];\n            v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8;\n            v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8;\n            v5 = p[3 + row] << 4;\n            v6 = p[5 + row] << 4;\n\n            // stage 3\n            t = (v0 - v1+ 1) >> 1;\n            v0 = (v0 + v1 + 1) >> 1;\n            v1 = t;\n            t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;\n            v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;\n            v3 = t;\n            t = (v4 - v6 + 1) >> 1;\n            v4 = (v4 + v6 + 1) >> 1;\n            v6 = t;\n            t = (v7 + v5 + 1) >> 1;\n            v5 = (v7 - v5 + 1) >> 1;\n            v7 = t;\n\n            // stage 2\n            t = (v0 - v3 + 1) >> 1;\n            v0 = (v0 + v3 + 1) >> 1;\n            v3 = t;\n            t = (v1 - v2 + 1) >> 1;\n            v1 = (v1 + v2 + 1) >> 1;\n            v2 = t;\n            t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;\n            v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;\n            v7 = t;\n            t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;\n            v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;\n            v6 = t;\n\n            // stage 1\n            p[0 + row] = v0 + v7;\n            p[7 + row] = v0 - v7;\n            p[1 + row] = v1 + v6;\n            p[6 + row] = v1 - v6;\n            p[2 + row] = v2 + v5;\n            p[5 + row] = v2 - v5;\n            p[3 + row] = v3 + v4;\n            p[4 + row] = v3 - v4;\n        }\n\n        // inverse DCT on columns\n        for (i = 0; i < 8; ++i) {\n            var col = i;\n\n            // check for all-zero AC coefficients\n            if (p[1*8 + col] == 0 && p[2*8 + col] == 0 && p[3*8 + col] == 0 &&\n                p[4*8 + col] == 0 && p[5*8 + col] == 0 && p[6*8 + col] == 0 &&\n                p[7*8 + col] == 0) {\n                t = (dctSqrt2 * p[i+0] + 8192) >> 14;\n                p[0*8 + col] = t;\n                p[1*8 + col] = t;\n                p[2*8 + col] = t;\n                p[3*8 + col] = t;\n                p[4*8 + col] = t;\n                p[5*8 + col] = t;\n                p[6*8 + col] = t;\n                p[7*8 + col] = t;\n                continue;\n            }\n\n            // stage 4\n            v0 = (dctSqrt2 * p[0*8 + col] + 2048) >> 12;\n            v1 = (dctSqrt2 * p[4*8 + col] + 2048) >> 12;\n            v2 = p[2*8 + col];\n            v3 = p[6*8 + col];\n            v4 = (dctSqrt1d2 * (p[1*8 + col] - p[7*8 + col]) + 2048) >> 12;\n            v7 = (dctSqrt1d2 * (p[1*8 + col] + p[7*8 + col]) + 2048) >> 12;\n            v5 = p[3*8 + col];\n            v6 = p[5*8 + col];\n\n            // stage 3\n            t = (v0 - v1 + 1) >> 1;\n            v0 = (v0 + v1 + 1) >> 1;\n            v1 = t;\n            t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;\n            v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;\n            v3 = t;\n            t = (v4 - v6 + 1) >> 1;\n            v4 = (v4 + v6 + 1) >> 1;\n            v6 = t;\n            t = (v7 + v5 + 1) >> 1;\n            v5 = (v7 - v5 + 1) >> 1;\n            v7 = t;\n\n            // stage 2\n            t = (v0 - v3 + 1) >> 1;\n            v0 = (v0 + v3 + 1) >> 1;\n            v3 = t;\n            t = (v1 - v2 + 1) >> 1;\n            v1 = (v1 + v2 + 1) >> 1;\n            v2 = t;\n            t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12;\n            v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12;\n            v7 = t;\n            t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12;\n            v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12;\n            v6 = t;\n\n            // stage 1\n            p[0*8 + col] = v0 + v7;\n            p[7*8 + col] = v0 - v7;\n            p[1*8 + col] = v1 + v6;\n            p[6*8 + col] = v1 - v6;\n            p[2*8 + col] = v2 + v5;\n            p[5*8 + col] = v2 - v5;\n            p[3*8 + col] = v3 + v4;\n            p[4*8 + col] = v3 - v4;\n        }\n\n        // convert to 8-bit integers\n        for (i = 0; i < 64; ++i) {\n            var index = blockBufferOffset + i;\n            var q = p[i];\n            q = (q <= -2056) ? 0 : (q >= 2024) ? 255 : (q + 2056) >> 4;\n            component.blockData[index] = q;\n        }\n    }\n\n    function buildComponentData(frame, component) {\n        var lines = [];\n        var blocksPerLine = component.blocksPerLine;\n        var blocksPerColumn = component.blocksPerColumn;\n        var samplesPerLine = blocksPerLine << 3;\n        var computationBuffer = new Int32Array(64);\n\n        var i, j, ll = 0;\n        for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {\n            for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {\n                var offset = getBlockBufferOffset(component, blockRow, blockCol)\n                quantizeAndInverse(component, offset, computationBuffer);\n            }\n        }\n        return component.blockData;\n    }\n\n    function clampToUint8(a) {\n        return a <= 0 ? 0 : a >= 255 ? 255 : a | 0;\n    }\n\n    constructor.prototype = {\n        load: function load(path) {\n            var xhr = new XMLHttpRequest();\n            xhr.open(\"GET\", path, true);\n            xhr.responseType = \"arraybuffer\";\n            xhr.onload = (function() {\n                // TODO catch parse error\n                var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);\n                this.parse(data);\n                if (this.onload)\n                    this.onload();\n            }).bind(this);\n            xhr.send(null);\n        },\n\n        loadFromBuffer: function loadFromBuffer(arrayBuffer) {\n            this.parse(arrayBuffer);\n            if (this.onload)\n                this.onload();\n        },\n\n        parse: function parse(data) {\n\n            function readUint16() {\n                var value = (data[offset] << 8) | data[offset + 1];\n                offset += 2;\n                return value;\n            }\n\n            function readDataBlock() {\n                var length = readUint16();\n                var array = data.subarray(offset, offset + length - 2);\n                offset += array.length;\n                return array;\n            }\n\n            function prepareComponents(frame) {\n                var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH);\n                var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);\n                for (var i = 0; i < frame.components.length; i++) {\n                    component = frame.components[i];\n                    var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH);\n                    var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines  / 8) * component.v / frame.maxV);\n                    var blocksPerLineForMcu = mcusPerLine * component.h;\n                    var blocksPerColumnForMcu = mcusPerColumn * component.v;\n\n                    var blocksBufferSize = 64 * blocksPerColumnForMcu\n                        * (blocksPerLineForMcu + 1);\n                    component.blockData = new Int16Array(blocksBufferSize);\n                    component.blocksPerLine = blocksPerLine;\n                    component.blocksPerColumn = blocksPerColumn;\n                }\n                frame.mcusPerLine = mcusPerLine;\n                frame.mcusPerColumn = mcusPerColumn;\n            }\n\n            var offset = 0, length = data.length;\n            var jfif = null;\n            var adobe = null;\n            var pixels = null;\n            var frame, resetInterval;\n            var quantizationTables = [];\n            var huffmanTablesAC = [], huffmanTablesDC = [];\n            var fileMarker = readUint16();\n            if (fileMarker != 0xFFD8) { // SOI (Start of Image)\n                throw \"SOI not found\";\n            }\n\n            fileMarker = readUint16();\n            while (fileMarker != 0xFFD9) { // EOI (End of image)\n                var i, j, l;\n                switch(fileMarker) {\n                    case 0xFFE0: // APP0 (Application Specific)\n                    case 0xFFE1: // APP1\n                    case 0xFFE2: // APP2\n                    case 0xFFE3: // APP3\n                    case 0xFFE4: // APP4\n                    case 0xFFE5: // APP5\n                    case 0xFFE6: // APP6\n                    case 0xFFE7: // APP7\n                    case 0xFFE8: // APP8\n                    case 0xFFE9: // APP9\n                    case 0xFFEA: // APP10\n                    case 0xFFEB: // APP11\n                    case 0xFFEC: // APP12\n                    case 0xFFED: // APP13\n                    case 0xFFEE: // APP14\n                    case 0xFFEF: // APP15\n                    case 0xFFFE: // COM (Comment)\n                        var appData = readDataBlock();\n\n                        if (fileMarker === 0xFFE0) {\n                            if (appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 &&\n                                appData[3] === 0x46 && appData[4] === 0) { // 'JFIF\\x00'\n                                jfif = {\n                                    version: { major: appData[5], minor: appData[6] },\n                                    densityUnits: appData[7],\n                                    xDensity: (appData[8] << 8) | appData[9],\n                                    yDensity: (appData[10] << 8) | appData[11],\n                                    thumbWidth: appData[12],\n                                    thumbHeight: appData[13],\n                                    thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13])\n                                };\n                            }\n                        }\n                        // TODO APP1 - Exif\n                        if (fileMarker === 0xFFEE) {\n                            if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F &&\n                                appData[3] === 0x62 && appData[4] === 0x65 && appData[5] === 0) { // 'Adobe\\x00'\n                                adobe = {\n                                    version: appData[6],\n                                    flags0: (appData[7] << 8) | appData[8],\n                                    flags1: (appData[9] << 8) | appData[10],\n                                    transformCode: appData[11]\n                                };\n                            }\n                        }\n                        break;\n\n                    case 0xFFDB: // DQT (Define Quantization Tables)\n                        var quantizationTablesLength = readUint16();\n                        var quantizationTablesEnd = quantizationTablesLength + offset - 2;\n                        while (offset < quantizationTablesEnd) {\n                            var quantizationTableSpec = data[offset++];\n                            var tableData = new Int32Array(64);\n                            if ((quantizationTableSpec >> 4) === 0) { // 8 bit values\n                                for (j = 0; j < 64; j++) {\n                                    var z = dctZigZag[j];\n                                    tableData[z] = data[offset++];\n                                }\n                            } else if ((quantizationTableSpec >> 4) === 1) { //16 bit\n                                for (j = 0; j < 64; j++) {\n                                    var z = dctZigZag[j];\n                                    tableData[z] = readUint16();\n                                }\n                            } else\n                                throw \"DQT: invalid table spec\";\n                            quantizationTables[quantizationTableSpec & 15] = tableData;\n                        }\n                        break;\n\n                    case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT)\n                    case 0xFFC1: // SOF1 (Start of Frame, Extended DCT)\n                    case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT)\n                        if (frame) {\n                            throw \"Only single frame JPEGs supported\";\n                        }\n                        readUint16(); // skip data length\n                        frame = {};\n                        frame.extended = (fileMarker === 0xFFC1);\n                        frame.progressive = (fileMarker === 0xFFC2);\n                        frame.precision = data[offset++];\n                        frame.scanLines = readUint16();\n                        frame.samplesPerLine = readUint16();\n                        frame.components = [];\n                        frame.componentIds = {};\n                        var componentsCount = data[offset++], componentId;\n                        var maxH = 0, maxV = 0;\n                        for (i = 0; i < componentsCount; i++) {\n                            componentId = data[offset];\n                            var h = data[offset + 1] >> 4;\n                            var v = data[offset + 1] & 15;\n                            if (maxH < h) maxH = h;\n                            if (maxV < v) maxV = v;\n                            var qId = data[offset + 2];\n                            var l = frame.components.push({\n                                h: h,\n                                v: v,\n                                quantizationTable: quantizationTables[qId]\n                            });\n                            frame.componentIds[componentId] = l - 1;\n                            offset += 3;\n                        }\n                        frame.maxH = maxH;\n                        frame.maxV = maxV;\n                        prepareComponents(frame);\n                        break;\n\n                    case 0xFFC4: // DHT (Define Huffman Tables)\n                        var huffmanLength = readUint16();\n                        for (i = 2; i < huffmanLength;) {\n                            var huffmanTableSpec = data[offset++];\n                            var codeLengths = new Uint8Array(16);\n                            var codeLengthSum = 0;\n                            for (j = 0; j < 16; j++, offset++)\n                                codeLengthSum += (codeLengths[j] = data[offset]);\n                            var huffmanValues = new Uint8Array(codeLengthSum);\n                            for (j = 0; j < codeLengthSum; j++, offset++)\n                                huffmanValues[j] = data[offset];\n                            i += 17 + codeLengthSum;\n\n                            ((huffmanTableSpec >> 4) === 0 ?\n                                huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] =\n                                buildHuffmanTable(codeLengths, huffmanValues);\n                        }\n                        break;\n\n                    case 0xFFDD: // DRI (Define Restart Interval)\n                        readUint16(); // skip data length\n                        resetInterval = readUint16();\n                        break;\n\n                    case 0xFFDA: // SOS (Start of Scan)\n                        var scanLength = readUint16();\n                        var selectorsCount = data[offset++];\n                        var components = [], component;\n                        for (i = 0; i < selectorsCount; i++) {\n                            var componentIndex = frame.componentIds[data[offset++]];\n                            component = frame.components[componentIndex];\n                            var tableSpec = data[offset++];\n                            component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];\n                            component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];\n                            components.push(component);\n                        }\n                        var spectralStart = data[offset++];\n                        var spectralEnd = data[offset++];\n                        var successiveApproximation = data[offset++];\n                        var processed = decodeScan(data, offset,\n                            frame, components, resetInterval,\n                            spectralStart, spectralEnd,\n                            successiveApproximation >> 4, successiveApproximation & 15);\n                        offset += processed;\n                        break;\n                    default:\n                        if (data[offset - 3] == 0xFF &&\n                            data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) {\n                            // could be incorrect encoding -- last 0xFF byte of the previous\n                            // block was eaten by the encoder\n                            offset -= 3;\n                            break;\n                        }\n                        throw \"unknown JPEG marker \" + fileMarker.toString(16);\n                }\n                fileMarker = readUint16();\n            }\n\n            this.width = frame.samplesPerLine;\n            this.height = frame.scanLines;\n            this.jfif = jfif;\n            this.adobe = adobe;\n            this.components = [];\n            for (var i = 0; i < frame.components.length; i++) {\n                var component = frame.components[i];\n                this.components.push({\n                    output: buildComponentData(frame, component),\n                    scaleX: component.h / frame.maxH,\n                    scaleY: component.v / frame.maxV,\n                    blocksPerLine: component.blocksPerLine,\n                    blocksPerColumn: component.blocksPerColumn\n                });\n            }\n        },\n\n        getData: function getData(imageData, width, height) {\n            var scaleX = this.width / width, scaleY = this.height / height;\n\n            var component, componentScaleX, componentScaleY;\n            var x, y, i;\n            var offset = 0;\n            var Y, Cb, Cr, K, C, M, Ye, R, G, B;\n            var colorTransform;\n            var numComponents = this.components.length;\n            var dataLength = width * height * numComponents;\n            //var data = new Uint8Array(dataLength);\n            var data = imageData.data;\n            var componentLine;\n\n            // lineData is reused for all components. Assume first component is\n            // the biggest\n            var lineData = new Uint8Array((this.components[0].blocksPerLine << 3) *\n                this.components[0].blocksPerColumn * 8);\n\n            // First construct image data ...\n            for (i = 0; i < numComponents; i++) {\n                component = this.components[i < 3 ? 2 - i : i];\n                var blocksPerLine = component.blocksPerLine;\n                var blocksPerColumn = component.blocksPerColumn;\n                var samplesPerLine = blocksPerLine << 3;\n\n                var j, k, ll = 0;\n                var lineOffset = 0;\n                for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {\n                    var scanLine = blockRow << 3;\n                    for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {\n                        var bufferOffset = getBlockBufferOffset(component, blockRow, blockCol);\n                        var offset = 0, sample = blockCol << 3;\n                        for (j = 0; j < 8; j++) {\n                            var lineOffset = (scanLine + j) * samplesPerLine;\n                            for (k = 0; k < 8; k++) {\n                                lineData[lineOffset + sample + k] =\n                                    component.output[bufferOffset + offset++];\n                            }\n                        }\n                    }\n                }\n\n                componentScaleX = component.scaleX * scaleX;\n                componentScaleY = component.scaleY * scaleY;\n                offset = i;\n\n                var cx, cy;\n                var index;\n                for (y = 0; y < height; y++) {\n                    for (x = 0; x < width; x++) {\n                        cy = 0 | (y * componentScaleY);\n                        cx = 0 | (x * componentScaleX);\n                        index = cy * samplesPerLine + cx;\n                        data[offset] = lineData[index];\n                        offset += numComponents;\n                    }\n                }\n            }\n\n          /*\n           // ... then transform colors, if necessary\n           switch (numComponents) {\n           case 1: case 2: break;\n           // no color conversion for one or two compoenents\n\n           case 3:\n           // The default transform for three components is true\n           colorTransform = true;\n           // The adobe transform marker overrides any previous setting\n           if (this.adobe && this.adobe.transformCode)\n           colorTransform = true;\n           else if (typeof this.colorTransform !== 'undefined')\n           colorTransform = !!this.colorTransform;\n\n           if (colorTransform) {\n           for (i = 0; i < dataLength; i += numComponents) {\n           Y  = data[i    ];\n           Cb = data[i + 1];\n           Cr = data[i + 2];\n\n           R = clampToUint8(Y - 179.456 + 1.402 * Cr);\n           G = clampToUint8(Y + 135.459 - 0.344 * Cb - 0.714 * Cr);\n           B = clampToUint8(Y - 226.816 + 1.772 * Cb);\n\n           data[i    ] = R;\n           data[i + 1] = G;\n           data[i + 2] = B;\n           }\n           }\n           break;\n           case 4:\n           console.log(this.colorTransform);\n           if (!this.adobe)\n           throw 'Unsupported color mode (4 components)';\n           // The default transform for four components is false\n           colorTransform = false;\n           // The adobe transform marker overrides any previous setting\n           if (this.adobe && this.adobe.transformCode)\n           colorTransform = true;\n           else if (typeof this.colorTransform !== 'undefined')\n           colorTransform = !!this.colorTransform;\n\n           if (colorTransform) {\n           for (i = 0; i < dataLength; i += numComponents) {\n           Y  = data[i];\n           Cb = data[i + 1];\n           Cr = data[i + 2];\n\n           C = clampToUint8(434.456 - Y - 1.402 * Cr);\n           M = clampToUint8(119.541 - Y + 0.344 * Cb + 0.714 * Cr);\n           Y = clampToUint8(481.816 - Y - 1.772 * Cb);\n\n           data[i    ] = C;\n           data[i + 1] = M;\n           data[i + 2] = Y;\n           // K is unchanged\n           }\n           }\n           break;\n           default:\n           throw 'Unsupported color mode';\n           }\n           */\n            return data;\n        },\n        copyToImageData: function copyToImageData(imageData) {\n            var width = imageData.width, height = imageData.height;\n            var imageDataBytes = width * height * 4;\n            var imageDataArray = imageData.data;\n            var data = this.getData(width, height);\n            var i = 0, j = 0, k0, k1;\n            var Y, K, C, M, R, G, B;\n            switch (this.components.length) {\n                case 1:\n                    while (j < imageDataBytes) {\n                        Y = data[i++];\n\n                        imageDataArray[j++] = Y;\n                        imageDataArray[j++] = Y;\n                        imageDataArray[j++] = Y;\n                        imageDataArray[j++] = 255;\n                    }\n                    break;\n                case 3:\n                    while (j < imageDataBytes) {\n                        R = data[i++];\n                        G = data[i++];\n                        B = data[i++];\n\n                        imageDataArray[j++] = R;\n                        imageDataArray[j++] = G;\n                        imageDataArray[j++] = B;\n                        imageDataArray[j++] = 255;\n                    }\n                    break;\n                case 4:\n                    while (j < imageDataBytes) {\n                        C = data[i++];\n                        M = data[i++];\n                        Y = data[i++];\n                        K = data[i++];\n\n                        k0 = 255 - K;\n                        k1 = k0 / 255;\n\n\n                        R = clampToUint8(k0 - C * k1);\n                        G = clampToUint8(k0 - M * k1);\n                        B = clampToUint8(k0 - Y * k1);\n\n                        imageDataArray[j++] = R;\n                        imageDataArray[j++] = G;\n                        imageDataArray[j++] = B;\n                        imageDataArray[j++] = 255;\n                    }\n                    break;\n                default:\n                    throw 'Unsupported color mode';\n            }\n        }\n    };\n\n    return constructor;\n})();\n\nexport default function decode (data) {\n    const jpegImage = new JpegImage();\n\n    jpegImage.loadFromBuffer(data);\n\n    var imageData;\n    if (typeof ImageData !== 'undefined') {\n        imageData = new ImageData(jpegImage.width, jpegImage.height);\n    } else {\n        imageData = {\n            width: jpegImage.width,\n            height: jpegImage.height,\n            data: new Uint8ClampedArray(jpegImage.width * jpegImage.height * 4)\n        };\n    }\n    jpegImage.getData(imageData, jpegImage.width, jpegImage.height);\n\n    return imageData;\n};\n","import decodeJPEG from '../third_party/decoder';\nimport {BLPImage, BLPContent, BLPType} from './blpimage';\n\nfunction keyword (view: DataView, offset: number): string {\n    return String.fromCharCode(\n        view.getUint8(offset),\n        view.getUint8(offset + 1),\n        view.getUint8(offset + 2),\n        view.getUint8(offset + 3)\n    );\n}\n\nfunction uint32 (view: DataView, offset: number): number {\n    return view.getUint32(offset * 4, true);\n}\n\nfunction bitVal (data: Uint8Array, bitCount: number, index: number): number {\n    // only 1, 4 or 8 bits\n    const byte = data[Math.floor(index * bitCount / 8)],\n        valsPerByte = 8 / bitCount;\n\n    return (byte >> (valsPerByte - index % valsPerByte - 1)) & ((1 << bitCount) - 1);\n}\n\ninterface ImageDataLike {\n    width: number;\n    height: number;\n    data: ImageDataArray;\n    colorSpace: 'srgb' | 'display-p3' | undefined;\n}\n\n// node.js have no native ImageData\nfunction createImageData (width: number, height: number): ImageDataLike {\n    if (typeof ImageData !== 'undefined') {\n        return new ImageData(width, height);\n    } else {\n        return {\n            width,\n            height,\n            data: new Uint8ClampedArray(width * height * 4),\n            colorSpace: 'srgb'\n        };\n    }\n}\n\nexport function decode (arrayBuffer: ArrayBuffer): BLPImage {\n    const view = new DataView(arrayBuffer);\n\n    const image: BLPImage = {\n        type: BLPType.BLP1,\n        width: 0,\n        height: 0,\n        content: BLPContent.JPEG,\n        alphaBits: 0,\n        mipmaps: [],\n        data: arrayBuffer,\n    };\n\n    const type = keyword(view, 0);\n\n    if (type === 'BLP0' || type === 'BLP2') {\n        throw new Error('BLP0/BLP2 not supported');\n    }\n    if (type !== 'BLP1') {\n        throw new Error('Not a blp image');\n    }\n\n    image.content = uint32(view, 1);\n\n    if (image.content !== BLPContent.JPEG && image.content !== BLPContent.Direct) {\n        throw new Error('Unknown BLP content');\n    }\n\n    image.alphaBits = uint32(view, 2);\n    image.width = uint32(view, 3);\n    image.height = uint32(view, 4);\n\n    for (let i = 0; i < 16; ++i) {\n        const mipmap = {\n            offset: uint32(view, 7 + i),\n            size: uint32(view, 7 + 16 + i)\n        };\n\n        if (mipmap.size > 0) {\n            image.mipmaps.push(mipmap);\n        } else {\n            break;\n        }\n    }\n\n    return image;\n}\n\nexport function getImageData (blp: BLPImage, mipmapLevel: number): ImageDataLike {\n    const view = new DataView(blp.data),\n        uint8Data = new Uint8Array(blp.data),\n        mipmap = blp.mipmaps[mipmapLevel];\n\n    if (blp.content === BLPContent.JPEG) {\n        const headerSize = uint32(view, 39),\n            data = new Uint8Array(headerSize + mipmap.size);\n\n        data.set(uint8Data.subarray(40 * 4, 40 * 4 + headerSize));\n        data.set(uint8Data.subarray(mipmap.offset, mipmap.offset + mipmap.size), headerSize);\n\n        return decodeJPEG(data);\n    } else {\n        const palette = new Uint8Array(blp.data, 39 * 4, 256 * 4),\n            width = blp.width / (1 << mipmapLevel),\n            height = blp.height / (1 << mipmapLevel),\n            size = width * height,\n            alphaData = new Uint8Array(blp.data, mipmap.offset + size, Math.ceil(size * blp.alphaBits / 8)),\n            imageData = createImageData(width, height),\n            valPerAlphaBit = 255 / ((1 << blp.alphaBits) - 1);\n\n        for (let i = 0; i < size; ++i) {\n            const paletteIndex = view.getUint8(mipmap.offset + i) * 4;\n            // BGRA order\n            imageData.data[i * 4]     = palette[paletteIndex + 2];\n            imageData.data[i * 4 + 1] = palette[paletteIndex + 1];\n            imageData.data[i * 4 + 2] = palette[paletteIndex];\n\n            if (blp.alphaBits > 0) {\n                imageData.data[i * 4 + 3] = bitVal(alphaData, blp.alphaBits, i) * valPerAlphaBit;\n            } else {\n                imageData.data[i * 4 + 3] = 255;\n            }\n        }\n\n        return imageData;\n    }\n}\n","/**\r\n * Common utilities\r\n * @module glMatrix\r\n */\n// Configuration Constants\nexport var EPSILON = 0.000001;\nexport var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;\nexport var RANDOM = Math.random;\n/**\r\n * Sets the type of array used when creating new vectors and matrices\r\n *\r\n * @param {Float32ArrayConstructor | ArrayConstructor} type Array type, such as Float32Array or Array\r\n */\n\nexport function setMatrixArrayType(type) {\n  ARRAY_TYPE = type;\n}\nvar degree = Math.PI / 180;\n/**\r\n * Convert Degree To Radian\r\n *\r\n * @param {Number} a Angle in Degrees\r\n */\n\nexport function toRadian(a) {\n  return a * degree;\n}\n/**\r\n * Tests whether or not the arguments have approximately the same value, within an absolute\r\n * or relative tolerance of glMatrix.EPSILON (an absolute tolerance is used for values less\r\n * than or equal to 1.0, and a relative tolerance is used for larger values)\r\n *\r\n * @param {Number} a The first number to test.\r\n * @param {Number} b The second number to test.\r\n * @returns {Boolean} True if the numbers are approximately equal, false otherwise.\r\n */\n\nexport function equals(a, b) {\n  return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));\n}\nif (!Math.hypot) Math.hypot = function () {\n  var y = 0,\n      i = arguments.length;\n\n  while (i--) {\n    y += arguments[i] * arguments[i];\n  }\n\n  return Math.sqrt(y);\n};","import * as glMatrix from \"./common.js\";\n/**\r\n * 3x3 Matrix\r\n * @module mat3\r\n */\n\n/**\r\n * Creates a new identity mat3\r\n *\r\n * @returns {mat3} a new 3x3 matrix\r\n */\n\nexport function create() {\n  var out = new glMatrix.ARRAY_TYPE(9);\n\n  if (glMatrix.ARRAY_TYPE != Float32Array) {\n    out[1] = 0;\n    out[2] = 0;\n    out[3] = 0;\n    out[5] = 0;\n    out[6] = 0;\n    out[7] = 0;\n  }\n\n  out[0] = 1;\n  out[4] = 1;\n  out[8] = 1;\n  return out;\n}\n/**\r\n * Copies the upper-left 3x3 values into the given mat3.\r\n *\r\n * @param {mat3} out the receiving 3x3 matrix\r\n * @param {ReadonlyMat4} a   the source 4x4 matrix\r\n * @returns {mat3} out\r\n */\n\nexport function fromMat4(out, a) {\n  out[0] = a[0];\n  out[1] = a[1];\n  out[2] = a[2];\n  out[3] = a[4];\n  out[4] = a[5];\n  out[5] = a[6];\n  out[6] = a[8];\n  out[7] = a[9];\n  out[8] = a[10];\n  return out;\n}\n/**\r\n * Creates a new mat3 initialized with values from an existing matrix\r\n *\r\n * @param {ReadonlyMat3} a matrix to clone\r\n * @returns {mat3} a new 3x3 matrix\r\n */\n\nexport function clone(a) {\n  var out = new glMatrix.ARRAY_TYPE(9);\n  out[0] = a[0];\n  out[1] = a[1];\n  out[2] = a[2];\n  out[3] = a[3];\n  out[4] = a[4];\n  out[5] = a[5];\n  out[6] = a[6];\n  out[7] = a[7];\n  out[8] = a[8];\n  return out;\n}\n/**\r\n * Copy the values from one mat3 to another\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the source matrix\r\n * @returns {mat3} out\r\n */\n\nexport function copy(out, a) {\n  out[0] = a[0];\n  out[1] = a[1];\n  out[2] = a[2];\n  out[3] = a[3];\n  out[4] = a[4];\n  out[5] = a[5];\n  out[6] = a[6];\n  out[7] = a[7];\n  out[8] = a[8];\n  return out;\n}\n/**\r\n * Create a new mat3 with the given values\r\n *\r\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\r\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\r\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\r\n * @param {Number} m10 Component in column 1, row 0 position (index 3)\r\n * @param {Number} m11 Component in column 1, row 1 position (index 4)\r\n * @param {Number} m12 Component in column 1, row 2 position (index 5)\r\n * @param {Number} m20 Component in column 2, row 0 position (index 6)\r\n * @param {Number} m21 Component in column 2, row 1 position (index 7)\r\n * @param {Number} m22 Component in column 2, row 2 position (index 8)\r\n * @returns {mat3} A new mat3\r\n */\n\nexport function fromValues(m00, m01, m02, m10, m11, m12, m20, m21, m22) {\n  var out = new glMatrix.ARRAY_TYPE(9);\n  out[0] = m00;\n  out[1] = m01;\n  out[2] = m02;\n  out[3] = m10;\n  out[4] = m11;\n  out[5] = m12;\n  out[6] = m20;\n  out[7] = m21;\n  out[8] = m22;\n  return out;\n}\n/**\r\n * Set the components of a mat3 to the given values\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\r\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\r\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\r\n * @param {Number} m10 Component in column 1, row 0 position (index 3)\r\n * @param {Number} m11 Component in column 1, row 1 position (index 4)\r\n * @param {Number} m12 Component in column 1, row 2 position (index 5)\r\n * @param {Number} m20 Component in column 2, row 0 position (index 6)\r\n * @param {Number} m21 Component in column 2, row 1 position (index 7)\r\n * @param {Number} m22 Component in column 2, row 2 position (index 8)\r\n * @returns {mat3} out\r\n */\n\nexport function set(out, m00, m01, m02, m10, m11, m12, m20, m21, m22) {\n  out[0] = m00;\n  out[1] = m01;\n  out[2] = m02;\n  out[3] = m10;\n  out[4] = m11;\n  out[5] = m12;\n  out[6] = m20;\n  out[7] = m21;\n  out[8] = m22;\n  return out;\n}\n/**\r\n * Set a mat3 to the identity matrix\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @returns {mat3} out\r\n */\n\nexport function identity(out) {\n  out[0] = 1;\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = 1;\n  out[5] = 0;\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = 1;\n  return out;\n}\n/**\r\n * Transpose the values of a mat3\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the source matrix\r\n * @returns {mat3} out\r\n */\n\nexport function transpose(out, a) {\n  // If we are transposing ourselves we can skip a few steps but have to cache some values\n  if (out === a) {\n    var a01 = a[1],\n        a02 = a[2],\n        a12 = a[5];\n    out[1] = a[3];\n    out[2] = a[6];\n    out[3] = a01;\n    out[5] = a[7];\n    out[6] = a02;\n    out[7] = a12;\n  } else {\n    out[0] = a[0];\n    out[1] = a[3];\n    out[2] = a[6];\n    out[3] = a[1];\n    out[4] = a[4];\n    out[5] = a[7];\n    out[6] = a[2];\n    out[7] = a[5];\n    out[8] = a[8];\n  }\n\n  return out;\n}\n/**\r\n * Inverts a mat3\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the source matrix\r\n * @returns {mat3} out\r\n */\n\nexport function invert(out, a) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2];\n  var a10 = a[3],\n      a11 = a[4],\n      a12 = a[5];\n  var a20 = a[6],\n      a21 = a[7],\n      a22 = a[8];\n  var b01 = a22 * a11 - a12 * a21;\n  var b11 = -a22 * a10 + a12 * a20;\n  var b21 = a21 * a10 - a11 * a20; // Calculate the determinant\n\n  var det = a00 * b01 + a01 * b11 + a02 * b21;\n\n  if (!det) {\n    return null;\n  }\n\n  det = 1.0 / det;\n  out[0] = b01 * det;\n  out[1] = (-a22 * a01 + a02 * a21) * det;\n  out[2] = (a12 * a01 - a02 * a11) * det;\n  out[3] = b11 * det;\n  out[4] = (a22 * a00 - a02 * a20) * det;\n  out[5] = (-a12 * a00 + a02 * a10) * det;\n  out[6] = b21 * det;\n  out[7] = (-a21 * a00 + a01 * a20) * det;\n  out[8] = (a11 * a00 - a01 * a10) * det;\n  return out;\n}\n/**\r\n * Calculates the adjugate of a mat3\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the source matrix\r\n * @returns {mat3} out\r\n */\n\nexport function adjoint(out, a) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2];\n  var a10 = a[3],\n      a11 = a[4],\n      a12 = a[5];\n  var a20 = a[6],\n      a21 = a[7],\n      a22 = a[8];\n  out[0] = a11 * a22 - a12 * a21;\n  out[1] = a02 * a21 - a01 * a22;\n  out[2] = a01 * a12 - a02 * a11;\n  out[3] = a12 * a20 - a10 * a22;\n  out[4] = a00 * a22 - a02 * a20;\n  out[5] = a02 * a10 - a00 * a12;\n  out[6] = a10 * a21 - a11 * a20;\n  out[7] = a01 * a20 - a00 * a21;\n  out[8] = a00 * a11 - a01 * a10;\n  return out;\n}\n/**\r\n * Calculates the determinant of a mat3\r\n *\r\n * @param {ReadonlyMat3} a the source matrix\r\n * @returns {Number} determinant of a\r\n */\n\nexport function determinant(a) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2];\n  var a10 = a[3],\n      a11 = a[4],\n      a12 = a[5];\n  var a20 = a[6],\n      a21 = a[7],\n      a22 = a[8];\n  return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);\n}\n/**\r\n * Multiplies two mat3's\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the first operand\r\n * @param {ReadonlyMat3} b the second operand\r\n * @returns {mat3} out\r\n */\n\nexport function multiply(out, a, b) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2];\n  var a10 = a[3],\n      a11 = a[4],\n      a12 = a[5];\n  var a20 = a[6],\n      a21 = a[7],\n      a22 = a[8];\n  var b00 = b[0],\n      b01 = b[1],\n      b02 = b[2];\n  var b10 = b[3],\n      b11 = b[4],\n      b12 = b[5];\n  var b20 = b[6],\n      b21 = b[7],\n      b22 = b[8];\n  out[0] = b00 * a00 + b01 * a10 + b02 * a20;\n  out[1] = b00 * a01 + b01 * a11 + b02 * a21;\n  out[2] = b00 * a02 + b01 * a12 + b02 * a22;\n  out[3] = b10 * a00 + b11 * a10 + b12 * a20;\n  out[4] = b10 * a01 + b11 * a11 + b12 * a21;\n  out[5] = b10 * a02 + b11 * a12 + b12 * a22;\n  out[6] = b20 * a00 + b21 * a10 + b22 * a20;\n  out[7] = b20 * a01 + b21 * a11 + b22 * a21;\n  out[8] = b20 * a02 + b21 * a12 + b22 * a22;\n  return out;\n}\n/**\r\n * Translate a mat3 by the given vector\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the matrix to translate\r\n * @param {ReadonlyVec2} v vector to translate by\r\n * @returns {mat3} out\r\n */\n\nexport function translate(out, a, v) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2],\n      a10 = a[3],\n      a11 = a[4],\n      a12 = a[5],\n      a20 = a[6],\n      a21 = a[7],\n      a22 = a[8],\n      x = v[0],\n      y = v[1];\n  out[0] = a00;\n  out[1] = a01;\n  out[2] = a02;\n  out[3] = a10;\n  out[4] = a11;\n  out[5] = a12;\n  out[6] = x * a00 + y * a10 + a20;\n  out[7] = x * a01 + y * a11 + a21;\n  out[8] = x * a02 + y * a12 + a22;\n  return out;\n}\n/**\r\n * Rotates a mat3 by the given angle\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat3} out\r\n */\n\nexport function rotate(out, a, rad) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2],\n      a10 = a[3],\n      a11 = a[4],\n      a12 = a[5],\n      a20 = a[6],\n      a21 = a[7],\n      a22 = a[8],\n      s = Math.sin(rad),\n      c = Math.cos(rad);\n  out[0] = c * a00 + s * a10;\n  out[1] = c * a01 + s * a11;\n  out[2] = c * a02 + s * a12;\n  out[3] = c * a10 - s * a00;\n  out[4] = c * a11 - s * a01;\n  out[5] = c * a12 - s * a02;\n  out[6] = a20;\n  out[7] = a21;\n  out[8] = a22;\n  return out;\n}\n/**\r\n * Scales the mat3 by the dimensions in the given vec2\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the matrix to rotate\r\n * @param {ReadonlyVec2} v the vec2 to scale the matrix by\r\n * @returns {mat3} out\r\n **/\n\nexport function scale(out, a, v) {\n  var x = v[0],\n      y = v[1];\n  out[0] = x * a[0];\n  out[1] = x * a[1];\n  out[2] = x * a[2];\n  out[3] = y * a[3];\n  out[4] = y * a[4];\n  out[5] = y * a[5];\n  out[6] = a[6];\n  out[7] = a[7];\n  out[8] = a[8];\n  return out;\n}\n/**\r\n * Creates a matrix from a vector translation\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat3.identity(dest);\r\n *     mat3.translate(dest, dest, vec);\r\n *\r\n * @param {mat3} out mat3 receiving operation result\r\n * @param {ReadonlyVec2} v Translation vector\r\n * @returns {mat3} out\r\n */\n\nexport function fromTranslation(out, v) {\n  out[0] = 1;\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = 1;\n  out[5] = 0;\n  out[6] = v[0];\n  out[7] = v[1];\n  out[8] = 1;\n  return out;\n}\n/**\r\n * Creates a matrix from a given angle\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat3.identity(dest);\r\n *     mat3.rotate(dest, dest, rad);\r\n *\r\n * @param {mat3} out mat3 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat3} out\r\n */\n\nexport function fromRotation(out, rad) {\n  var s = Math.sin(rad),\n      c = Math.cos(rad);\n  out[0] = c;\n  out[1] = s;\n  out[2] = 0;\n  out[3] = -s;\n  out[4] = c;\n  out[5] = 0;\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = 1;\n  return out;\n}\n/**\r\n * Creates a matrix from a vector scaling\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat3.identity(dest);\r\n *     mat3.scale(dest, dest, vec);\r\n *\r\n * @param {mat3} out mat3 receiving operation result\r\n * @param {ReadonlyVec2} v Scaling vector\r\n * @returns {mat3} out\r\n */\n\nexport function fromScaling(out, v) {\n  out[0] = v[0];\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = v[1];\n  out[5] = 0;\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = 1;\n  return out;\n}\n/**\r\n * Copies the values from a mat2d into a mat3\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat2d} a the matrix to copy\r\n * @returns {mat3} out\r\n **/\n\nexport function fromMat2d(out, a) {\n  out[0] = a[0];\n  out[1] = a[1];\n  out[2] = 0;\n  out[3] = a[2];\n  out[4] = a[3];\n  out[5] = 0;\n  out[6] = a[4];\n  out[7] = a[5];\n  out[8] = 1;\n  return out;\n}\n/**\r\n * Calculates a 3x3 matrix from the given quaternion\r\n *\r\n * @param {mat3} out mat3 receiving operation result\r\n * @param {ReadonlyQuat} q Quaternion to create matrix from\r\n *\r\n * @returns {mat3} out\r\n */\n\nexport function fromQuat(out, q) {\n  var x = q[0],\n      y = q[1],\n      z = q[2],\n      w = q[3];\n  var x2 = x + x;\n  var y2 = y + y;\n  var z2 = z + z;\n  var xx = x * x2;\n  var yx = y * x2;\n  var yy = y * y2;\n  var zx = z * x2;\n  var zy = z * y2;\n  var zz = z * z2;\n  var wx = w * x2;\n  var wy = w * y2;\n  var wz = w * z2;\n  out[0] = 1 - yy - zz;\n  out[3] = yx - wz;\n  out[6] = zx + wy;\n  out[1] = yx + wz;\n  out[4] = 1 - xx - zz;\n  out[7] = zy - wx;\n  out[2] = zx - wy;\n  out[5] = zy + wx;\n  out[8] = 1 - xx - yy;\n  return out;\n}\n/**\r\n * Calculates a 3x3 normal matrix (transpose inverse) from the 4x4 matrix\r\n *\r\n * @param {mat3} out mat3 receiving operation result\r\n * @param {ReadonlyMat4} a Mat4 to derive the normal matrix from\r\n *\r\n * @returns {mat3} out\r\n */\n\nexport function normalFromMat4(out, a) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2],\n      a03 = a[3];\n  var a10 = a[4],\n      a11 = a[5],\n      a12 = a[6],\n      a13 = a[7];\n  var a20 = a[8],\n      a21 = a[9],\n      a22 = a[10],\n      a23 = a[11];\n  var a30 = a[12],\n      a31 = a[13],\n      a32 = a[14],\n      a33 = a[15];\n  var b00 = a00 * a11 - a01 * a10;\n  var b01 = a00 * a12 - a02 * a10;\n  var b02 = a00 * a13 - a03 * a10;\n  var b03 = a01 * a12 - a02 * a11;\n  var b04 = a01 * a13 - a03 * a11;\n  var b05 = a02 * a13 - a03 * a12;\n  var b06 = a20 * a31 - a21 * a30;\n  var b07 = a20 * a32 - a22 * a30;\n  var b08 = a20 * a33 - a23 * a30;\n  var b09 = a21 * a32 - a22 * a31;\n  var b10 = a21 * a33 - a23 * a31;\n  var b11 = a22 * a33 - a23 * a32; // Calculate the determinant\n\n  var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n  if (!det) {\n    return null;\n  }\n\n  det = 1.0 / det;\n  out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\n  out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\n  out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\n  out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\n  out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\n  out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\n  out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\n  out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\n  out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\n  return out;\n}\n/**\r\n * Generates a 2D projection matrix with the given bounds\r\n *\r\n * @param {mat3} out mat3 frustum matrix will be written into\r\n * @param {number} width Width of your gl context\r\n * @param {number} height Height of gl context\r\n * @returns {mat3} out\r\n */\n\nexport function projection(out, width, height) {\n  out[0] = 2 / width;\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = -2 / height;\n  out[5] = 0;\n  out[6] = -1;\n  out[7] = 1;\n  out[8] = 1;\n  return out;\n}\n/**\r\n * Returns a string representation of a mat3\r\n *\r\n * @param {ReadonlyMat3} a matrix to represent as a string\r\n * @returns {String} string representation of the matrix\r\n */\n\nexport function str(a) {\n  return \"mat3(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \", \" + a[4] + \", \" + a[5] + \", \" + a[6] + \", \" + a[7] + \", \" + a[8] + \")\";\n}\n/**\r\n * Returns Frobenius norm of a mat3\r\n *\r\n * @param {ReadonlyMat3} a the matrix to calculate Frobenius norm of\r\n * @returns {Number} Frobenius norm\r\n */\n\nexport function frob(a) {\n  return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]);\n}\n/**\r\n * Adds two mat3's\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the first operand\r\n * @param {ReadonlyMat3} b the second operand\r\n * @returns {mat3} out\r\n */\n\nexport function add(out, a, b) {\n  out[0] = a[0] + b[0];\n  out[1] = a[1] + b[1];\n  out[2] = a[2] + b[2];\n  out[3] = a[3] + b[3];\n  out[4] = a[4] + b[4];\n  out[5] = a[5] + b[5];\n  out[6] = a[6] + b[6];\n  out[7] = a[7] + b[7];\n  out[8] = a[8] + b[8];\n  return out;\n}\n/**\r\n * Subtracts matrix b from matrix a\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the first operand\r\n * @param {ReadonlyMat3} b the second operand\r\n * @returns {mat3} out\r\n */\n\nexport function subtract(out, a, b) {\n  out[0] = a[0] - b[0];\n  out[1] = a[1] - b[1];\n  out[2] = a[2] - b[2];\n  out[3] = a[3] - b[3];\n  out[4] = a[4] - b[4];\n  out[5] = a[5] - b[5];\n  out[6] = a[6] - b[6];\n  out[7] = a[7] - b[7];\n  out[8] = a[8] - b[8];\n  return out;\n}\n/**\r\n * Multiply each element of the matrix by a scalar.\r\n *\r\n * @param {mat3} out the receiving matrix\r\n * @param {ReadonlyMat3} a the matrix to scale\r\n * @param {Number} b amount to scale the matrix's elements by\r\n * @returns {mat3} out\r\n */\n\nexport function multiplyScalar(out, a, b) {\n  out[0] = a[0] * b;\n  out[1] = a[1] * b;\n  out[2] = a[2] * b;\n  out[3] = a[3] * b;\n  out[4] = a[4] * b;\n  out[5] = a[5] * b;\n  out[6] = a[6] * b;\n  out[7] = a[7] * b;\n  out[8] = a[8] * b;\n  return out;\n}\n/**\r\n * Adds two mat3's after multiplying each element of the second operand by a scalar value.\r\n *\r\n * @param {mat3} out the receiving vector\r\n * @param {ReadonlyMat3} a the first operand\r\n * @param {ReadonlyMat3} b the second operand\r\n * @param {Number} scale the amount to scale b's elements by before adding\r\n * @returns {mat3} out\r\n */\n\nexport function multiplyScalarAndAdd(out, a, b, scale) {\n  out[0] = a[0] + b[0] * scale;\n  out[1] = a[1] + b[1] * scale;\n  out[2] = a[2] + b[2] * scale;\n  out[3] = a[3] + b[3] * scale;\n  out[4] = a[4] + b[4] * scale;\n  out[5] = a[5] + b[5] * scale;\n  out[6] = a[6] + b[6] * scale;\n  out[7] = a[7] + b[7] * scale;\n  out[8] = a[8] + b[8] * scale;\n  return out;\n}\n/**\r\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {ReadonlyMat3} a The first matrix.\r\n * @param {ReadonlyMat3} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\n\nexport function exactEquals(a, b) {\n  return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8];\n}\n/**\r\n * Returns whether or not the matrices have approximately the same elements in the same position.\r\n *\r\n * @param {ReadonlyMat3} a The first matrix.\r\n * @param {ReadonlyMat3} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\n\nexport function equals(a, b) {\n  var a0 = a[0],\n      a1 = a[1],\n      a2 = a[2],\n      a3 = a[3],\n      a4 = a[4],\n      a5 = a[5],\n      a6 = a[6],\n      a7 = a[7],\n      a8 = a[8];\n  var b0 = b[0],\n      b1 = b[1],\n      b2 = b[2],\n      b3 = b[3],\n      b4 = b[4],\n      b5 = b[5],\n      b6 = b[6],\n      b7 = b[7],\n      b8 = b[8];\n  return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8));\n}\n/**\r\n * Alias for {@link mat3.multiply}\r\n * @function\r\n */\n\nexport var mul = multiply;\n/**\r\n * Alias for {@link mat3.subtract}\r\n * @function\r\n */\n\nexport var sub = subtract;","import * as glMatrix from \"./common.js\";\n/**\r\n * 4x4 Matrix<br>Format: column-major, when typed out it looks like row-major<br>The matrices are being post multiplied.\r\n * @module mat4\r\n */\n\n/**\r\n * Creates a new identity mat4\r\n *\r\n * @returns {mat4} a new 4x4 matrix\r\n */\n\nexport function create() {\n  var out = new glMatrix.ARRAY_TYPE(16);\n\n  if (glMatrix.ARRAY_TYPE != Float32Array) {\n    out[1] = 0;\n    out[2] = 0;\n    out[3] = 0;\n    out[4] = 0;\n    out[6] = 0;\n    out[7] = 0;\n    out[8] = 0;\n    out[9] = 0;\n    out[11] = 0;\n    out[12] = 0;\n    out[13] = 0;\n    out[14] = 0;\n  }\n\n  out[0] = 1;\n  out[5] = 1;\n  out[10] = 1;\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Creates a new mat4 initialized with values from an existing matrix\r\n *\r\n * @param {ReadonlyMat4} a matrix to clone\r\n * @returns {mat4} a new 4x4 matrix\r\n */\n\nexport function clone(a) {\n  var out = new glMatrix.ARRAY_TYPE(16);\n  out[0] = a[0];\n  out[1] = a[1];\n  out[2] = a[2];\n  out[3] = a[3];\n  out[4] = a[4];\n  out[5] = a[5];\n  out[6] = a[6];\n  out[7] = a[7];\n  out[8] = a[8];\n  out[9] = a[9];\n  out[10] = a[10];\n  out[11] = a[11];\n  out[12] = a[12];\n  out[13] = a[13];\n  out[14] = a[14];\n  out[15] = a[15];\n  return out;\n}\n/**\r\n * Copy the values from one mat4 to another\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the source matrix\r\n * @returns {mat4} out\r\n */\n\nexport function copy(out, a) {\n  out[0] = a[0];\n  out[1] = a[1];\n  out[2] = a[2];\n  out[3] = a[3];\n  out[4] = a[4];\n  out[5] = a[5];\n  out[6] = a[6];\n  out[7] = a[7];\n  out[8] = a[8];\n  out[9] = a[9];\n  out[10] = a[10];\n  out[11] = a[11];\n  out[12] = a[12];\n  out[13] = a[13];\n  out[14] = a[14];\n  out[15] = a[15];\n  return out;\n}\n/**\r\n * Create a new mat4 with the given values\r\n *\r\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\r\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\r\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\r\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\r\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\r\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\r\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\r\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\r\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\r\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\r\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\r\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\r\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\r\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\r\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\r\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\r\n * @returns {mat4} A new mat4\r\n */\n\nexport function fromValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n  var out = new glMatrix.ARRAY_TYPE(16);\n  out[0] = m00;\n  out[1] = m01;\n  out[2] = m02;\n  out[3] = m03;\n  out[4] = m10;\n  out[5] = m11;\n  out[6] = m12;\n  out[7] = m13;\n  out[8] = m20;\n  out[9] = m21;\n  out[10] = m22;\n  out[11] = m23;\n  out[12] = m30;\n  out[13] = m31;\n  out[14] = m32;\n  out[15] = m33;\n  return out;\n}\n/**\r\n * Set the components of a mat4 to the given values\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {Number} m00 Component in column 0, row 0 position (index 0)\r\n * @param {Number} m01 Component in column 0, row 1 position (index 1)\r\n * @param {Number} m02 Component in column 0, row 2 position (index 2)\r\n * @param {Number} m03 Component in column 0, row 3 position (index 3)\r\n * @param {Number} m10 Component in column 1, row 0 position (index 4)\r\n * @param {Number} m11 Component in column 1, row 1 position (index 5)\r\n * @param {Number} m12 Component in column 1, row 2 position (index 6)\r\n * @param {Number} m13 Component in column 1, row 3 position (index 7)\r\n * @param {Number} m20 Component in column 2, row 0 position (index 8)\r\n * @param {Number} m21 Component in column 2, row 1 position (index 9)\r\n * @param {Number} m22 Component in column 2, row 2 position (index 10)\r\n * @param {Number} m23 Component in column 2, row 3 position (index 11)\r\n * @param {Number} m30 Component in column 3, row 0 position (index 12)\r\n * @param {Number} m31 Component in column 3, row 1 position (index 13)\r\n * @param {Number} m32 Component in column 3, row 2 position (index 14)\r\n * @param {Number} m33 Component in column 3, row 3 position (index 15)\r\n * @returns {mat4} out\r\n */\n\nexport function set(out, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) {\n  out[0] = m00;\n  out[1] = m01;\n  out[2] = m02;\n  out[3] = m03;\n  out[4] = m10;\n  out[5] = m11;\n  out[6] = m12;\n  out[7] = m13;\n  out[8] = m20;\n  out[9] = m21;\n  out[10] = m22;\n  out[11] = m23;\n  out[12] = m30;\n  out[13] = m31;\n  out[14] = m32;\n  out[15] = m33;\n  return out;\n}\n/**\r\n * Set a mat4 to the identity matrix\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @returns {mat4} out\r\n */\n\nexport function identity(out) {\n  out[0] = 1;\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = 0;\n  out[5] = 1;\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = 0;\n  out[9] = 0;\n  out[10] = 1;\n  out[11] = 0;\n  out[12] = 0;\n  out[13] = 0;\n  out[14] = 0;\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Transpose the values of a mat4\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the source matrix\r\n * @returns {mat4} out\r\n */\n\nexport function transpose(out, a) {\n  // If we are transposing ourselves we can skip a few steps but have to cache some values\n  if (out === a) {\n    var a01 = a[1],\n        a02 = a[2],\n        a03 = a[3];\n    var a12 = a[6],\n        a13 = a[7];\n    var a23 = a[11];\n    out[1] = a[4];\n    out[2] = a[8];\n    out[3] = a[12];\n    out[4] = a01;\n    out[6] = a[9];\n    out[7] = a[13];\n    out[8] = a02;\n    out[9] = a12;\n    out[11] = a[14];\n    out[12] = a03;\n    out[13] = a13;\n    out[14] = a23;\n  } else {\n    out[0] = a[0];\n    out[1] = a[4];\n    out[2] = a[8];\n    out[3] = a[12];\n    out[4] = a[1];\n    out[5] = a[5];\n    out[6] = a[9];\n    out[7] = a[13];\n    out[8] = a[2];\n    out[9] = a[6];\n    out[10] = a[10];\n    out[11] = a[14];\n    out[12] = a[3];\n    out[13] = a[7];\n    out[14] = a[11];\n    out[15] = a[15];\n  }\n\n  return out;\n}\n/**\r\n * Inverts a mat4\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the source matrix\r\n * @returns {mat4} out\r\n */\n\nexport function invert(out, a) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2],\n      a03 = a[3];\n  var a10 = a[4],\n      a11 = a[5],\n      a12 = a[6],\n      a13 = a[7];\n  var a20 = a[8],\n      a21 = a[9],\n      a22 = a[10],\n      a23 = a[11];\n  var a30 = a[12],\n      a31 = a[13],\n      a32 = a[14],\n      a33 = a[15];\n  var b00 = a00 * a11 - a01 * a10;\n  var b01 = a00 * a12 - a02 * a10;\n  var b02 = a00 * a13 - a03 * a10;\n  var b03 = a01 * a12 - a02 * a11;\n  var b04 = a01 * a13 - a03 * a11;\n  var b05 = a02 * a13 - a03 * a12;\n  var b06 = a20 * a31 - a21 * a30;\n  var b07 = a20 * a32 - a22 * a30;\n  var b08 = a20 * a33 - a23 * a30;\n  var b09 = a21 * a32 - a22 * a31;\n  var b10 = a21 * a33 - a23 * a31;\n  var b11 = a22 * a33 - a23 * a32; // Calculate the determinant\n\n  var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n  if (!det) {\n    return null;\n  }\n\n  det = 1.0 / det;\n  out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\n  out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\n  out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\n  out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;\n  out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\n  out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\n  out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\n  out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;\n  out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\n  out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\n  out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\n  out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;\n  out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;\n  out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;\n  out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;\n  out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;\n  return out;\n}\n/**\r\n * Calculates the adjugate of a mat4\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the source matrix\r\n * @returns {mat4} out\r\n */\n\nexport function adjoint(out, a) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2],\n      a03 = a[3];\n  var a10 = a[4],\n      a11 = a[5],\n      a12 = a[6],\n      a13 = a[7];\n  var a20 = a[8],\n      a21 = a[9],\n      a22 = a[10],\n      a23 = a[11];\n  var a30 = a[12],\n      a31 = a[13],\n      a32 = a[14],\n      a33 = a[15];\n  out[0] = a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22);\n  out[1] = -(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22));\n  out[2] = a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12);\n  out[3] = -(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12));\n  out[4] = -(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22));\n  out[5] = a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22);\n  out[6] = -(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12));\n  out[7] = a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12);\n  out[8] = a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21);\n  out[9] = -(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21));\n  out[10] = a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11);\n  out[11] = -(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11));\n  out[12] = -(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21));\n  out[13] = a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21);\n  out[14] = -(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11));\n  out[15] = a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11);\n  return out;\n}\n/**\r\n * Calculates the determinant of a mat4\r\n *\r\n * @param {ReadonlyMat4} a the source matrix\r\n * @returns {Number} determinant of a\r\n */\n\nexport function determinant(a) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2],\n      a03 = a[3];\n  var a10 = a[4],\n      a11 = a[5],\n      a12 = a[6],\n      a13 = a[7];\n  var a20 = a[8],\n      a21 = a[9],\n      a22 = a[10],\n      a23 = a[11];\n  var a30 = a[12],\n      a31 = a[13],\n      a32 = a[14],\n      a33 = a[15];\n  var b00 = a00 * a11 - a01 * a10;\n  var b01 = a00 * a12 - a02 * a10;\n  var b02 = a00 * a13 - a03 * a10;\n  var b03 = a01 * a12 - a02 * a11;\n  var b04 = a01 * a13 - a03 * a11;\n  var b05 = a02 * a13 - a03 * a12;\n  var b06 = a20 * a31 - a21 * a30;\n  var b07 = a20 * a32 - a22 * a30;\n  var b08 = a20 * a33 - a23 * a30;\n  var b09 = a21 * a32 - a22 * a31;\n  var b10 = a21 * a33 - a23 * a31;\n  var b11 = a22 * a33 - a23 * a32; // Calculate the determinant\n\n  return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n}\n/**\r\n * Multiplies two mat4s\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the first operand\r\n * @param {ReadonlyMat4} b the second operand\r\n * @returns {mat4} out\r\n */\n\nexport function multiply(out, a, b) {\n  var a00 = a[0],\n      a01 = a[1],\n      a02 = a[2],\n      a03 = a[3];\n  var a10 = a[4],\n      a11 = a[5],\n      a12 = a[6],\n      a13 = a[7];\n  var a20 = a[8],\n      a21 = a[9],\n      a22 = a[10],\n      a23 = a[11];\n  var a30 = a[12],\n      a31 = a[13],\n      a32 = a[14],\n      a33 = a[15]; // Cache only the current line of the second matrix\n\n  var b0 = b[0],\n      b1 = b[1],\n      b2 = b[2],\n      b3 = b[3];\n  out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n  out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n  out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n  out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n  b0 = b[4];\n  b1 = b[5];\n  b2 = b[6];\n  b3 = b[7];\n  out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n  out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n  out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n  out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n  b0 = b[8];\n  b1 = b[9];\n  b2 = b[10];\n  b3 = b[11];\n  out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n  out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n  out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n  out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n  b0 = b[12];\n  b1 = b[13];\n  b2 = b[14];\n  b3 = b[15];\n  out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n  out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n  out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n  out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n  return out;\n}\n/**\r\n * Translate a mat4 by the given vector\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the matrix to translate\r\n * @param {ReadonlyVec3} v vector to translate by\r\n * @returns {mat4} out\r\n */\n\nexport function translate(out, a, v) {\n  var x = v[0],\n      y = v[1],\n      z = v[2];\n  var a00, a01, a02, a03;\n  var a10, a11, a12, a13;\n  var a20, a21, a22, a23;\n\n  if (a === out) {\n    out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];\n    out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];\n    out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];\n    out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];\n  } else {\n    a00 = a[0];\n    a01 = a[1];\n    a02 = a[2];\n    a03 = a[3];\n    a10 = a[4];\n    a11 = a[5];\n    a12 = a[6];\n    a13 = a[7];\n    a20 = a[8];\n    a21 = a[9];\n    a22 = a[10];\n    a23 = a[11];\n    out[0] = a00;\n    out[1] = a01;\n    out[2] = a02;\n    out[3] = a03;\n    out[4] = a10;\n    out[5] = a11;\n    out[6] = a12;\n    out[7] = a13;\n    out[8] = a20;\n    out[9] = a21;\n    out[10] = a22;\n    out[11] = a23;\n    out[12] = a00 * x + a10 * y + a20 * z + a[12];\n    out[13] = a01 * x + a11 * y + a21 * z + a[13];\n    out[14] = a02 * x + a12 * y + a22 * z + a[14];\n    out[15] = a03 * x + a13 * y + a23 * z + a[15];\n  }\n\n  return out;\n}\n/**\r\n * Scales the mat4 by the dimensions in the given vec3 not using vectorization\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the matrix to scale\r\n * @param {ReadonlyVec3} v the vec3 to scale the matrix by\r\n * @returns {mat4} out\r\n **/\n\nexport function scale(out, a, v) {\n  var x = v[0],\n      y = v[1],\n      z = v[2];\n  out[0] = a[0] * x;\n  out[1] = a[1] * x;\n  out[2] = a[2] * x;\n  out[3] = a[3] * x;\n  out[4] = a[4] * y;\n  out[5] = a[5] * y;\n  out[6] = a[6] * y;\n  out[7] = a[7] * y;\n  out[8] = a[8] * z;\n  out[9] = a[9] * z;\n  out[10] = a[10] * z;\n  out[11] = a[11] * z;\n  out[12] = a[12];\n  out[13] = a[13];\n  out[14] = a[14];\n  out[15] = a[15];\n  return out;\n}\n/**\r\n * Rotates a mat4 by the given angle around the given axis\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @param {ReadonlyVec3} axis the axis to rotate around\r\n * @returns {mat4} out\r\n */\n\nexport function rotate(out, a, rad, axis) {\n  var x = axis[0],\n      y = axis[1],\n      z = axis[2];\n  var len = Math.hypot(x, y, z);\n  var s, c, t;\n  var a00, a01, a02, a03;\n  var a10, a11, a12, a13;\n  var a20, a21, a22, a23;\n  var b00, b01, b02;\n  var b10, b11, b12;\n  var b20, b21, b22;\n\n  if (len < glMatrix.EPSILON) {\n    return null;\n  }\n\n  len = 1 / len;\n  x *= len;\n  y *= len;\n  z *= len;\n  s = Math.sin(rad);\n  c = Math.cos(rad);\n  t = 1 - c;\n  a00 = a[0];\n  a01 = a[1];\n  a02 = a[2];\n  a03 = a[3];\n  a10 = a[4];\n  a11 = a[5];\n  a12 = a[6];\n  a13 = a[7];\n  a20 = a[8];\n  a21 = a[9];\n  a22 = a[10];\n  a23 = a[11]; // Construct the elements of the rotation matrix\n\n  b00 = x * x * t + c;\n  b01 = y * x * t + z * s;\n  b02 = z * x * t - y * s;\n  b10 = x * y * t - z * s;\n  b11 = y * y * t + c;\n  b12 = z * y * t + x * s;\n  b20 = x * z * t + y * s;\n  b21 = y * z * t - x * s;\n  b22 = z * z * t + c; // Perform rotation-specific matrix multiplication\n\n  out[0] = a00 * b00 + a10 * b01 + a20 * b02;\n  out[1] = a01 * b00 + a11 * b01 + a21 * b02;\n  out[2] = a02 * b00 + a12 * b01 + a22 * b02;\n  out[3] = a03 * b00 + a13 * b01 + a23 * b02;\n  out[4] = a00 * b10 + a10 * b11 + a20 * b12;\n  out[5] = a01 * b10 + a11 * b11 + a21 * b12;\n  out[6] = a02 * b10 + a12 * b11 + a22 * b12;\n  out[7] = a03 * b10 + a13 * b11 + a23 * b12;\n  out[8] = a00 * b20 + a10 * b21 + a20 * b22;\n  out[9] = a01 * b20 + a11 * b21 + a21 * b22;\n  out[10] = a02 * b20 + a12 * b21 + a22 * b22;\n  out[11] = a03 * b20 + a13 * b21 + a23 * b22;\n\n  if (a !== out) {\n    // If the source and destination differ, copy the unchanged last row\n    out[12] = a[12];\n    out[13] = a[13];\n    out[14] = a[14];\n    out[15] = a[15];\n  }\n\n  return out;\n}\n/**\r\n * Rotates a matrix by the given angle around the X axis\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\n\nexport function rotateX(out, a, rad) {\n  var s = Math.sin(rad);\n  var c = Math.cos(rad);\n  var a10 = a[4];\n  var a11 = a[5];\n  var a12 = a[6];\n  var a13 = a[7];\n  var a20 = a[8];\n  var a21 = a[9];\n  var a22 = a[10];\n  var a23 = a[11];\n\n  if (a !== out) {\n    // If the source and destination differ, copy the unchanged rows\n    out[0] = a[0];\n    out[1] = a[1];\n    out[2] = a[2];\n    out[3] = a[3];\n    out[12] = a[12];\n    out[13] = a[13];\n    out[14] = a[14];\n    out[15] = a[15];\n  } // Perform axis-specific matrix multiplication\n\n\n  out[4] = a10 * c + a20 * s;\n  out[5] = a11 * c + a21 * s;\n  out[6] = a12 * c + a22 * s;\n  out[7] = a13 * c + a23 * s;\n  out[8] = a20 * c - a10 * s;\n  out[9] = a21 * c - a11 * s;\n  out[10] = a22 * c - a12 * s;\n  out[11] = a23 * c - a13 * s;\n  return out;\n}\n/**\r\n * Rotates a matrix by the given angle around the Y axis\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\n\nexport function rotateY(out, a, rad) {\n  var s = Math.sin(rad);\n  var c = Math.cos(rad);\n  var a00 = a[0];\n  var a01 = a[1];\n  var a02 = a[2];\n  var a03 = a[3];\n  var a20 = a[8];\n  var a21 = a[9];\n  var a22 = a[10];\n  var a23 = a[11];\n\n  if (a !== out) {\n    // If the source and destination differ, copy the unchanged rows\n    out[4] = a[4];\n    out[5] = a[5];\n    out[6] = a[6];\n    out[7] = a[7];\n    out[12] = a[12];\n    out[13] = a[13];\n    out[14] = a[14];\n    out[15] = a[15];\n  } // Perform axis-specific matrix multiplication\n\n\n  out[0] = a00 * c - a20 * s;\n  out[1] = a01 * c - a21 * s;\n  out[2] = a02 * c - a22 * s;\n  out[3] = a03 * c - a23 * s;\n  out[8] = a00 * s + a20 * c;\n  out[9] = a01 * s + a21 * c;\n  out[10] = a02 * s + a22 * c;\n  out[11] = a03 * s + a23 * c;\n  return out;\n}\n/**\r\n * Rotates a matrix by the given angle around the Z axis\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the matrix to rotate\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\n\nexport function rotateZ(out, a, rad) {\n  var s = Math.sin(rad);\n  var c = Math.cos(rad);\n  var a00 = a[0];\n  var a01 = a[1];\n  var a02 = a[2];\n  var a03 = a[3];\n  var a10 = a[4];\n  var a11 = a[5];\n  var a12 = a[6];\n  var a13 = a[7];\n\n  if (a !== out) {\n    // If the source and destination differ, copy the unchanged last row\n    out[8] = a[8];\n    out[9] = a[9];\n    out[10] = a[10];\n    out[11] = a[11];\n    out[12] = a[12];\n    out[13] = a[13];\n    out[14] = a[14];\n    out[15] = a[15];\n  } // Perform axis-specific matrix multiplication\n\n\n  out[0] = a00 * c + a10 * s;\n  out[1] = a01 * c + a11 * s;\n  out[2] = a02 * c + a12 * s;\n  out[3] = a03 * c + a13 * s;\n  out[4] = a10 * c - a00 * s;\n  out[5] = a11 * c - a01 * s;\n  out[6] = a12 * c - a02 * s;\n  out[7] = a13 * c - a03 * s;\n  return out;\n}\n/**\r\n * Creates a matrix from a vector translation\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.translate(dest, dest, vec);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {ReadonlyVec3} v Translation vector\r\n * @returns {mat4} out\r\n */\n\nexport function fromTranslation(out, v) {\n  out[0] = 1;\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = 0;\n  out[5] = 1;\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = 0;\n  out[9] = 0;\n  out[10] = 1;\n  out[11] = 0;\n  out[12] = v[0];\n  out[13] = v[1];\n  out[14] = v[2];\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Creates a matrix from a vector scaling\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.scale(dest, dest, vec);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {ReadonlyVec3} v Scaling vector\r\n * @returns {mat4} out\r\n */\n\nexport function fromScaling(out, v) {\n  out[0] = v[0];\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = 0;\n  out[5] = v[1];\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = 0;\n  out[9] = 0;\n  out[10] = v[2];\n  out[11] = 0;\n  out[12] = 0;\n  out[13] = 0;\n  out[14] = 0;\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Creates a matrix from a given angle around a given axis\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.rotate(dest, dest, rad, axis);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @param {ReadonlyVec3} axis the axis to rotate around\r\n * @returns {mat4} out\r\n */\n\nexport function fromRotation(out, rad, axis) {\n  var x = axis[0],\n      y = axis[1],\n      z = axis[2];\n  var len = Math.hypot(x, y, z);\n  var s, c, t;\n\n  if (len < glMatrix.EPSILON) {\n    return null;\n  }\n\n  len = 1 / len;\n  x *= len;\n  y *= len;\n  z *= len;\n  s = Math.sin(rad);\n  c = Math.cos(rad);\n  t = 1 - c; // Perform rotation-specific matrix multiplication\n\n  out[0] = x * x * t + c;\n  out[1] = y * x * t + z * s;\n  out[2] = z * x * t - y * s;\n  out[3] = 0;\n  out[4] = x * y * t - z * s;\n  out[5] = y * y * t + c;\n  out[6] = z * y * t + x * s;\n  out[7] = 0;\n  out[8] = x * z * t + y * s;\n  out[9] = y * z * t - x * s;\n  out[10] = z * z * t + c;\n  out[11] = 0;\n  out[12] = 0;\n  out[13] = 0;\n  out[14] = 0;\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Creates a matrix from the given angle around the X axis\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.rotateX(dest, dest, rad);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\n\nexport function fromXRotation(out, rad) {\n  var s = Math.sin(rad);\n  var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n  out[0] = 1;\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = 0;\n  out[5] = c;\n  out[6] = s;\n  out[7] = 0;\n  out[8] = 0;\n  out[9] = -s;\n  out[10] = c;\n  out[11] = 0;\n  out[12] = 0;\n  out[13] = 0;\n  out[14] = 0;\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Creates a matrix from the given angle around the Y axis\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.rotateY(dest, dest, rad);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\n\nexport function fromYRotation(out, rad) {\n  var s = Math.sin(rad);\n  var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n  out[0] = c;\n  out[1] = 0;\n  out[2] = -s;\n  out[3] = 0;\n  out[4] = 0;\n  out[5] = 1;\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = s;\n  out[9] = 0;\n  out[10] = c;\n  out[11] = 0;\n  out[12] = 0;\n  out[13] = 0;\n  out[14] = 0;\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Creates a matrix from the given angle around the Z axis\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.rotateZ(dest, dest, rad);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {Number} rad the angle to rotate the matrix by\r\n * @returns {mat4} out\r\n */\n\nexport function fromZRotation(out, rad) {\n  var s = Math.sin(rad);\n  var c = Math.cos(rad); // Perform axis-specific matrix multiplication\n\n  out[0] = c;\n  out[1] = s;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = -s;\n  out[5] = c;\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = 0;\n  out[9] = 0;\n  out[10] = 1;\n  out[11] = 0;\n  out[12] = 0;\n  out[13] = 0;\n  out[14] = 0;\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Creates a matrix from a quaternion rotation and vector translation\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.translate(dest, vec);\r\n *     let quatMat = mat4.create();\r\n *     quat4.toMat4(quat, quatMat);\r\n *     mat4.multiply(dest, quatMat);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {quat4} q Rotation quaternion\r\n * @param {ReadonlyVec3} v Translation vector\r\n * @returns {mat4} out\r\n */\n\nexport function fromRotationTranslation(out, q, v) {\n  // Quaternion math\n  var x = q[0],\n      y = q[1],\n      z = q[2],\n      w = q[3];\n  var x2 = x + x;\n  var y2 = y + y;\n  var z2 = z + z;\n  var xx = x * x2;\n  var xy = x * y2;\n  var xz = x * z2;\n  var yy = y * y2;\n  var yz = y * z2;\n  var zz = z * z2;\n  var wx = w * x2;\n  var wy = w * y2;\n  var wz = w * z2;\n  out[0] = 1 - (yy + zz);\n  out[1] = xy + wz;\n  out[2] = xz - wy;\n  out[3] = 0;\n  out[4] = xy - wz;\n  out[5] = 1 - (xx + zz);\n  out[6] = yz + wx;\n  out[7] = 0;\n  out[8] = xz + wy;\n  out[9] = yz - wx;\n  out[10] = 1 - (xx + yy);\n  out[11] = 0;\n  out[12] = v[0];\n  out[13] = v[1];\n  out[14] = v[2];\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Creates a new mat4 from a dual quat.\r\n *\r\n * @param {mat4} out Matrix\r\n * @param {ReadonlyQuat2} a Dual Quaternion\r\n * @returns {mat4} mat4 receiving operation result\r\n */\n\nexport function fromQuat2(out, a) {\n  var translation = new glMatrix.ARRAY_TYPE(3);\n  var bx = -a[0],\n      by = -a[1],\n      bz = -a[2],\n      bw = a[3],\n      ax = a[4],\n      ay = a[5],\n      az = a[6],\n      aw = a[7];\n  var magnitude = bx * bx + by * by + bz * bz + bw * bw; //Only scale if it makes sense\n\n  if (magnitude > 0) {\n    translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2 / magnitude;\n    translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2 / magnitude;\n    translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2 / magnitude;\n  } else {\n    translation[0] = (ax * bw + aw * bx + ay * bz - az * by) * 2;\n    translation[1] = (ay * bw + aw * by + az * bx - ax * bz) * 2;\n    translation[2] = (az * bw + aw * bz + ax * by - ay * bx) * 2;\n  }\n\n  fromRotationTranslation(out, a, translation);\n  return out;\n}\n/**\r\n * Returns the translation vector component of a transformation\r\n *  matrix. If a matrix is built with fromRotationTranslation,\r\n *  the returned vector will be the same as the translation vector\r\n *  originally supplied.\r\n * @param  {vec3} out Vector to receive translation component\r\n * @param  {ReadonlyMat4} mat Matrix to be decomposed (input)\r\n * @return {vec3} out\r\n */\n\nexport function getTranslation(out, mat) {\n  out[0] = mat[12];\n  out[1] = mat[13];\n  out[2] = mat[14];\n  return out;\n}\n/**\r\n * Returns the scaling factor component of a transformation\r\n *  matrix. If a matrix is built with fromRotationTranslationScale\r\n *  with a normalized Quaternion paramter, the returned vector will be\r\n *  the same as the scaling vector\r\n *  originally supplied.\r\n * @param  {vec3} out Vector to receive scaling factor component\r\n * @param  {ReadonlyMat4} mat Matrix to be decomposed (input)\r\n * @return {vec3} out\r\n */\n\nexport function getScaling(out, mat) {\n  var m11 = mat[0];\n  var m12 = mat[1];\n  var m13 = mat[2];\n  var m21 = mat[4];\n  var m22 = mat[5];\n  var m23 = mat[6];\n  var m31 = mat[8];\n  var m32 = mat[9];\n  var m33 = mat[10];\n  out[0] = Math.hypot(m11, m12, m13);\n  out[1] = Math.hypot(m21, m22, m23);\n  out[2] = Math.hypot(m31, m32, m33);\n  return out;\n}\n/**\r\n * Returns a quaternion representing the rotational component\r\n *  of a transformation matrix. If a matrix is built with\r\n *  fromRotationTranslation, the returned quaternion will be the\r\n *  same as the quaternion originally supplied.\r\n * @param {quat} out Quaternion to receive the rotation component\r\n * @param {ReadonlyMat4} mat Matrix to be decomposed (input)\r\n * @return {quat} out\r\n */\n\nexport function getRotation(out, mat) {\n  var scaling = new glMatrix.ARRAY_TYPE(3);\n  getScaling(scaling, mat);\n  var is1 = 1 / scaling[0];\n  var is2 = 1 / scaling[1];\n  var is3 = 1 / scaling[2];\n  var sm11 = mat[0] * is1;\n  var sm12 = mat[1] * is2;\n  var sm13 = mat[2] * is3;\n  var sm21 = mat[4] * is1;\n  var sm22 = mat[5] * is2;\n  var sm23 = mat[6] * is3;\n  var sm31 = mat[8] * is1;\n  var sm32 = mat[9] * is2;\n  var sm33 = mat[10] * is3;\n  var trace = sm11 + sm22 + sm33;\n  var S = 0;\n\n  if (trace > 0) {\n    S = Math.sqrt(trace + 1.0) * 2;\n    out[3] = 0.25 * S;\n    out[0] = (sm23 - sm32) / S;\n    out[1] = (sm31 - sm13) / S;\n    out[2] = (sm12 - sm21) / S;\n  } else if (sm11 > sm22 && sm11 > sm33) {\n    S = Math.sqrt(1.0 + sm11 - sm22 - sm33) * 2;\n    out[3] = (sm23 - sm32) / S;\n    out[0] = 0.25 * S;\n    out[1] = (sm12 + sm21) / S;\n    out[2] = (sm31 + sm13) / S;\n  } else if (sm22 > sm33) {\n    S = Math.sqrt(1.0 + sm22 - sm11 - sm33) * 2;\n    out[3] = (sm31 - sm13) / S;\n    out[0] = (sm12 + sm21) / S;\n    out[1] = 0.25 * S;\n    out[2] = (sm23 + sm32) / S;\n  } else {\n    S = Math.sqrt(1.0 + sm33 - sm11 - sm22) * 2;\n    out[3] = (sm12 - sm21) / S;\n    out[0] = (sm31 + sm13) / S;\n    out[1] = (sm23 + sm32) / S;\n    out[2] = 0.25 * S;\n  }\n\n  return out;\n}\n/**\r\n * Creates a matrix from a quaternion rotation, vector translation and vector scale\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.translate(dest, vec);\r\n *     let quatMat = mat4.create();\r\n *     quat4.toMat4(quat, quatMat);\r\n *     mat4.multiply(dest, quatMat);\r\n *     mat4.scale(dest, scale)\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {quat4} q Rotation quaternion\r\n * @param {ReadonlyVec3} v Translation vector\r\n * @param {ReadonlyVec3} s Scaling vector\r\n * @returns {mat4} out\r\n */\n\nexport function fromRotationTranslationScale(out, q, v, s) {\n  // Quaternion math\n  var x = q[0],\n      y = q[1],\n      z = q[2],\n      w = q[3];\n  var x2 = x + x;\n  var y2 = y + y;\n  var z2 = z + z;\n  var xx = x * x2;\n  var xy = x * y2;\n  var xz = x * z2;\n  var yy = y * y2;\n  var yz = y * z2;\n  var zz = z * z2;\n  var wx = w * x2;\n  var wy = w * y2;\n  var wz = w * z2;\n  var sx = s[0];\n  var sy = s[1];\n  var sz = s[2];\n  out[0] = (1 - (yy + zz)) * sx;\n  out[1] = (xy + wz) * sx;\n  out[2] = (xz - wy) * sx;\n  out[3] = 0;\n  out[4] = (xy - wz) * sy;\n  out[5] = (1 - (xx + zz)) * sy;\n  out[6] = (yz + wx) * sy;\n  out[7] = 0;\n  out[8] = (xz + wy) * sz;\n  out[9] = (yz - wx) * sz;\n  out[10] = (1 - (xx + yy)) * sz;\n  out[11] = 0;\n  out[12] = v[0];\n  out[13] = v[1];\n  out[14] = v[2];\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Creates a matrix from a quaternion rotation, vector translation and vector scale, rotating and scaling around the given origin\r\n * This is equivalent to (but much faster than):\r\n *\r\n *     mat4.identity(dest);\r\n *     mat4.translate(dest, vec);\r\n *     mat4.translate(dest, origin);\r\n *     let quatMat = mat4.create();\r\n *     quat4.toMat4(quat, quatMat);\r\n *     mat4.multiply(dest, quatMat);\r\n *     mat4.scale(dest, scale)\r\n *     mat4.translate(dest, negativeOrigin);\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {quat4} q Rotation quaternion\r\n * @param {ReadonlyVec3} v Translation vector\r\n * @param {ReadonlyVec3} s Scaling vector\r\n * @param {ReadonlyVec3} o The origin vector around which to scale and rotate\r\n * @returns {mat4} out\r\n */\n\nexport function fromRotationTranslationScaleOrigin(out, q, v, s, o) {\n  // Quaternion math\n  var x = q[0],\n      y = q[1],\n      z = q[2],\n      w = q[3];\n  var x2 = x + x;\n  var y2 = y + y;\n  var z2 = z + z;\n  var xx = x * x2;\n  var xy = x * y2;\n  var xz = x * z2;\n  var yy = y * y2;\n  var yz = y * z2;\n  var zz = z * z2;\n  var wx = w * x2;\n  var wy = w * y2;\n  var wz = w * z2;\n  var sx = s[0];\n  var sy = s[1];\n  var sz = s[2];\n  var ox = o[0];\n  var oy = o[1];\n  var oz = o[2];\n  var out0 = (1 - (yy + zz)) * sx;\n  var out1 = (xy + wz) * sx;\n  var out2 = (xz - wy) * sx;\n  var out4 = (xy - wz) * sy;\n  var out5 = (1 - (xx + zz)) * sy;\n  var out6 = (yz + wx) * sy;\n  var out8 = (xz + wy) * sz;\n  var out9 = (yz - wx) * sz;\n  var out10 = (1 - (xx + yy)) * sz;\n  out[0] = out0;\n  out[1] = out1;\n  out[2] = out2;\n  out[3] = 0;\n  out[4] = out4;\n  out[5] = out5;\n  out[6] = out6;\n  out[7] = 0;\n  out[8] = out8;\n  out[9] = out9;\n  out[10] = out10;\n  out[11] = 0;\n  out[12] = v[0] + ox - (out0 * ox + out4 * oy + out8 * oz);\n  out[13] = v[1] + oy - (out1 * ox + out5 * oy + out9 * oz);\n  out[14] = v[2] + oz - (out2 * ox + out6 * oy + out10 * oz);\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Calculates a 4x4 matrix from the given quaternion\r\n *\r\n * @param {mat4} out mat4 receiving operation result\r\n * @param {ReadonlyQuat} q Quaternion to create matrix from\r\n *\r\n * @returns {mat4} out\r\n */\n\nexport function fromQuat(out, q) {\n  var x = q[0],\n      y = q[1],\n      z = q[2],\n      w = q[3];\n  var x2 = x + x;\n  var y2 = y + y;\n  var z2 = z + z;\n  var xx = x * x2;\n  var yx = y * x2;\n  var yy = y * y2;\n  var zx = z * x2;\n  var zy = z * y2;\n  var zz = z * z2;\n  var wx = w * x2;\n  var wy = w * y2;\n  var wz = w * z2;\n  out[0] = 1 - yy - zz;\n  out[1] = yx + wz;\n  out[2] = zx - wy;\n  out[3] = 0;\n  out[4] = yx - wz;\n  out[5] = 1 - xx - zz;\n  out[6] = zy + wx;\n  out[7] = 0;\n  out[8] = zx + wy;\n  out[9] = zy - wx;\n  out[10] = 1 - xx - yy;\n  out[11] = 0;\n  out[12] = 0;\n  out[13] = 0;\n  out[14] = 0;\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Generates a frustum matrix with the given bounds\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {Number} left Left bound of the frustum\r\n * @param {Number} right Right bound of the frustum\r\n * @param {Number} bottom Bottom bound of the frustum\r\n * @param {Number} top Top bound of the frustum\r\n * @param {Number} near Near bound of the frustum\r\n * @param {Number} far Far bound of the frustum\r\n * @returns {mat4} out\r\n */\n\nexport function frustum(out, left, right, bottom, top, near, far) {\n  var rl = 1 / (right - left);\n  var tb = 1 / (top - bottom);\n  var nf = 1 / (near - far);\n  out[0] = near * 2 * rl;\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = 0;\n  out[5] = near * 2 * tb;\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = (right + left) * rl;\n  out[9] = (top + bottom) * tb;\n  out[10] = (far + near) * nf;\n  out[11] = -1;\n  out[12] = 0;\n  out[13] = 0;\n  out[14] = far * near * 2 * nf;\n  out[15] = 0;\n  return out;\n}\n/**\r\n * Generates a perspective projection matrix with the given bounds.\r\n * Passing null/undefined/no value for far will generate infinite projection matrix.\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {number} fovy Vertical field of view in radians\r\n * @param {number} aspect Aspect ratio. typically viewport width/height\r\n * @param {number} near Near bound of the frustum\r\n * @param {number} far Far bound of the frustum, can be null or Infinity\r\n * @returns {mat4} out\r\n */\n\nexport function perspective(out, fovy, aspect, near, far) {\n  var f = 1.0 / Math.tan(fovy / 2),\n      nf;\n  out[0] = f / aspect;\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = 0;\n  out[5] = f;\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = 0;\n  out[9] = 0;\n  out[11] = -1;\n  out[12] = 0;\n  out[13] = 0;\n  out[15] = 0;\n\n  if (far != null && far !== Infinity) {\n    nf = 1 / (near - far);\n    out[10] = (far + near) * nf;\n    out[14] = 2 * far * near * nf;\n  } else {\n    out[10] = -1;\n    out[14] = -2 * near;\n  }\n\n  return out;\n}\n/**\r\n * Generates a perspective projection matrix with the given field of view.\r\n * This is primarily useful for generating projection matrices to be used\r\n * with the still experiemental WebVR API.\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {Object} fov Object containing the following values: upDegrees, downDegrees, leftDegrees, rightDegrees\r\n * @param {number} near Near bound of the frustum\r\n * @param {number} far Far bound of the frustum\r\n * @returns {mat4} out\r\n */\n\nexport function perspectiveFromFieldOfView(out, fov, near, far) {\n  var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);\n  var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);\n  var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);\n  var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);\n  var xScale = 2.0 / (leftTan + rightTan);\n  var yScale = 2.0 / (upTan + downTan);\n  out[0] = xScale;\n  out[1] = 0.0;\n  out[2] = 0.0;\n  out[3] = 0.0;\n  out[4] = 0.0;\n  out[5] = yScale;\n  out[6] = 0.0;\n  out[7] = 0.0;\n  out[8] = -((leftTan - rightTan) * xScale * 0.5);\n  out[9] = (upTan - downTan) * yScale * 0.5;\n  out[10] = far / (near - far);\n  out[11] = -1.0;\n  out[12] = 0.0;\n  out[13] = 0.0;\n  out[14] = far * near / (near - far);\n  out[15] = 0.0;\n  return out;\n}\n/**\r\n * Generates a orthogonal projection matrix with the given bounds\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {number} left Left bound of the frustum\r\n * @param {number} right Right bound of the frustum\r\n * @param {number} bottom Bottom bound of the frustum\r\n * @param {number} top Top bound of the frustum\r\n * @param {number} near Near bound of the frustum\r\n * @param {number} far Far bound of the frustum\r\n * @returns {mat4} out\r\n */\n\nexport function ortho(out, left, right, bottom, top, near, far) {\n  var lr = 1 / (left - right);\n  var bt = 1 / (bottom - top);\n  var nf = 1 / (near - far);\n  out[0] = -2 * lr;\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 0;\n  out[4] = 0;\n  out[5] = -2 * bt;\n  out[6] = 0;\n  out[7] = 0;\n  out[8] = 0;\n  out[9] = 0;\n  out[10] = 2 * nf;\n  out[11] = 0;\n  out[12] = (left + right) * lr;\n  out[13] = (top + bottom) * bt;\n  out[14] = (far + near) * nf;\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Generates a look-at matrix with the given eye position, focal point, and up axis.\r\n * If you want a matrix that actually makes an object look at another object, you should use targetTo instead.\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {ReadonlyVec3} eye Position of the viewer\r\n * @param {ReadonlyVec3} center Point the viewer is looking at\r\n * @param {ReadonlyVec3} up vec3 pointing up\r\n * @returns {mat4} out\r\n */\n\nexport function lookAt(out, eye, center, up) {\n  var x0, x1, x2, y0, y1, y2, z0, z1, z2, len;\n  var eyex = eye[0];\n  var eyey = eye[1];\n  var eyez = eye[2];\n  var upx = up[0];\n  var upy = up[1];\n  var upz = up[2];\n  var centerx = center[0];\n  var centery = center[1];\n  var centerz = center[2];\n\n  if (Math.abs(eyex - centerx) < glMatrix.EPSILON && Math.abs(eyey - centery) < glMatrix.EPSILON && Math.abs(eyez - centerz) < glMatrix.EPSILON) {\n    return identity(out);\n  }\n\n  z0 = eyex - centerx;\n  z1 = eyey - centery;\n  z2 = eyez - centerz;\n  len = 1 / Math.hypot(z0, z1, z2);\n  z0 *= len;\n  z1 *= len;\n  z2 *= len;\n  x0 = upy * z2 - upz * z1;\n  x1 = upz * z0 - upx * z2;\n  x2 = upx * z1 - upy * z0;\n  len = Math.hypot(x0, x1, x2);\n\n  if (!len) {\n    x0 = 0;\n    x1 = 0;\n    x2 = 0;\n  } else {\n    len = 1 / len;\n    x0 *= len;\n    x1 *= len;\n    x2 *= len;\n  }\n\n  y0 = z1 * x2 - z2 * x1;\n  y1 = z2 * x0 - z0 * x2;\n  y2 = z0 * x1 - z1 * x0;\n  len = Math.hypot(y0, y1, y2);\n\n  if (!len) {\n    y0 = 0;\n    y1 = 0;\n    y2 = 0;\n  } else {\n    len = 1 / len;\n    y0 *= len;\n    y1 *= len;\n    y2 *= len;\n  }\n\n  out[0] = x0;\n  out[1] = y0;\n  out[2] = z0;\n  out[3] = 0;\n  out[4] = x1;\n  out[5] = y1;\n  out[6] = z1;\n  out[7] = 0;\n  out[8] = x2;\n  out[9] = y2;\n  out[10] = z2;\n  out[11] = 0;\n  out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);\n  out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);\n  out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Generates a matrix that makes something look at something else.\r\n *\r\n * @param {mat4} out mat4 frustum matrix will be written into\r\n * @param {ReadonlyVec3} eye Position of the viewer\r\n * @param {ReadonlyVec3} center Point the viewer is looking at\r\n * @param {ReadonlyVec3} up vec3 pointing up\r\n * @returns {mat4} out\r\n */\n\nexport function targetTo(out, eye, target, up) {\n  var eyex = eye[0],\n      eyey = eye[1],\n      eyez = eye[2],\n      upx = up[0],\n      upy = up[1],\n      upz = up[2];\n  var z0 = eyex - target[0],\n      z1 = eyey - target[1],\n      z2 = eyez - target[2];\n  var len = z0 * z0 + z1 * z1 + z2 * z2;\n\n  if (len > 0) {\n    len = 1 / Math.sqrt(len);\n    z0 *= len;\n    z1 *= len;\n    z2 *= len;\n  }\n\n  var x0 = upy * z2 - upz * z1,\n      x1 = upz * z0 - upx * z2,\n      x2 = upx * z1 - upy * z0;\n  len = x0 * x0 + x1 * x1 + x2 * x2;\n\n  if (len > 0) {\n    len = 1 / Math.sqrt(len);\n    x0 *= len;\n    x1 *= len;\n    x2 *= len;\n  }\n\n  out[0] = x0;\n  out[1] = x1;\n  out[2] = x2;\n  out[3] = 0;\n  out[4] = z1 * x2 - z2 * x1;\n  out[5] = z2 * x0 - z0 * x2;\n  out[6] = z0 * x1 - z1 * x0;\n  out[7] = 0;\n  out[8] = z0;\n  out[9] = z1;\n  out[10] = z2;\n  out[11] = 0;\n  out[12] = eyex;\n  out[13] = eyey;\n  out[14] = eyez;\n  out[15] = 1;\n  return out;\n}\n/**\r\n * Returns a string representation of a mat4\r\n *\r\n * @param {ReadonlyMat4} a matrix to represent as a string\r\n * @returns {String} string representation of the matrix\r\n */\n\nexport function str(a) {\n  return \"mat4(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \", \" + a[4] + \", \" + a[5] + \", \" + a[6] + \", \" + a[7] + \", \" + a[8] + \", \" + a[9] + \", \" + a[10] + \", \" + a[11] + \", \" + a[12] + \", \" + a[13] + \", \" + a[14] + \", \" + a[15] + \")\";\n}\n/**\r\n * Returns Frobenius norm of a mat4\r\n *\r\n * @param {ReadonlyMat4} a the matrix to calculate Frobenius norm of\r\n * @returns {Number} Frobenius norm\r\n */\n\nexport function frob(a) {\n  return Math.hypot(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]);\n}\n/**\r\n * Adds two mat4's\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the first operand\r\n * @param {ReadonlyMat4} b the second operand\r\n * @returns {mat4} out\r\n */\n\nexport function add(out, a, b) {\n  out[0] = a[0] + b[0];\n  out[1] = a[1] + b[1];\n  out[2] = a[2] + b[2];\n  out[3] = a[3] + b[3];\n  out[4] = a[4] + b[4];\n  out[5] = a[5] + b[5];\n  out[6] = a[6] + b[6];\n  out[7] = a[7] + b[7];\n  out[8] = a[8] + b[8];\n  out[9] = a[9] + b[9];\n  out[10] = a[10] + b[10];\n  out[11] = a[11] + b[11];\n  out[12] = a[12] + b[12];\n  out[13] = a[13] + b[13];\n  out[14] = a[14] + b[14];\n  out[15] = a[15] + b[15];\n  return out;\n}\n/**\r\n * Subtracts matrix b from matrix a\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the first operand\r\n * @param {ReadonlyMat4} b the second operand\r\n * @returns {mat4} out\r\n */\n\nexport function subtract(out, a, b) {\n  out[0] = a[0] - b[0];\n  out[1] = a[1] - b[1];\n  out[2] = a[2] - b[2];\n  out[3] = a[3] - b[3];\n  out[4] = a[4] - b[4];\n  out[5] = a[5] - b[5];\n  out[6] = a[6] - b[6];\n  out[7] = a[7] - b[7];\n  out[8] = a[8] - b[8];\n  out[9] = a[9] - b[9];\n  out[10] = a[10] - b[10];\n  out[11] = a[11] - b[11];\n  out[12] = a[12] - b[12];\n  out[13] = a[13] - b[13];\n  out[14] = a[14] - b[14];\n  out[15] = a[15] - b[15];\n  return out;\n}\n/**\r\n * Multiply each element of the matrix by a scalar.\r\n *\r\n * @param {mat4} out the receiving matrix\r\n * @param {ReadonlyMat4} a the matrix to scale\r\n * @param {Number} b amount to scale the matrix's elements by\r\n * @returns {mat4} out\r\n */\n\nexport function multiplyScalar(out, a, b) {\n  out[0] = a[0] * b;\n  out[1] = a[1] * b;\n  out[2] = a[2] * b;\n  out[3] = a[3] * b;\n  out[4] = a[4] * b;\n  out[5] = a[5] * b;\n  out[6] = a[6] * b;\n  out[7] = a[7] * b;\n  out[8] = a[8] * b;\n  out[9] = a[9] * b;\n  out[10] = a[10] * b;\n  out[11] = a[11] * b;\n  out[12] = a[12] * b;\n  out[13] = a[13] * b;\n  out[14] = a[14] * b;\n  out[15] = a[15] * b;\n  return out;\n}\n/**\r\n * Adds two mat4's after multiplying each element of the second operand by a scalar value.\r\n *\r\n * @param {mat4} out the receiving vector\r\n * @param {ReadonlyMat4} a the first operand\r\n * @param {ReadonlyMat4} b the second operand\r\n * @param {Number} scale the amount to scale b's elements by before adding\r\n * @returns {mat4} out\r\n */\n\nexport function multiplyScalarAndAdd(out, a, b, scale) {\n  out[0] = a[0] + b[0] * scale;\n  out[1] = a[1] + b[1] * scale;\n  out[2] = a[2] + b[2] * scale;\n  out[3] = a[3] + b[3] * scale;\n  out[4] = a[4] + b[4] * scale;\n  out[5] = a[5] + b[5] * scale;\n  out[6] = a[6] + b[6] * scale;\n  out[7] = a[7] + b[7] * scale;\n  out[8] = a[8] + b[8] * scale;\n  out[9] = a[9] + b[9] * scale;\n  out[10] = a[10] + b[10] * scale;\n  out[11] = a[11] + b[11] * scale;\n  out[12] = a[12] + b[12] * scale;\n  out[13] = a[13] + b[13] * scale;\n  out[14] = a[14] + b[14] * scale;\n  out[15] = a[15] + b[15] * scale;\n  return out;\n}\n/**\r\n * Returns whether or not the matrices have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {ReadonlyMat4} a The first matrix.\r\n * @param {ReadonlyMat4} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\n\nexport function exactEquals(a, b) {\n  return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];\n}\n/**\r\n * Returns whether or not the matrices have approximately the same elements in the same position.\r\n *\r\n * @param {ReadonlyMat4} a The first matrix.\r\n * @param {ReadonlyMat4} b The second matrix.\r\n * @returns {Boolean} True if the matrices are equal, false otherwise.\r\n */\n\nexport function equals(a, b) {\n  var a0 = a[0],\n      a1 = a[1],\n      a2 = a[2],\n      a3 = a[3];\n  var a4 = a[4],\n      a5 = a[5],\n      a6 = a[6],\n      a7 = a[7];\n  var a8 = a[8],\n      a9 = a[9],\n      a10 = a[10],\n      a11 = a[11];\n  var a12 = a[12],\n      a13 = a[13],\n      a14 = a[14],\n      a15 = a[15];\n  var b0 = b[0],\n      b1 = b[1],\n      b2 = b[2],\n      b3 = b[3];\n  var b4 = b[4],\n      b5 = b[5],\n      b6 = b[6],\n      b7 = b[7];\n  var b8 = b[8],\n      b9 = b[9],\n      b10 = b[10],\n      b11 = b[11];\n  var b12 = b[12],\n      b13 = b[13],\n      b14 = b[14],\n      b15 = b[15];\n  return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)) && Math.abs(a4 - b4) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a4), Math.abs(b4)) && Math.abs(a5 - b5) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a5), Math.abs(b5)) && Math.abs(a6 - b6) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a6), Math.abs(b6)) && Math.abs(a7 - b7) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a7), Math.abs(b7)) && Math.abs(a8 - b8) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a8), Math.abs(b8)) && Math.abs(a9 - b9) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a9), Math.abs(b9)) && Math.abs(a10 - b10) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a10), Math.abs(b10)) && Math.abs(a11 - b11) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a11), Math.abs(b11)) && Math.abs(a12 - b12) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a12), Math.abs(b12)) && Math.abs(a13 - b13) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a13), Math.abs(b13)) && Math.abs(a14 - b14) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a14), Math.abs(b14)) && Math.abs(a15 - b15) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a15), Math.abs(b15));\n}\n/**\r\n * Alias for {@link mat4.multiply}\r\n * @function\r\n */\n\nexport var mul = multiply;\n/**\r\n * Alias for {@link mat4.subtract}\r\n * @function\r\n */\n\nexport var sub = subtract;","import * as glMatrix from \"./common.js\";\n/**\r\n * 3 Dimensional Vector\r\n * @module vec3\r\n */\n\n/**\r\n * Creates a new, empty vec3\r\n *\r\n * @returns {vec3} a new 3D vector\r\n */\n\nexport function create() {\n  var out = new glMatrix.ARRAY_TYPE(3);\n\n  if (glMatrix.ARRAY_TYPE != Float32Array) {\n    out[0] = 0;\n    out[1] = 0;\n    out[2] = 0;\n  }\n\n  return out;\n}\n/**\r\n * Creates a new vec3 initialized with values from an existing vector\r\n *\r\n * @param {ReadonlyVec3} a vector to clone\r\n * @returns {vec3} a new 3D vector\r\n */\n\nexport function clone(a) {\n  var out = new glMatrix.ARRAY_TYPE(3);\n  out[0] = a[0];\n  out[1] = a[1];\n  out[2] = a[2];\n  return out;\n}\n/**\r\n * Calculates the length of a vec3\r\n *\r\n * @param {ReadonlyVec3} a vector to calculate length of\r\n * @returns {Number} length of a\r\n */\n\nexport function length(a) {\n  var x = a[0];\n  var y = a[1];\n  var z = a[2];\n  return Math.hypot(x, y, z);\n}\n/**\r\n * Creates a new vec3 initialized with the given values\r\n *\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @returns {vec3} a new 3D vector\r\n */\n\nexport function fromValues(x, y, z) {\n  var out = new glMatrix.ARRAY_TYPE(3);\n  out[0] = x;\n  out[1] = y;\n  out[2] = z;\n  return out;\n}\n/**\r\n * Copy the values from one vec3 to another\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the source vector\r\n * @returns {vec3} out\r\n */\n\nexport function copy(out, a) {\n  out[0] = a[0];\n  out[1] = a[1];\n  out[2] = a[2];\n  return out;\n}\n/**\r\n * Set the components of a vec3 to the given values\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @returns {vec3} out\r\n */\n\nexport function set(out, x, y, z) {\n  out[0] = x;\n  out[1] = y;\n  out[2] = z;\n  return out;\n}\n/**\r\n * Adds two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @returns {vec3} out\r\n */\n\nexport function add(out, a, b) {\n  out[0] = a[0] + b[0];\n  out[1] = a[1] + b[1];\n  out[2] = a[2] + b[2];\n  return out;\n}\n/**\r\n * Subtracts vector b from vector a\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @returns {vec3} out\r\n */\n\nexport function subtract(out, a, b) {\n  out[0] = a[0] - b[0];\n  out[1] = a[1] - b[1];\n  out[2] = a[2] - b[2];\n  return out;\n}\n/**\r\n * Multiplies two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @returns {vec3} out\r\n */\n\nexport function multiply(out, a, b) {\n  out[0] = a[0] * b[0];\n  out[1] = a[1] * b[1];\n  out[2] = a[2] * b[2];\n  return out;\n}\n/**\r\n * Divides two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @returns {vec3} out\r\n */\n\nexport function divide(out, a, b) {\n  out[0] = a[0] / b[0];\n  out[1] = a[1] / b[1];\n  out[2] = a[2] / b[2];\n  return out;\n}\n/**\r\n * Math.ceil the components of a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a vector to ceil\r\n * @returns {vec3} out\r\n */\n\nexport function ceil(out, a) {\n  out[0] = Math.ceil(a[0]);\n  out[1] = Math.ceil(a[1]);\n  out[2] = Math.ceil(a[2]);\n  return out;\n}\n/**\r\n * Math.floor the components of a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a vector to floor\r\n * @returns {vec3} out\r\n */\n\nexport function floor(out, a) {\n  out[0] = Math.floor(a[0]);\n  out[1] = Math.floor(a[1]);\n  out[2] = Math.floor(a[2]);\n  return out;\n}\n/**\r\n * Returns the minimum of two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @returns {vec3} out\r\n */\n\nexport function min(out, a, b) {\n  out[0] = Math.min(a[0], b[0]);\n  out[1] = Math.min(a[1], b[1]);\n  out[2] = Math.min(a[2], b[2]);\n  return out;\n}\n/**\r\n * Returns the maximum of two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @returns {vec3} out\r\n */\n\nexport function max(out, a, b) {\n  out[0] = Math.max(a[0], b[0]);\n  out[1] = Math.max(a[1], b[1]);\n  out[2] = Math.max(a[2], b[2]);\n  return out;\n}\n/**\r\n * Math.round the components of a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a vector to round\r\n * @returns {vec3} out\r\n */\n\nexport function round(out, a) {\n  out[0] = Math.round(a[0]);\n  out[1] = Math.round(a[1]);\n  out[2] = Math.round(a[2]);\n  return out;\n}\n/**\r\n * Scales a vec3 by a scalar number\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the vector to scale\r\n * @param {Number} b amount to scale the vector by\r\n * @returns {vec3} out\r\n */\n\nexport function scale(out, a, b) {\n  out[0] = a[0] * b;\n  out[1] = a[1] * b;\n  out[2] = a[2] * b;\n  return out;\n}\n/**\r\n * Adds two vec3's after scaling the second operand by a scalar value\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @param {Number} scale the amount to scale b by before adding\r\n * @returns {vec3} out\r\n */\n\nexport function scaleAndAdd(out, a, b, scale) {\n  out[0] = a[0] + b[0] * scale;\n  out[1] = a[1] + b[1] * scale;\n  out[2] = a[2] + b[2] * scale;\n  return out;\n}\n/**\r\n * Calculates the euclidian distance between two vec3's\r\n *\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @returns {Number} distance between a and b\r\n */\n\nexport function distance(a, b) {\n  var x = b[0] - a[0];\n  var y = b[1] - a[1];\n  var z = b[2] - a[2];\n  return Math.hypot(x, y, z);\n}\n/**\r\n * Calculates the squared euclidian distance between two vec3's\r\n *\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @returns {Number} squared distance between a and b\r\n */\n\nexport function squaredDistance(a, b) {\n  var x = b[0] - a[0];\n  var y = b[1] - a[1];\n  var z = b[2] - a[2];\n  return x * x + y * y + z * z;\n}\n/**\r\n * Calculates the squared length of a vec3\r\n *\r\n * @param {ReadonlyVec3} a vector to calculate squared length of\r\n * @returns {Number} squared length of a\r\n */\n\nexport function squaredLength(a) {\n  var x = a[0];\n  var y = a[1];\n  var z = a[2];\n  return x * x + y * y + z * z;\n}\n/**\r\n * Negates the components of a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a vector to negate\r\n * @returns {vec3} out\r\n */\n\nexport function negate(out, a) {\n  out[0] = -a[0];\n  out[1] = -a[1];\n  out[2] = -a[2];\n  return out;\n}\n/**\r\n * Returns the inverse of the components of a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a vector to invert\r\n * @returns {vec3} out\r\n */\n\nexport function inverse(out, a) {\n  out[0] = 1.0 / a[0];\n  out[1] = 1.0 / a[1];\n  out[2] = 1.0 / a[2];\n  return out;\n}\n/**\r\n * Normalize a vec3\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a vector to normalize\r\n * @returns {vec3} out\r\n */\n\nexport function normalize(out, a) {\n  var x = a[0];\n  var y = a[1];\n  var z = a[2];\n  var len = x * x + y * y + z * z;\n\n  if (len > 0) {\n    //TODO: evaluate use of glm_invsqrt here?\n    len = 1 / Math.sqrt(len);\n  }\n\n  out[0] = a[0] * len;\n  out[1] = a[1] * len;\n  out[2] = a[2] * len;\n  return out;\n}\n/**\r\n * Calculates the dot product of two vec3's\r\n *\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @returns {Number} dot product of a and b\r\n */\n\nexport function dot(a, b) {\n  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n}\n/**\r\n * Computes the cross product of two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @returns {vec3} out\r\n */\n\nexport function cross(out, a, b) {\n  var ax = a[0],\n      ay = a[1],\n      az = a[2];\n  var bx = b[0],\n      by = b[1],\n      bz = b[2];\n  out[0] = ay * bz - az * by;\n  out[1] = az * bx - ax * bz;\n  out[2] = ax * by - ay * bx;\n  return out;\n}\n/**\r\n * Performs a linear interpolation between two vec3's\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {vec3} out\r\n */\n\nexport function lerp(out, a, b, t) {\n  var ax = a[0];\n  var ay = a[1];\n  var az = a[2];\n  out[0] = ax + t * (b[0] - ax);\n  out[1] = ay + t * (b[1] - ay);\n  out[2] = az + t * (b[2] - az);\n  return out;\n}\n/**\r\n * Performs a hermite interpolation with two control points\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @param {ReadonlyVec3} c the third operand\r\n * @param {ReadonlyVec3} d the fourth operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {vec3} out\r\n */\n\nexport function hermite(out, a, b, c, d, t) {\n  var factorTimes2 = t * t;\n  var factor1 = factorTimes2 * (2 * t - 3) + 1;\n  var factor2 = factorTimes2 * (t - 2) + t;\n  var factor3 = factorTimes2 * (t - 1);\n  var factor4 = factorTimes2 * (3 - 2 * t);\n  out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n  out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n  out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n  return out;\n}\n/**\r\n * Performs a bezier interpolation with two control points\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the first operand\r\n * @param {ReadonlyVec3} b the second operand\r\n * @param {ReadonlyVec3} c the third operand\r\n * @param {ReadonlyVec3} d the fourth operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {vec3} out\r\n */\n\nexport function bezier(out, a, b, c, d, t) {\n  var inverseFactor = 1 - t;\n  var inverseFactorTimesTwo = inverseFactor * inverseFactor;\n  var factorTimes2 = t * t;\n  var factor1 = inverseFactorTimesTwo * inverseFactor;\n  var factor2 = 3 * t * inverseFactorTimesTwo;\n  var factor3 = 3 * factorTimes2 * inverseFactor;\n  var factor4 = factorTimes2 * t;\n  out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n  out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n  out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n  return out;\n}\n/**\r\n * Generates a random vector with the given scale\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned\r\n * @returns {vec3} out\r\n */\n\nexport function random(out, scale) {\n  scale = scale || 1.0;\n  var r = glMatrix.RANDOM() * 2.0 * Math.PI;\n  var z = glMatrix.RANDOM() * 2.0 - 1.0;\n  var zScale = Math.sqrt(1.0 - z * z) * scale;\n  out[0] = Math.cos(r) * zScale;\n  out[1] = Math.sin(r) * zScale;\n  out[2] = z * scale;\n  return out;\n}\n/**\r\n * Transforms the vec3 with a mat4.\r\n * 4th vector component is implicitly '1'\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the vector to transform\r\n * @param {ReadonlyMat4} m matrix to transform with\r\n * @returns {vec3} out\r\n */\n\nexport function transformMat4(out, a, m) {\n  var x = a[0],\n      y = a[1],\n      z = a[2];\n  var w = m[3] * x + m[7] * y + m[11] * z + m[15];\n  w = w || 1.0;\n  out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;\n  out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;\n  out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;\n  return out;\n}\n/**\r\n * Transforms the vec3 with a mat3.\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the vector to transform\r\n * @param {ReadonlyMat3} m the 3x3 matrix to transform with\r\n * @returns {vec3} out\r\n */\n\nexport function transformMat3(out, a, m) {\n  var x = a[0],\n      y = a[1],\n      z = a[2];\n  out[0] = x * m[0] + y * m[3] + z * m[6];\n  out[1] = x * m[1] + y * m[4] + z * m[7];\n  out[2] = x * m[2] + y * m[5] + z * m[8];\n  return out;\n}\n/**\r\n * Transforms the vec3 with a quat\r\n * Can also be used for dual quaternions. (Multiply it with the real part)\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @param {ReadonlyVec3} a the vector to transform\r\n * @param {ReadonlyQuat} q quaternion to transform with\r\n * @returns {vec3} out\r\n */\n\nexport function transformQuat(out, a, q) {\n  // benchmarks: https://jsperf.com/quaternion-transform-vec3-implementations-fixed\n  var qx = q[0],\n      qy = q[1],\n      qz = q[2],\n      qw = q[3];\n  var x = a[0],\n      y = a[1],\n      z = a[2]; // var qvec = [qx, qy, qz];\n  // var uv = vec3.cross([], qvec, a);\n\n  var uvx = qy * z - qz * y,\n      uvy = qz * x - qx * z,\n      uvz = qx * y - qy * x; // var uuv = vec3.cross([], qvec, uv);\n\n  var uuvx = qy * uvz - qz * uvy,\n      uuvy = qz * uvx - qx * uvz,\n      uuvz = qx * uvy - qy * uvx; // vec3.scale(uv, uv, 2 * w);\n\n  var w2 = qw * 2;\n  uvx *= w2;\n  uvy *= w2;\n  uvz *= w2; // vec3.scale(uuv, uuv, 2);\n\n  uuvx *= 2;\n  uuvy *= 2;\n  uuvz *= 2; // return vec3.add(out, a, vec3.add(out, uv, uuv));\n\n  out[0] = x + uvx + uuvx;\n  out[1] = y + uvy + uuvy;\n  out[2] = z + uvz + uuvz;\n  return out;\n}\n/**\r\n * Rotate a 3D vector around the x-axis\r\n * @param {vec3} out The receiving vec3\r\n * @param {ReadonlyVec3} a The vec3 point to rotate\r\n * @param {ReadonlyVec3} b The origin of the rotation\r\n * @param {Number} rad The angle of rotation in radians\r\n * @returns {vec3} out\r\n */\n\nexport function rotateX(out, a, b, rad) {\n  var p = [],\n      r = []; //Translate point to the origin\n\n  p[0] = a[0] - b[0];\n  p[1] = a[1] - b[1];\n  p[2] = a[2] - b[2]; //perform rotation\n\n  r[0] = p[0];\n  r[1] = p[1] * Math.cos(rad) - p[2] * Math.sin(rad);\n  r[2] = p[1] * Math.sin(rad) + p[2] * Math.cos(rad); //translate to correct position\n\n  out[0] = r[0] + b[0];\n  out[1] = r[1] + b[1];\n  out[2] = r[2] + b[2];\n  return out;\n}\n/**\r\n * Rotate a 3D vector around the y-axis\r\n * @param {vec3} out The receiving vec3\r\n * @param {ReadonlyVec3} a The vec3 point to rotate\r\n * @param {ReadonlyVec3} b The origin of the rotation\r\n * @param {Number} rad The angle of rotation in radians\r\n * @returns {vec3} out\r\n */\n\nexport function rotateY(out, a, b, rad) {\n  var p = [],\n      r = []; //Translate point to the origin\n\n  p[0] = a[0] - b[0];\n  p[1] = a[1] - b[1];\n  p[2] = a[2] - b[2]; //perform rotation\n\n  r[0] = p[2] * Math.sin(rad) + p[0] * Math.cos(rad);\n  r[1] = p[1];\n  r[2] = p[2] * Math.cos(rad) - p[0] * Math.sin(rad); //translate to correct position\n\n  out[0] = r[0] + b[0];\n  out[1] = r[1] + b[1];\n  out[2] = r[2] + b[2];\n  return out;\n}\n/**\r\n * Rotate a 3D vector around the z-axis\r\n * @param {vec3} out The receiving vec3\r\n * @param {ReadonlyVec3} a The vec3 point to rotate\r\n * @param {ReadonlyVec3} b The origin of the rotation\r\n * @param {Number} rad The angle of rotation in radians\r\n * @returns {vec3} out\r\n */\n\nexport function rotateZ(out, a, b, rad) {\n  var p = [],\n      r = []; //Translate point to the origin\n\n  p[0] = a[0] - b[0];\n  p[1] = a[1] - b[1];\n  p[2] = a[2] - b[2]; //perform rotation\n\n  r[0] = p[0] * Math.cos(rad) - p[1] * Math.sin(rad);\n  r[1] = p[0] * Math.sin(rad) + p[1] * Math.cos(rad);\n  r[2] = p[2]; //translate to correct position\n\n  out[0] = r[0] + b[0];\n  out[1] = r[1] + b[1];\n  out[2] = r[2] + b[2];\n  return out;\n}\n/**\r\n * Get the angle between two 3D vectors\r\n * @param {ReadonlyVec3} a The first operand\r\n * @param {ReadonlyVec3} b The second operand\r\n * @returns {Number} The angle in radians\r\n */\n\nexport function angle(a, b) {\n  var ax = a[0],\n      ay = a[1],\n      az = a[2],\n      bx = b[0],\n      by = b[1],\n      bz = b[2],\n      mag1 = Math.sqrt(ax * ax + ay * ay + az * az),\n      mag2 = Math.sqrt(bx * bx + by * by + bz * bz),\n      mag = mag1 * mag2,\n      cosine = mag && dot(a, b) / mag;\n  return Math.acos(Math.min(Math.max(cosine, -1), 1));\n}\n/**\r\n * Set the components of a vec3 to zero\r\n *\r\n * @param {vec3} out the receiving vector\r\n * @returns {vec3} out\r\n */\n\nexport function zero(out) {\n  out[0] = 0.0;\n  out[1] = 0.0;\n  out[2] = 0.0;\n  return out;\n}\n/**\r\n * Returns a string representation of a vector\r\n *\r\n * @param {ReadonlyVec3} a vector to represent as a string\r\n * @returns {String} string representation of the vector\r\n */\n\nexport function str(a) {\n  return \"vec3(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \")\";\n}\n/**\r\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {ReadonlyVec3} a The first vector.\r\n * @param {ReadonlyVec3} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\n\nexport function exactEquals(a, b) {\n  return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];\n}\n/**\r\n * Returns whether or not the vectors have approximately the same elements in the same position.\r\n *\r\n * @param {ReadonlyVec3} a The first vector.\r\n * @param {ReadonlyVec3} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\n\nexport function equals(a, b) {\n  var a0 = a[0],\n      a1 = a[1],\n      a2 = a[2];\n  var b0 = b[0],\n      b1 = b[1],\n      b2 = b[2];\n  return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2));\n}\n/**\r\n * Alias for {@link vec3.subtract}\r\n * @function\r\n */\n\nexport var sub = subtract;\n/**\r\n * Alias for {@link vec3.multiply}\r\n * @function\r\n */\n\nexport var mul = multiply;\n/**\r\n * Alias for {@link vec3.divide}\r\n * @function\r\n */\n\nexport var div = divide;\n/**\r\n * Alias for {@link vec3.distance}\r\n * @function\r\n */\n\nexport var dist = distance;\n/**\r\n * Alias for {@link vec3.squaredDistance}\r\n * @function\r\n */\n\nexport var sqrDist = squaredDistance;\n/**\r\n * Alias for {@link vec3.length}\r\n * @function\r\n */\n\nexport var len = length;\n/**\r\n * Alias for {@link vec3.squaredLength}\r\n * @function\r\n */\n\nexport var sqrLen = squaredLength;\n/**\r\n * Perform some operation over an array of vec3s.\r\n *\r\n * @param {Array} a the array of vectors to iterate over\r\n * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed\r\n * @param {Number} offset Number of elements to skip at the beginning of the array\r\n * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array\r\n * @param {Function} fn Function to call for each vector in the array\r\n * @param {Object} [arg] additional argument to pass to fn\r\n * @returns {Array} a\r\n * @function\r\n */\n\nexport var forEach = function () {\n  var vec = create();\n  return function (a, stride, offset, count, fn, arg) {\n    var i, l;\n\n    if (!stride) {\n      stride = 3;\n    }\n\n    if (!offset) {\n      offset = 0;\n    }\n\n    if (count) {\n      l = Math.min(count * stride + offset, a.length);\n    } else {\n      l = a.length;\n    }\n\n    for (i = offset; i < l; i += stride) {\n      vec[0] = a[i];\n      vec[1] = a[i + 1];\n      vec[2] = a[i + 2];\n      fn(vec, vec, arg);\n      a[i] = vec[0];\n      a[i + 1] = vec[1];\n      a[i + 2] = vec[2];\n    }\n\n    return a;\n  };\n}();","import * as glMatrix from \"./common.js\";\n/**\r\n * 4 Dimensional Vector\r\n * @module vec4\r\n */\n\n/**\r\n * Creates a new, empty vec4\r\n *\r\n * @returns {vec4} a new 4D vector\r\n */\n\nexport function create() {\n  var out = new glMatrix.ARRAY_TYPE(4);\n\n  if (glMatrix.ARRAY_TYPE != Float32Array) {\n    out[0] = 0;\n    out[1] = 0;\n    out[2] = 0;\n    out[3] = 0;\n  }\n\n  return out;\n}\n/**\r\n * Creates a new vec4 initialized with values from an existing vector\r\n *\r\n * @param {ReadonlyVec4} a vector to clone\r\n * @returns {vec4} a new 4D vector\r\n */\n\nexport function clone(a) {\n  var out = new glMatrix.ARRAY_TYPE(4);\n  out[0] = a[0];\n  out[1] = a[1];\n  out[2] = a[2];\n  out[3] = a[3];\n  return out;\n}\n/**\r\n * Creates a new vec4 initialized with the given values\r\n *\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @param {Number} w W component\r\n * @returns {vec4} a new 4D vector\r\n */\n\nexport function fromValues(x, y, z, w) {\n  var out = new glMatrix.ARRAY_TYPE(4);\n  out[0] = x;\n  out[1] = y;\n  out[2] = z;\n  out[3] = w;\n  return out;\n}\n/**\r\n * Copy the values from one vec4 to another\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the source vector\r\n * @returns {vec4} out\r\n */\n\nexport function copy(out, a) {\n  out[0] = a[0];\n  out[1] = a[1];\n  out[2] = a[2];\n  out[3] = a[3];\n  return out;\n}\n/**\r\n * Set the components of a vec4 to the given values\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @param {Number} w W component\r\n * @returns {vec4} out\r\n */\n\nexport function set(out, x, y, z, w) {\n  out[0] = x;\n  out[1] = y;\n  out[2] = z;\n  out[3] = w;\n  return out;\n}\n/**\r\n * Adds two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @returns {vec4} out\r\n */\n\nexport function add(out, a, b) {\n  out[0] = a[0] + b[0];\n  out[1] = a[1] + b[1];\n  out[2] = a[2] + b[2];\n  out[3] = a[3] + b[3];\n  return out;\n}\n/**\r\n * Subtracts vector b from vector a\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @returns {vec4} out\r\n */\n\nexport function subtract(out, a, b) {\n  out[0] = a[0] - b[0];\n  out[1] = a[1] - b[1];\n  out[2] = a[2] - b[2];\n  out[3] = a[3] - b[3];\n  return out;\n}\n/**\r\n * Multiplies two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @returns {vec4} out\r\n */\n\nexport function multiply(out, a, b) {\n  out[0] = a[0] * b[0];\n  out[1] = a[1] * b[1];\n  out[2] = a[2] * b[2];\n  out[3] = a[3] * b[3];\n  return out;\n}\n/**\r\n * Divides two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @returns {vec4} out\r\n */\n\nexport function divide(out, a, b) {\n  out[0] = a[0] / b[0];\n  out[1] = a[1] / b[1];\n  out[2] = a[2] / b[2];\n  out[3] = a[3] / b[3];\n  return out;\n}\n/**\r\n * Math.ceil the components of a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a vector to ceil\r\n * @returns {vec4} out\r\n */\n\nexport function ceil(out, a) {\n  out[0] = Math.ceil(a[0]);\n  out[1] = Math.ceil(a[1]);\n  out[2] = Math.ceil(a[2]);\n  out[3] = Math.ceil(a[3]);\n  return out;\n}\n/**\r\n * Math.floor the components of a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a vector to floor\r\n * @returns {vec4} out\r\n */\n\nexport function floor(out, a) {\n  out[0] = Math.floor(a[0]);\n  out[1] = Math.floor(a[1]);\n  out[2] = Math.floor(a[2]);\n  out[3] = Math.floor(a[3]);\n  return out;\n}\n/**\r\n * Returns the minimum of two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @returns {vec4} out\r\n */\n\nexport function min(out, a, b) {\n  out[0] = Math.min(a[0], b[0]);\n  out[1] = Math.min(a[1], b[1]);\n  out[2] = Math.min(a[2], b[2]);\n  out[3] = Math.min(a[3], b[3]);\n  return out;\n}\n/**\r\n * Returns the maximum of two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @returns {vec4} out\r\n */\n\nexport function max(out, a, b) {\n  out[0] = Math.max(a[0], b[0]);\n  out[1] = Math.max(a[1], b[1]);\n  out[2] = Math.max(a[2], b[2]);\n  out[3] = Math.max(a[3], b[3]);\n  return out;\n}\n/**\r\n * Math.round the components of a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a vector to round\r\n * @returns {vec4} out\r\n */\n\nexport function round(out, a) {\n  out[0] = Math.round(a[0]);\n  out[1] = Math.round(a[1]);\n  out[2] = Math.round(a[2]);\n  out[3] = Math.round(a[3]);\n  return out;\n}\n/**\r\n * Scales a vec4 by a scalar number\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the vector to scale\r\n * @param {Number} b amount to scale the vector by\r\n * @returns {vec4} out\r\n */\n\nexport function scale(out, a, b) {\n  out[0] = a[0] * b;\n  out[1] = a[1] * b;\n  out[2] = a[2] * b;\n  out[3] = a[3] * b;\n  return out;\n}\n/**\r\n * Adds two vec4's after scaling the second operand by a scalar value\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @param {Number} scale the amount to scale b by before adding\r\n * @returns {vec4} out\r\n */\n\nexport function scaleAndAdd(out, a, b, scale) {\n  out[0] = a[0] + b[0] * scale;\n  out[1] = a[1] + b[1] * scale;\n  out[2] = a[2] + b[2] * scale;\n  out[3] = a[3] + b[3] * scale;\n  return out;\n}\n/**\r\n * Calculates the euclidian distance between two vec4's\r\n *\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @returns {Number} distance between a and b\r\n */\n\nexport function distance(a, b) {\n  var x = b[0] - a[0];\n  var y = b[1] - a[1];\n  var z = b[2] - a[2];\n  var w = b[3] - a[3];\n  return Math.hypot(x, y, z, w);\n}\n/**\r\n * Calculates the squared euclidian distance between two vec4's\r\n *\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @returns {Number} squared distance between a and b\r\n */\n\nexport function squaredDistance(a, b) {\n  var x = b[0] - a[0];\n  var y = b[1] - a[1];\n  var z = b[2] - a[2];\n  var w = b[3] - a[3];\n  return x * x + y * y + z * z + w * w;\n}\n/**\r\n * Calculates the length of a vec4\r\n *\r\n * @param {ReadonlyVec4} a vector to calculate length of\r\n * @returns {Number} length of a\r\n */\n\nexport function length(a) {\n  var x = a[0];\n  var y = a[1];\n  var z = a[2];\n  var w = a[3];\n  return Math.hypot(x, y, z, w);\n}\n/**\r\n * Calculates the squared length of a vec4\r\n *\r\n * @param {ReadonlyVec4} a vector to calculate squared length of\r\n * @returns {Number} squared length of a\r\n */\n\nexport function squaredLength(a) {\n  var x = a[0];\n  var y = a[1];\n  var z = a[2];\n  var w = a[3];\n  return x * x + y * y + z * z + w * w;\n}\n/**\r\n * Negates the components of a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a vector to negate\r\n * @returns {vec4} out\r\n */\n\nexport function negate(out, a) {\n  out[0] = -a[0];\n  out[1] = -a[1];\n  out[2] = -a[2];\n  out[3] = -a[3];\n  return out;\n}\n/**\r\n * Returns the inverse of the components of a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a vector to invert\r\n * @returns {vec4} out\r\n */\n\nexport function inverse(out, a) {\n  out[0] = 1.0 / a[0];\n  out[1] = 1.0 / a[1];\n  out[2] = 1.0 / a[2];\n  out[3] = 1.0 / a[3];\n  return out;\n}\n/**\r\n * Normalize a vec4\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a vector to normalize\r\n * @returns {vec4} out\r\n */\n\nexport function normalize(out, a) {\n  var x = a[0];\n  var y = a[1];\n  var z = a[2];\n  var w = a[3];\n  var len = x * x + y * y + z * z + w * w;\n\n  if (len > 0) {\n    len = 1 / Math.sqrt(len);\n  }\n\n  out[0] = x * len;\n  out[1] = y * len;\n  out[2] = z * len;\n  out[3] = w * len;\n  return out;\n}\n/**\r\n * Calculates the dot product of two vec4's\r\n *\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @returns {Number} dot product of a and b\r\n */\n\nexport function dot(a, b) {\n  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];\n}\n/**\r\n * Returns the cross-product of three vectors in a 4-dimensional space\r\n *\r\n * @param {ReadonlyVec4} result the receiving vector\r\n * @param {ReadonlyVec4} U the first vector\r\n * @param {ReadonlyVec4} V the second vector\r\n * @param {ReadonlyVec4} W the third vector\r\n * @returns {vec4} result\r\n */\n\nexport function cross(out, u, v, w) {\n  var A = v[0] * w[1] - v[1] * w[0],\n      B = v[0] * w[2] - v[2] * w[0],\n      C = v[0] * w[3] - v[3] * w[0],\n      D = v[1] * w[2] - v[2] * w[1],\n      E = v[1] * w[3] - v[3] * w[1],\n      F = v[2] * w[3] - v[3] * w[2];\n  var G = u[0];\n  var H = u[1];\n  var I = u[2];\n  var J = u[3];\n  out[0] = H * F - I * E + J * D;\n  out[1] = -(G * F) + I * C - J * B;\n  out[2] = G * E - H * C + J * A;\n  out[3] = -(G * D) + H * B - I * A;\n  return out;\n}\n/**\r\n * Performs a linear interpolation between two vec4's\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the first operand\r\n * @param {ReadonlyVec4} b the second operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {vec4} out\r\n */\n\nexport function lerp(out, a, b, t) {\n  var ax = a[0];\n  var ay = a[1];\n  var az = a[2];\n  var aw = a[3];\n  out[0] = ax + t * (b[0] - ax);\n  out[1] = ay + t * (b[1] - ay);\n  out[2] = az + t * (b[2] - az);\n  out[3] = aw + t * (b[3] - aw);\n  return out;\n}\n/**\r\n * Generates a random vector with the given scale\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {Number} [scale] Length of the resulting vector. If ommitted, a unit vector will be returned\r\n * @returns {vec4} out\r\n */\n\nexport function random(out, scale) {\n  scale = scale || 1.0; // Marsaglia, George. Choosing a Point from the Surface of a\n  // Sphere. Ann. Math. Statist. 43 (1972), no. 2, 645--646.\n  // http://projecteuclid.org/euclid.aoms/1177692644;\n\n  var v1, v2, v3, v4;\n  var s1, s2;\n\n  do {\n    v1 = glMatrix.RANDOM() * 2 - 1;\n    v2 = glMatrix.RANDOM() * 2 - 1;\n    s1 = v1 * v1 + v2 * v2;\n  } while (s1 >= 1);\n\n  do {\n    v3 = glMatrix.RANDOM() * 2 - 1;\n    v4 = glMatrix.RANDOM() * 2 - 1;\n    s2 = v3 * v3 + v4 * v4;\n  } while (s2 >= 1);\n\n  var d = Math.sqrt((1 - s1) / s2);\n  out[0] = scale * v1;\n  out[1] = scale * v2;\n  out[2] = scale * v3 * d;\n  out[3] = scale * v4 * d;\n  return out;\n}\n/**\r\n * Transforms the vec4 with a mat4.\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the vector to transform\r\n * @param {ReadonlyMat4} m matrix to transform with\r\n * @returns {vec4} out\r\n */\n\nexport function transformMat4(out, a, m) {\n  var x = a[0],\n      y = a[1],\n      z = a[2],\n      w = a[3];\n  out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;\n  out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;\n  out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;\n  out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;\n  return out;\n}\n/**\r\n * Transforms the vec4 with a quat\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @param {ReadonlyVec4} a the vector to transform\r\n * @param {ReadonlyQuat} q quaternion to transform with\r\n * @returns {vec4} out\r\n */\n\nexport function transformQuat(out, a, q) {\n  var x = a[0],\n      y = a[1],\n      z = a[2];\n  var qx = q[0],\n      qy = q[1],\n      qz = q[2],\n      qw = q[3]; // calculate quat * vec\n\n  var ix = qw * x + qy * z - qz * y;\n  var iy = qw * y + qz * x - qx * z;\n  var iz = qw * z + qx * y - qy * x;\n  var iw = -qx * x - qy * y - qz * z; // calculate result * inverse quat\n\n  out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;\n  out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;\n  out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;\n  out[3] = a[3];\n  return out;\n}\n/**\r\n * Set the components of a vec4 to zero\r\n *\r\n * @param {vec4} out the receiving vector\r\n * @returns {vec4} out\r\n */\n\nexport function zero(out) {\n  out[0] = 0.0;\n  out[1] = 0.0;\n  out[2] = 0.0;\n  out[3] = 0.0;\n  return out;\n}\n/**\r\n * Returns a string representation of a vector\r\n *\r\n * @param {ReadonlyVec4} a vector to represent as a string\r\n * @returns {String} string representation of the vector\r\n */\n\nexport function str(a) {\n  return \"vec4(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \")\";\n}\n/**\r\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {ReadonlyVec4} a The first vector.\r\n * @param {ReadonlyVec4} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\n\nexport function exactEquals(a, b) {\n  return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];\n}\n/**\r\n * Returns whether or not the vectors have approximately the same elements in the same position.\r\n *\r\n * @param {ReadonlyVec4} a The first vector.\r\n * @param {ReadonlyVec4} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\n\nexport function equals(a, b) {\n  var a0 = a[0],\n      a1 = a[1],\n      a2 = a[2],\n      a3 = a[3];\n  var b0 = b[0],\n      b1 = b[1],\n      b2 = b[2],\n      b3 = b[3];\n  return Math.abs(a0 - b0) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) && Math.abs(a1 - b1) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) && Math.abs(a2 - b2) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) && Math.abs(a3 - b3) <= glMatrix.EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3));\n}\n/**\r\n * Alias for {@link vec4.subtract}\r\n * @function\r\n */\n\nexport var sub = subtract;\n/**\r\n * Alias for {@link vec4.multiply}\r\n * @function\r\n */\n\nexport var mul = multiply;\n/**\r\n * Alias for {@link vec4.divide}\r\n * @function\r\n */\n\nexport var div = divide;\n/**\r\n * Alias for {@link vec4.distance}\r\n * @function\r\n */\n\nexport var dist = distance;\n/**\r\n * Alias for {@link vec4.squaredDistance}\r\n * @function\r\n */\n\nexport var sqrDist = squaredDistance;\n/**\r\n * Alias for {@link vec4.length}\r\n * @function\r\n */\n\nexport var len = length;\n/**\r\n * Alias for {@link vec4.squaredLength}\r\n * @function\r\n */\n\nexport var sqrLen = squaredLength;\n/**\r\n * Perform some operation over an array of vec4s.\r\n *\r\n * @param {Array} a the array of vectors to iterate over\r\n * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed\r\n * @param {Number} offset Number of elements to skip at the beginning of the array\r\n * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array\r\n * @param {Function} fn Function to call for each vector in the array\r\n * @param {Object} [arg] additional argument to pass to fn\r\n * @returns {Array} a\r\n * @function\r\n */\n\nexport var forEach = function () {\n  var vec = create();\n  return function (a, stride, offset, count, fn, arg) {\n    var i, l;\n\n    if (!stride) {\n      stride = 4;\n    }\n\n    if (!offset) {\n      offset = 0;\n    }\n\n    if (count) {\n      l = Math.min(count * stride + offset, a.length);\n    } else {\n      l = a.length;\n    }\n\n    for (i = offset; i < l; i += stride) {\n      vec[0] = a[i];\n      vec[1] = a[i + 1];\n      vec[2] = a[i + 2];\n      vec[3] = a[i + 3];\n      fn(vec, vec, arg);\n      a[i] = vec[0];\n      a[i + 1] = vec[1];\n      a[i + 2] = vec[2];\n      a[i + 3] = vec[3];\n    }\n\n    return a;\n  };\n}();","import * as glMatrix from \"./common.js\";\nimport * as mat3 from \"./mat3.js\";\nimport * as vec3 from \"./vec3.js\";\nimport * as vec4 from \"./vec4.js\";\n/**\r\n * Quaternion\r\n * @module quat\r\n */\n\n/**\r\n * Creates a new identity quat\r\n *\r\n * @returns {quat} a new quaternion\r\n */\n\nexport function create() {\n  var out = new glMatrix.ARRAY_TYPE(4);\n\n  if (glMatrix.ARRAY_TYPE != Float32Array) {\n    out[0] = 0;\n    out[1] = 0;\n    out[2] = 0;\n  }\n\n  out[3] = 1;\n  return out;\n}\n/**\r\n * Set a quat to the identity quaternion\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @returns {quat} out\r\n */\n\nexport function identity(out) {\n  out[0] = 0;\n  out[1] = 0;\n  out[2] = 0;\n  out[3] = 1;\n  return out;\n}\n/**\r\n * Sets a quat from the given angle and rotation axis,\r\n * then returns it.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyVec3} axis the axis around which to rotate\r\n * @param {Number} rad the angle in radians\r\n * @returns {quat} out\r\n **/\n\nexport function setAxisAngle(out, axis, rad) {\n  rad = rad * 0.5;\n  var s = Math.sin(rad);\n  out[0] = s * axis[0];\n  out[1] = s * axis[1];\n  out[2] = s * axis[2];\n  out[3] = Math.cos(rad);\n  return out;\n}\n/**\r\n * Gets the rotation axis and angle for a given\r\n *  quaternion. If a quaternion is created with\r\n *  setAxisAngle, this method will return the same\r\n *  values as providied in the original parameter list\r\n *  OR functionally equivalent values.\r\n * Example: The quaternion formed by axis [0, 0, 1] and\r\n *  angle -90 is the same as the quaternion formed by\r\n *  [0, 0, 1] and 270. This method favors the latter.\r\n * @param  {vec3} out_axis  Vector receiving the axis of rotation\r\n * @param  {ReadonlyQuat} q     Quaternion to be decomposed\r\n * @return {Number}     Angle, in radians, of the rotation\r\n */\n\nexport function getAxisAngle(out_axis, q) {\n  var rad = Math.acos(q[3]) * 2.0;\n  var s = Math.sin(rad / 2.0);\n\n  if (s > glMatrix.EPSILON) {\n    out_axis[0] = q[0] / s;\n    out_axis[1] = q[1] / s;\n    out_axis[2] = q[2] / s;\n  } else {\n    // If s is zero, return any axis (no rotation - axis does not matter)\n    out_axis[0] = 1;\n    out_axis[1] = 0;\n    out_axis[2] = 0;\n  }\n\n  return rad;\n}\n/**\r\n * Gets the angular distance between two unit quaternions\r\n *\r\n * @param  {ReadonlyQuat} a     Origin unit quaternion\r\n * @param  {ReadonlyQuat} b     Destination unit quaternion\r\n * @return {Number}     Angle, in radians, between the two quaternions\r\n */\n\nexport function getAngle(a, b) {\n  var dotproduct = dot(a, b);\n  return Math.acos(2 * dotproduct * dotproduct - 1);\n}\n/**\r\n * Multiplies two quat's\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a the first operand\r\n * @param {ReadonlyQuat} b the second operand\r\n * @returns {quat} out\r\n */\n\nexport function multiply(out, a, b) {\n  var ax = a[0],\n      ay = a[1],\n      az = a[2],\n      aw = a[3];\n  var bx = b[0],\n      by = b[1],\n      bz = b[2],\n      bw = b[3];\n  out[0] = ax * bw + aw * bx + ay * bz - az * by;\n  out[1] = ay * bw + aw * by + az * bx - ax * bz;\n  out[2] = az * bw + aw * bz + ax * by - ay * bx;\n  out[3] = aw * bw - ax * bx - ay * by - az * bz;\n  return out;\n}\n/**\r\n * Rotates a quaternion by the given angle about the X axis\r\n *\r\n * @param {quat} out quat receiving operation result\r\n * @param {ReadonlyQuat} a quat to rotate\r\n * @param {number} rad angle (in radians) to rotate\r\n * @returns {quat} out\r\n */\n\nexport function rotateX(out, a, rad) {\n  rad *= 0.5;\n  var ax = a[0],\n      ay = a[1],\n      az = a[2],\n      aw = a[3];\n  var bx = Math.sin(rad),\n      bw = Math.cos(rad);\n  out[0] = ax * bw + aw * bx;\n  out[1] = ay * bw + az * bx;\n  out[2] = az * bw - ay * bx;\n  out[3] = aw * bw - ax * bx;\n  return out;\n}\n/**\r\n * Rotates a quaternion by the given angle about the Y axis\r\n *\r\n * @param {quat} out quat receiving operation result\r\n * @param {ReadonlyQuat} a quat to rotate\r\n * @param {number} rad angle (in radians) to rotate\r\n * @returns {quat} out\r\n */\n\nexport function rotateY(out, a, rad) {\n  rad *= 0.5;\n  var ax = a[0],\n      ay = a[1],\n      az = a[2],\n      aw = a[3];\n  var by = Math.sin(rad),\n      bw = Math.cos(rad);\n  out[0] = ax * bw - az * by;\n  out[1] = ay * bw + aw * by;\n  out[2] = az * bw + ax * by;\n  out[3] = aw * bw - ay * by;\n  return out;\n}\n/**\r\n * Rotates a quaternion by the given angle about the Z axis\r\n *\r\n * @param {quat} out quat receiving operation result\r\n * @param {ReadonlyQuat} a quat to rotate\r\n * @param {number} rad angle (in radians) to rotate\r\n * @returns {quat} out\r\n */\n\nexport function rotateZ(out, a, rad) {\n  rad *= 0.5;\n  var ax = a[0],\n      ay = a[1],\n      az = a[2],\n      aw = a[3];\n  var bz = Math.sin(rad),\n      bw = Math.cos(rad);\n  out[0] = ax * bw + ay * bz;\n  out[1] = ay * bw - ax * bz;\n  out[2] = az * bw + aw * bz;\n  out[3] = aw * bw - az * bz;\n  return out;\n}\n/**\r\n * Calculates the W component of a quat from the X, Y, and Z components.\r\n * Assumes that quaternion is 1 unit in length.\r\n * Any existing W component will be ignored.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a quat to calculate W component of\r\n * @returns {quat} out\r\n */\n\nexport function calculateW(out, a) {\n  var x = a[0],\n      y = a[1],\n      z = a[2];\n  out[0] = x;\n  out[1] = y;\n  out[2] = z;\n  out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));\n  return out;\n}\n/**\r\n * Calculate the exponential of a unit quaternion.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a quat to calculate the exponential of\r\n * @returns {quat} out\r\n */\n\nexport function exp(out, a) {\n  var x = a[0],\n      y = a[1],\n      z = a[2],\n      w = a[3];\n  var r = Math.sqrt(x * x + y * y + z * z);\n  var et = Math.exp(w);\n  var s = r > 0 ? et * Math.sin(r) / r : 0;\n  out[0] = x * s;\n  out[1] = y * s;\n  out[2] = z * s;\n  out[3] = et * Math.cos(r);\n  return out;\n}\n/**\r\n * Calculate the natural logarithm of a unit quaternion.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a quat to calculate the exponential of\r\n * @returns {quat} out\r\n */\n\nexport function ln(out, a) {\n  var x = a[0],\n      y = a[1],\n      z = a[2],\n      w = a[3];\n  var r = Math.sqrt(x * x + y * y + z * z);\n  var t = r > 0 ? Math.atan2(r, w) / r : 0;\n  out[0] = x * t;\n  out[1] = y * t;\n  out[2] = z * t;\n  out[3] = 0.5 * Math.log(x * x + y * y + z * z + w * w);\n  return out;\n}\n/**\r\n * Calculate the scalar power of a unit quaternion.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a quat to calculate the exponential of\r\n * @param {Number} b amount to scale the quaternion by\r\n * @returns {quat} out\r\n */\n\nexport function pow(out, a, b) {\n  ln(out, a);\n  scale(out, out, b);\n  exp(out, out);\n  return out;\n}\n/**\r\n * Performs a spherical linear interpolation between two quat\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a the first operand\r\n * @param {ReadonlyQuat} b the second operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {quat} out\r\n */\n\nexport function slerp(out, a, b, t) {\n  // benchmarks:\n  //    http://jsperf.com/quaternion-slerp-implementations\n  var ax = a[0],\n      ay = a[1],\n      az = a[2],\n      aw = a[3];\n  var bx = b[0],\n      by = b[1],\n      bz = b[2],\n      bw = b[3];\n  var omega, cosom, sinom, scale0, scale1; // calc cosine\n\n  cosom = ax * bx + ay * by + az * bz + aw * bw; // adjust signs (if necessary)\n\n  if (cosom < 0.0) {\n    cosom = -cosom;\n    bx = -bx;\n    by = -by;\n    bz = -bz;\n    bw = -bw;\n  } // calculate coefficients\n\n\n  if (1.0 - cosom > glMatrix.EPSILON) {\n    // standard case (slerp)\n    omega = Math.acos(cosom);\n    sinom = Math.sin(omega);\n    scale0 = Math.sin((1.0 - t) * omega) / sinom;\n    scale1 = Math.sin(t * omega) / sinom;\n  } else {\n    // \"from\" and \"to\" quaternions are very close\n    //  ... so we can do a linear interpolation\n    scale0 = 1.0 - t;\n    scale1 = t;\n  } // calculate final values\n\n\n  out[0] = scale0 * ax + scale1 * bx;\n  out[1] = scale0 * ay + scale1 * by;\n  out[2] = scale0 * az + scale1 * bz;\n  out[3] = scale0 * aw + scale1 * bw;\n  return out;\n}\n/**\r\n * Generates a random unit quaternion\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @returns {quat} out\r\n */\n\nexport function random(out) {\n  // Implementation of http://planning.cs.uiuc.edu/node198.html\n  // TODO: Calling random 3 times is probably not the fastest solution\n  var u1 = glMatrix.RANDOM();\n  var u2 = glMatrix.RANDOM();\n  var u3 = glMatrix.RANDOM();\n  var sqrt1MinusU1 = Math.sqrt(1 - u1);\n  var sqrtU1 = Math.sqrt(u1);\n  out[0] = sqrt1MinusU1 * Math.sin(2.0 * Math.PI * u2);\n  out[1] = sqrt1MinusU1 * Math.cos(2.0 * Math.PI * u2);\n  out[2] = sqrtU1 * Math.sin(2.0 * Math.PI * u3);\n  out[3] = sqrtU1 * Math.cos(2.0 * Math.PI * u3);\n  return out;\n}\n/**\r\n * Calculates the inverse of a quat\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a quat to calculate inverse of\r\n * @returns {quat} out\r\n */\n\nexport function invert(out, a) {\n  var a0 = a[0],\n      a1 = a[1],\n      a2 = a[2],\n      a3 = a[3];\n  var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;\n  var invDot = dot ? 1.0 / dot : 0; // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0\n\n  out[0] = -a0 * invDot;\n  out[1] = -a1 * invDot;\n  out[2] = -a2 * invDot;\n  out[3] = a3 * invDot;\n  return out;\n}\n/**\r\n * Calculates the conjugate of a quat\r\n * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a quat to calculate conjugate of\r\n * @returns {quat} out\r\n */\n\nexport function conjugate(out, a) {\n  out[0] = -a[0];\n  out[1] = -a[1];\n  out[2] = -a[2];\n  out[3] = a[3];\n  return out;\n}\n/**\r\n * Creates a quaternion from the given 3x3 rotation matrix.\r\n *\r\n * NOTE: The resultant quaternion is not normalized, so you should be sure\r\n * to renormalize the quaternion yourself where necessary.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyMat3} m rotation matrix\r\n * @returns {quat} out\r\n * @function\r\n */\n\nexport function fromMat3(out, m) {\n  // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes\n  // article \"Quaternion Calculus and Fast Animation\".\n  var fTrace = m[0] + m[4] + m[8];\n  var fRoot;\n\n  if (fTrace > 0.0) {\n    // |w| > 1/2, may as well choose w > 1/2\n    fRoot = Math.sqrt(fTrace + 1.0); // 2w\n\n    out[3] = 0.5 * fRoot;\n    fRoot = 0.5 / fRoot; // 1/(4w)\n\n    out[0] = (m[5] - m[7]) * fRoot;\n    out[1] = (m[6] - m[2]) * fRoot;\n    out[2] = (m[1] - m[3]) * fRoot;\n  } else {\n    // |w| <= 1/2\n    var i = 0;\n    if (m[4] > m[0]) i = 1;\n    if (m[8] > m[i * 3 + i]) i = 2;\n    var j = (i + 1) % 3;\n    var k = (i + 2) % 3;\n    fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0);\n    out[i] = 0.5 * fRoot;\n    fRoot = 0.5 / fRoot;\n    out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot;\n    out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;\n    out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;\n  }\n\n  return out;\n}\n/**\r\n * Creates a quaternion from the given euler angle x, y, z.\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {x} Angle to rotate around X axis in degrees.\r\n * @param {y} Angle to rotate around Y axis in degrees.\r\n * @param {z} Angle to rotate around Z axis in degrees.\r\n * @returns {quat} out\r\n * @function\r\n */\n\nexport function fromEuler(out, x, y, z) {\n  var halfToRad = 0.5 * Math.PI / 180.0;\n  x *= halfToRad;\n  y *= halfToRad;\n  z *= halfToRad;\n  var sx = Math.sin(x);\n  var cx = Math.cos(x);\n  var sy = Math.sin(y);\n  var cy = Math.cos(y);\n  var sz = Math.sin(z);\n  var cz = Math.cos(z);\n  out[0] = sx * cy * cz - cx * sy * sz;\n  out[1] = cx * sy * cz + sx * cy * sz;\n  out[2] = cx * cy * sz - sx * sy * cz;\n  out[3] = cx * cy * cz + sx * sy * sz;\n  return out;\n}\n/**\r\n * Returns a string representation of a quatenion\r\n *\r\n * @param {ReadonlyQuat} a vector to represent as a string\r\n * @returns {String} string representation of the vector\r\n */\n\nexport function str(a) {\n  return \"quat(\" + a[0] + \", \" + a[1] + \", \" + a[2] + \", \" + a[3] + \")\";\n}\n/**\r\n * Creates a new quat initialized with values from an existing quaternion\r\n *\r\n * @param {ReadonlyQuat} a quaternion to clone\r\n * @returns {quat} a new quaternion\r\n * @function\r\n */\n\nexport var clone = vec4.clone;\n/**\r\n * Creates a new quat initialized with the given values\r\n *\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @param {Number} w W component\r\n * @returns {quat} a new quaternion\r\n * @function\r\n */\n\nexport var fromValues = vec4.fromValues;\n/**\r\n * Copy the values from one quat to another\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a the source quaternion\r\n * @returns {quat} out\r\n * @function\r\n */\n\nexport var copy = vec4.copy;\n/**\r\n * Set the components of a quat to the given values\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {Number} x X component\r\n * @param {Number} y Y component\r\n * @param {Number} z Z component\r\n * @param {Number} w W component\r\n * @returns {quat} out\r\n * @function\r\n */\n\nexport var set = vec4.set;\n/**\r\n * Adds two quat's\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a the first operand\r\n * @param {ReadonlyQuat} b the second operand\r\n * @returns {quat} out\r\n * @function\r\n */\n\nexport var add = vec4.add;\n/**\r\n * Alias for {@link quat.multiply}\r\n * @function\r\n */\n\nexport var mul = multiply;\n/**\r\n * Scales a quat by a scalar number\r\n *\r\n * @param {quat} out the receiving vector\r\n * @param {ReadonlyQuat} a the vector to scale\r\n * @param {Number} b amount to scale the vector by\r\n * @returns {quat} out\r\n * @function\r\n */\n\nexport var scale = vec4.scale;\n/**\r\n * Calculates the dot product of two quat's\r\n *\r\n * @param {ReadonlyQuat} a the first operand\r\n * @param {ReadonlyQuat} b the second operand\r\n * @returns {Number} dot product of a and b\r\n * @function\r\n */\n\nexport var dot = vec4.dot;\n/**\r\n * Performs a linear interpolation between two quat's\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a the first operand\r\n * @param {ReadonlyQuat} b the second operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {quat} out\r\n * @function\r\n */\n\nexport var lerp = vec4.lerp;\n/**\r\n * Calculates the length of a quat\r\n *\r\n * @param {ReadonlyQuat} a vector to calculate length of\r\n * @returns {Number} length of a\r\n */\n\nexport var length = vec4.length;\n/**\r\n * Alias for {@link quat.length}\r\n * @function\r\n */\n\nexport var len = length;\n/**\r\n * Calculates the squared length of a quat\r\n *\r\n * @param {ReadonlyQuat} a vector to calculate squared length of\r\n * @returns {Number} squared length of a\r\n * @function\r\n */\n\nexport var squaredLength = vec4.squaredLength;\n/**\r\n * Alias for {@link quat.squaredLength}\r\n * @function\r\n */\n\nexport var sqrLen = squaredLength;\n/**\r\n * Normalize a quat\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a quaternion to normalize\r\n * @returns {quat} out\r\n * @function\r\n */\n\nexport var normalize = vec4.normalize;\n/**\r\n * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)\r\n *\r\n * @param {ReadonlyQuat} a The first quaternion.\r\n * @param {ReadonlyQuat} b The second quaternion.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\n\nexport var exactEquals = vec4.exactEquals;\n/**\r\n * Returns whether or not the quaternions have approximately the same elements in the same position.\r\n *\r\n * @param {ReadonlyQuat} a The first vector.\r\n * @param {ReadonlyQuat} b The second vector.\r\n * @returns {Boolean} True if the vectors are equal, false otherwise.\r\n */\n\nexport var equals = vec4.equals;\n/**\r\n * Sets a quaternion to represent the shortest rotation from one\r\n * vector to another.\r\n *\r\n * Both vectors are assumed to be unit length.\r\n *\r\n * @param {quat} out the receiving quaternion.\r\n * @param {ReadonlyVec3} a the initial vector\r\n * @param {ReadonlyVec3} b the destination vector\r\n * @returns {quat} out\r\n */\n\nexport var rotationTo = function () {\n  var tmpvec3 = vec3.create();\n  var xUnitVec3 = vec3.fromValues(1, 0, 0);\n  var yUnitVec3 = vec3.fromValues(0, 1, 0);\n  return function (out, a, b) {\n    var dot = vec3.dot(a, b);\n\n    if (dot < -0.999999) {\n      vec3.cross(tmpvec3, xUnitVec3, a);\n      if (vec3.len(tmpvec3) < 0.000001) vec3.cross(tmpvec3, yUnitVec3, a);\n      vec3.normalize(tmpvec3, tmpvec3);\n      setAxisAngle(out, tmpvec3, Math.PI);\n      return out;\n    } else if (dot > 0.999999) {\n      out[0] = 0;\n      out[1] = 0;\n      out[2] = 0;\n      out[3] = 1;\n      return out;\n    } else {\n      vec3.cross(tmpvec3, a, b);\n      out[0] = tmpvec3[0];\n      out[1] = tmpvec3[1];\n      out[2] = tmpvec3[2];\n      out[3] = 1 + dot;\n      return normalize(out, out);\n    }\n  };\n}();\n/**\r\n * Performs a spherical linear interpolation with two control points\r\n *\r\n * @param {quat} out the receiving quaternion\r\n * @param {ReadonlyQuat} a the first operand\r\n * @param {ReadonlyQuat} b the second operand\r\n * @param {ReadonlyQuat} c the third operand\r\n * @param {ReadonlyQuat} d the fourth operand\r\n * @param {Number} t interpolation amount, in the range [0-1], between the two inputs\r\n * @returns {quat} out\r\n */\n\nexport var sqlerp = function () {\n  var temp1 = create();\n  var temp2 = create();\n  return function (out, a, b, c, d, t) {\n    slerp(temp1, a, d, t);\n    slerp(temp2, b, c, t);\n    slerp(out, temp1, temp2, 2 * t * (1 - t));\n    return out;\n  };\n}();\n/**\r\n * Sets the specified quaternion with values corresponding to the given\r\n * axes. Each axis is a vec3 and is expected to be unit length and\r\n * perpendicular to all other specified axes.\r\n *\r\n * @param {ReadonlyVec3} view  the vector representing the viewing direction\r\n * @param {ReadonlyVec3} right the vector representing the local \"right\" direction\r\n * @param {ReadonlyVec3} up    the vector representing the local \"up\" direction\r\n * @returns {quat} out\r\n */\n\nexport var setAxes = function () {\n  var matr = mat3.create();\n  return function (out, view, right, up) {\n    matr[0] = right[0];\n    matr[3] = right[1];\n    matr[6] = right[2];\n    matr[1] = up[0];\n    matr[4] = up[1];\n    matr[7] = up[2];\n    matr[2] = -view[0];\n    matr[5] = -view[1];\n    matr[8] = -view[2];\n    return normalize(out, fromMat3(out, matr));\n  };\n}();","import {LineType, AnimKeyframe, AnimVector} from '../model';\nimport {vec3, quat} from 'gl-matrix';\n\nconst findKeyframesRes = {\n    frame: 0,\n    left: null,\n    right: null\n};\n\nexport function lerp (left: number, right: number, t: number): number {\n    return left * (1 - t) + right * t;\n}\n\nfunction bezier (left: number, outTan: number, inTan: number, right: number, t: number): number {\n    const inverseFactor = 1 - t,\n        inverseFactorTimesTwo = inverseFactor * inverseFactor,\n        factorTimes2 = t * t,\n        factor1 = inverseFactorTimesTwo * inverseFactor,\n        factor2 = 3 * t * inverseFactorTimesTwo,\n        factor3 = 3 * factorTimes2 * inverseFactor,\n        factor4 = factorTimes2 * t;\n\n    return left * factor1 + outTan * factor2 + inTan * factor3 + right * factor4;\n}\n\nfunction hermite (left: number, outTan: number, inTan: number, right: number, t: number): number {\n    const factorTimes2 = t * t,\n        factor1 = factorTimes2 * (2 * t - 3) + 1,\n        factor2 = factorTimes2 * (t - 2) + t,\n        factor3 = factorTimes2 * (t - 1),\n        factor4 = factorTimes2 * (3 - 2 * t);\n\n    return left * factor1 + outTan * factor2 + inTan * factor3 + right * factor4;\n}\n\nexport function findKeyframes (animVector: AnimVector, frame: number, from: number, to: number):\n        null | {frame: number, left: AnimKeyframe, right: AnimKeyframe} {\n    if (!animVector) {\n        return null;\n    }\n\n    const array = animVector.Keys;\n    let first = 0;\n    let count = array.length;\n\n    if (count === 0) {\n        return null;\n    }\n\n    if (array[0].Frame > to) {\n        return null;\n    } else if (array[count - 1].Frame < from) {\n        return null;\n    }\n\n    while (count > 0) {\n        const step = count >> 1;\n        if (array[first + step].Frame <= frame) {\n            first = first + step + 1;\n            count -= step + 1;\n        } else {\n            count = step;\n        }\n    }\n\n    if (first === array.length || array[first].Frame > to) {\n        if (first > 0 && array[first - 1].Frame >= from) {\n            findKeyframesRes.frame = frame;\n            findKeyframesRes.left = array[first - 1];\n            findKeyframesRes.right = array[first - 1];\n\n            return findKeyframesRes;\n        } else {\n            return null;\n        }\n    }\n    if (first === 0 || array[first - 1].Frame < from) {\n        if (array[first].Frame <= to) {\n            findKeyframesRes.frame = frame;\n            findKeyframesRes.left = array[first];\n            findKeyframesRes.right = array[first];\n\n            return findKeyframesRes;\n        } else {\n            return null;\n        }\n    }\n\n    findKeyframesRes.frame = frame;\n    findKeyframesRes.left = array[first - 1];\n    findKeyframesRes.right = array[first];\n\n    return findKeyframesRes;\n}\n\nexport function interpNum (frame: number, left: AnimKeyframe, right: AnimKeyframe, lineType: LineType): number|null {\n    if (left.Frame === right.Frame) {\n        return left.Vector[0];\n    }\n\n    const t = (frame - left.Frame) / (right.Frame - left.Frame);\n\n    if (lineType === LineType.DontInterp) {\n        return left.Vector[0];\n    } else if (lineType === LineType.Bezier) {\n        return bezier(left.Vector[0], left.OutTan[0], right.InTan[0], right.Vector[0], t);\n    } else if (lineType === LineType.Hermite) {\n        return hermite(left.Vector[0], left.OutTan[0], right.InTan[0], right.Vector[0], t);\n    } else {\n        // Linear\n        return lerp(left.Vector[0], right.Vector[0], t);\n    }\n}\n\nexport function interpVec3 (out: vec3, frame: number, left: AnimKeyframe, right: AnimKeyframe,\n                            lineType: LineType): vec3 {\n    if (left.Frame === right.Frame) {\n        return left.Vector as vec3;\n    }\n\n    const t = (frame - left.Frame) / (right.Frame - left.Frame);\n\n    if (lineType === LineType.DontInterp) {\n        return left.Vector as vec3;\n    } else if (lineType === LineType.Bezier) {\n        return vec3.bezier(out, left.Vector as vec3, left.OutTan as vec3, right.InTan as vec3, right.Vector as vec3, t);\n    } else if (lineType === LineType.Hermite) {\n        return vec3.hermite(out, left.Vector as vec3, left.OutTan as vec3,\n            right.InTan as vec3, right.Vector as vec3, t);\n    } else {\n        return vec3.lerp(out, left.Vector as vec3, right.Vector as vec3, t);\n    }\n}\n\nexport function interpQuat (out: quat, frame: number, left: AnimKeyframe, right: AnimKeyframe,\n                            lineType: LineType): quat {\n    if (left.Frame === right.Frame) {\n        return left.Vector as quat;\n    }\n\n    const t = (frame - left.Frame) / (right.Frame - left.Frame);\n\n    if (lineType === LineType.DontInterp) {\n        return left.Vector as quat;\n    } else if (lineType === LineType.Hermite || lineType === LineType.Bezier) {\n        return quat.sqlerp(out, left.Vector as quat, left.OutTan as quat, right.InTan as quat, right.Vector as quat, t);\n    } else {\n        return quat.slerp(out, left.Vector as quat, right.Vector as quat, t);\n    }\n}\n","import {AnimKeyframe, AnimVector} from '../model';\nimport {findKeyframes, interpNum, interpVec3, interpQuat} from './interp';\nimport {vec3, quat} from 'gl-matrix';\nimport {RendererData} from './rendererData';\n\nconst findLocalFrameRes = {\n    frame: 0,\n    from: 0,\n    to: 0\n};\n\nexport class ModelInterp {\n    public static maxAnimVectorVal (vector: AnimVector|number): number {\n        if (typeof vector === 'number') {\n            return vector;\n        }\n\n        let max = vector.Keys[0].Vector[0];\n\n        for (let i = 1; i < vector.Keys.length; ++i) {\n            if (vector.Keys[i].Vector[0] > max) {\n                max = vector.Keys[i].Vector[0];\n            }\n        }\n\n        return max;\n    }\n\n    private rendererData: RendererData;\n\n    constructor (rendererData: RendererData) {\n        this.rendererData = rendererData;\n    }\n\n    public num (animVector: AnimVector): number|null {\n        const res = this.findKeyframes(animVector);\n        if (!res) {\n            return null;\n        }\n        return interpNum(res.frame, res.left, res.right, animVector.LineType);\n    }\n\n    public vec3 (out: vec3, animVector: AnimVector): vec3|null {\n        const res = this.findKeyframes(animVector);\n        if (!res) {\n            return null;\n        }\n        return interpVec3(out, res.frame, res.left, res.right, animVector.LineType);\n    }\n\n    public quat (out: quat, animVector: AnimVector): quat|null {\n        const res = this.findKeyframes(animVector);\n        if (!res) {\n            return null;\n        }\n        return interpQuat(out, res.frame, res.left, res.right, animVector.LineType);\n    }\n\n    public animVectorVal (vector: AnimVector|number, defaultVal: number): number {\n        let res;\n\n        if (typeof vector === 'number') {\n            res = vector;\n        } else {\n            res = this.num(vector);\n            if (res === null) {\n                res = defaultVal;\n            }\n        }\n\n        return res;\n    }\n\n    public findKeyframes (animVector: AnimVector): null | {frame: number, left: AnimKeyframe, right: AnimKeyframe} {\n        if (!animVector) {\n            return null;\n        }\n\n        const {frame, from, to} = this.findLocalFrame(animVector);\n\n        return findKeyframes(animVector, frame, from, to);\n    }\n\n    public findLocalFrame (animVector: AnimVector): {frame: number, from: number, to: number} {\n        if (typeof animVector.GlobalSeqId === 'number') {\n            findLocalFrameRes.frame = this.rendererData.globalSequencesFrames[animVector.GlobalSeqId];\n            findLocalFrameRes.from = 0;\n            findLocalFrameRes.to = this.rendererData.model.GlobalSequences[animVector.GlobalSeqId];\n        } else {\n            findLocalFrameRes.frame = this.rendererData.frame;\n            findLocalFrameRes.from = this.rendererData.animationInfo.Interval[0];\n            findLocalFrameRes.to = this.rendererData.animationInfo.Interval[1];\n        }\n        return findLocalFrameRes;\n    }\n}\n","export default \"attribute vec3 aVertexPosition;\\nattribute vec2 aTextureCoord;\\nattribute vec4 aColor;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\n\\nvarying vec2 vTextureCoord;\\nvarying vec4 vColor;\\n\\nvoid main(void) {\\n    vec4 position = vec4(aVertexPosition, 1.0);\\n    gl_Position = uPMatrix * uMVMatrix * position;\\n    vTextureCoord = aTextureCoord;\\n    vColor = aColor;\\n}\\n\"","export default \"precision mediump float;\\n\\nvarying vec2 vTextureCoord;\\nvarying vec4 vColor;\\n\\nuniform sampler2D uSampler;\\nuniform vec3 uReplaceableColor;\\nuniform float uReplaceableType;\\nuniform float uDiscardAlphaLevel;\\n\\nfloat hypot (vec2 z) {\\n    float t;\\n    float x = abs(z.x);\\n    float y = abs(z.y);\\n    t = min(x, y);\\n    x = max(x, y);\\n    t = t / x;\\n    return (z.x == 0.0 && z.y == 0.0) ? 0.0 : x * sqrt(1.0 + t * t);\\n}\\n\\nvoid main(void) {\\n    vec2 coords = vec2(vTextureCoord.s, vTextureCoord.t);\\n    if (uReplaceableType == 0.) {\\n        gl_FragColor = texture2D(uSampler, coords);\\n    } else if (uReplaceableType == 1.) {\\n        gl_FragColor = vec4(uReplaceableColor, 1.0);\\n    } else if (uReplaceableType == 2.) {\\n        float dist = hypot(coords - vec2(0.5, 0.5)) * 2.;\\n        float truncateDist = clamp(1. - dist * 1.4, 0., 1.);\\n        float alpha = sin(truncateDist);\\n        gl_FragColor = vec4(uReplaceableColor * alpha, 1.0);\\n    }\\n    gl_FragColor *= vColor;\\n\\n    if (gl_FragColor[3] < uDiscardAlphaLevel) {\\n        discard;\\n    }\\n}\\n\"","export default \"struct VSUniforms {\\n    mvMatrix: mat4x4f,\\n    pMatrix: mat4x4f,\\n}\\n\\nstruct FSUniforms {\\n    replaceableColor: vec3f,\\n    replaceableType: u32,\\n    discardAlphaLevel: f32,\\n}\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n@group(1) @binding(0) var<uniform> fsUniforms: FSUniforms;\\n@group(1) @binding(1) var fsUniformSampler: sampler;\\n@group(1) @binding(2) var fsUniformTexture: texture_2d<f32>;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n    @location(1) textureCoord: vec2f,\\n    @location(2) color: vec4f,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) textureCoord: vec2f,\\n    @location(1) color: vec4f,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    var position: vec4f = vec4f(in.vertexPosition, 1.0);\\n\\n    var out: VSOut;\\n    out.position = vsUniforms.pMatrix * vsUniforms.mvMatrix * position;\\n    out.textureCoord = in.textureCoord;\\n    out.color = in.color;\\n    return out;\\n}\\n\\nfn hypot(z: vec2f) -> f32 {\\n    var t: f32 = 0;\\n    var x: f32 = abs(z.x);\\n    let y: f32 = abs(z.y);\\n    t = min(x, y);\\n    x = max(x, y);\\n    t = t / x;\\n    if (z.x == 0.0 && z.y == 0.0) {\\n        return 0.0;\\n    }\\n    return x * sqrt(1.0 + t * t);\\n}\\n\\n@fragment fn fs(\\n    in: VSOut\\n) -> @location(0) vec4f {\\n    let texCoord: vec2f = in.textureCoord;\\n    var color: vec4f = vec4f(0.0);\\n\\n    if (fsUniforms.replaceableType == 0) {\\n        color = textureSample(fsUniformTexture, fsUniformSampler, texCoord);\\n    } else if (fsUniforms.replaceableType == 1) {\\n        color = vec4f(fsUniforms.replaceableColor, 1.0);\\n    } else if (fsUniforms.replaceableType == 2) {\\n        let dist: f32 = hypot(texCoord - vec2(0.5, 0.5)) * 2.;\\n        let truncateDist: f32 = clamp(1. - dist * 1.4, 0., 1.);\\n        let alpha: f32 = sin(truncateDist);\\n        color = vec4f(fsUniforms.replaceableColor * alpha, 1.0);\\n    }\\n\\n    color *= in.color;\\n\\n    // hand-made alpha-test\\n    if (color.a < fsUniforms.discardAlphaLevel) {\\n        discard;\\n    }\\n\\n    return color;\\n}\\n\"","import {\n    ParticleEmitter2, ParticleEmitter2FilterMode, ParticleEmitter2Flags,\n    ParticleEmitter2FramesFlags\n} from '../model';\nimport {vec3, vec4} from 'gl-matrix';\nimport {ModelInterp} from './modelInterp';\nimport {mat4} from 'gl-matrix';\nimport {degToRad, rand, getShader} from './util';\nimport {RendererData} from './rendererData';\nimport {lerp} from './interp';\nimport vertexShader from './shaders/webgl/particles.vs.glsl?raw';\nimport fragmentShader from './shaders/webgl/particles.fs.glsl?raw';\nimport particlesShader from './shaders/webgpu/particles.wgsl?raw';\n\nconst rotateCenter: vec3 = vec3.fromValues(0, 0, 0);\nconst firstColor = vec4.create();\nconst secondColor = vec4.create();\nconst color = vec4.create();\nconst tailPos = vec3.create();\nconst tailCross = vec3.create();\n\ninterface Particle {\n    emitter: ParticleEmitterWrapper;\n    // xyz\n    pos: vec3;\n    // xyz\n    speed: vec3;\n    angle: number;\n    gravity: number;\n    lifeSpan: number;\n}\n\ninterface ParticleEmitterWrapper {\n    index: number;\n\n    emission: number;\n    squirtFrame: number;\n    particles: Particle[];\n    props: ParticleEmitter2;\n    capacity: number;\n    baseCapacity: number;\n    // head or tail or both\n    type: number;\n\n    // xyz\n    tailVertices: Float32Array<ArrayBuffer>;\n    tailVertexBuffer: WebGLBuffer;\n    tailVertexGPUBuffer: GPUBuffer;\n    // xyz\n    headVertices: Float32Array<ArrayBuffer>;\n    headVertexBuffer: WebGLBuffer;\n    headVertexGPUBuffer: GPUBuffer;\n    // xy\n    tailTexCoords: Float32Array<ArrayBuffer>;\n    tailTexCoordBuffer: WebGLBuffer;\n    tailTexCoordGPUBuffer: GPUBuffer;\n    // xy\n    headTexCoords: Float32Array<ArrayBuffer>;\n    headTexCoordBuffer: WebGLBuffer;\n    headTexCoordGPUBuffer: GPUBuffer;\n    // rgba\n    colors: Float32Array<ArrayBuffer>;\n    colorBuffer: WebGLBuffer;\n    colorGPUBuffer: GPUBuffer;\n    // 2 * triangles\n    indices: Uint16Array<ArrayBuffer>;\n    indexBuffer: WebGLBuffer;\n    indexGPUBuffer: GPUBuffer;\n\n    fsUniformsBuffer: GPUBuffer;\n}\n\nconst DISCARD_ALPHA_KEY_LEVEL = 0.83;\nconst DISCARD_MODULATE_LEVEL = 0.01;\n\nexport class ParticlesController {\n    private gl: WebGL2RenderingContext | WebGLRenderingContext;\n    private shaderProgram: WebGLProgram;\n    private vertexShader: WebGLShader;\n    private fragmentShader: WebGLShader;\n\n    private device: GPUDevice;\n    private gpuShaderModule: GPUShaderModule;\n    private gpuPipelineLayout: GPUPipelineLayout;\n    private gpuPipelines: GPURenderPipeline[];\n    private vsBindGroupLayout: GPUBindGroupLayout | null;\n    private fsBindGroupLayout: GPUBindGroupLayout | null;\n    private gpuVSUniformsBuffer: GPUBuffer;\n    private gpuVSUniformsBindGroup: GPUBindGroup;\n\n    private shaderProgramLocations: {\n        vertexPositionAttribute: number | null;\n        textureCoordAttribute: number | null;\n        colorAttribute: number | null;\n        pMatrixUniform: WebGLUniformLocation | null;\n        mvMatrixUniform: WebGLUniformLocation | null;\n        samplerUniform: WebGLUniformLocation | null;\n        replaceableColorUniform: WebGLUniformLocation | null;\n        replaceableTypeUniform: WebGLUniformLocation | null;\n        discardAlphaLevelUniform: WebGLUniformLocation | null;\n    };\n\n    private particleStorage: Particle[];\n\n    private interp: ModelInterp;\n    private rendererData: RendererData;\n    private emitters: ParticleEmitterWrapper[];\n\n    private particleBaseVectors: vec3[];\n\n    constructor (interp: ModelInterp, rendererData: RendererData) {\n        this.shaderProgramLocations = {\n            vertexPositionAttribute: null,\n            textureCoordAttribute: null,\n            colorAttribute: null,\n            pMatrixUniform: null,\n            mvMatrixUniform: null,\n            samplerUniform: null,\n            replaceableColorUniform: null,\n            replaceableTypeUniform: null,\n            discardAlphaLevelUniform: null\n        };\n        this.particleStorage = [];\n        this.interp = interp;\n        this.rendererData = rendererData;\n        this.emitters = [];\n\n        if (rendererData.model.ParticleEmitters2.length) {\n            this.particleBaseVectors = [\n                vec3.create(),\n                vec3.create(),\n                vec3.create(),\n                vec3.create()\n            ];\n\n            for (let i = 0; i < rendererData.model.ParticleEmitters2.length; ++i) {\n                const particleEmitter = rendererData.model.ParticleEmitters2[i];\n                const emitter: ParticleEmitterWrapper = {\n                    index: i,\n                    emission: 0,\n                    squirtFrame: 0,\n                    particles: [],\n                    props: particleEmitter,\n                    capacity: 0,\n                    baseCapacity: 0,\n                    type: particleEmitter.FrameFlags,\n                    tailVertices: null,\n                    tailVertexBuffer: null,\n                    tailVertexGPUBuffer: null,\n                    headVertices: null,\n                    headVertexBuffer: null,\n                    headVertexGPUBuffer: null,\n                    tailTexCoords: null,\n                    tailTexCoordBuffer: null,\n                    tailTexCoordGPUBuffer: null,\n                    headTexCoords: null,\n                    headTexCoordBuffer: null,\n                    headTexCoordGPUBuffer: null,\n                    colors: null,\n                    colorBuffer: null,\n                    colorGPUBuffer: null,\n                    indices: null,\n                    indexBuffer: null,\n                    indexGPUBuffer: null,\n                    fsUniformsBuffer: null\n                };\n\n                emitter.baseCapacity = Math.ceil(\n                    ModelInterp.maxAnimVectorVal(emitter.props.EmissionRate) * emitter.props.LifeSpan\n                );\n\n                this.emitters.push(emitter);\n            }\n        }\n    }\n\n    public destroy (): void {\n        if (this.shaderProgram) {\n            if (this.vertexShader) {\n                this.gl.detachShader(this.shaderProgram, this.vertexShader);\n                this.gl.deleteShader(this.vertexShader);\n                this.vertexShader = null;\n            }\n            if (this.fragmentShader) {\n                this.gl.detachShader(this.shaderProgram, this.fragmentShader);\n                this.gl.deleteShader(this.fragmentShader);\n                this.fragmentShader = null;\n            }\n            this.gl.deleteProgram(this.shaderProgram);\n            this.shaderProgram = null;\n        }\n        this.particleStorage = [];\n\n        if (this.gpuVSUniformsBuffer) {\n            this.gpuVSUniformsBuffer.destroy();\n            this.gpuVSUniformsBuffer = null;\n        }\n\n        for (const emitter of this.emitters) {\n            if (emitter.colorGPUBuffer) {\n                emitter.colorGPUBuffer.destroy();\n            }\n            if (emitter.indexGPUBuffer) {\n                emitter.indexGPUBuffer.destroy();\n            }\n            if (emitter.headVertexGPUBuffer) {\n                emitter.headVertexGPUBuffer.destroy();\n            }\n            if (emitter.tailVertexGPUBuffer) {\n                emitter.tailVertexGPUBuffer.destroy();\n            }\n            if (emitter.headTexCoordGPUBuffer) {\n                emitter.headTexCoordGPUBuffer.destroy();\n            }\n            if (emitter.tailTexCoordGPUBuffer) {\n                emitter.tailTexCoordGPUBuffer.destroy();\n            }\n            if (emitter.fsUniformsBuffer) {\n                emitter.fsUniformsBuffer.destroy();\n            }\n        }\n\n        this.emitters = [];\n    }\n\n    public initGL (glContext: WebGLRenderingContext): void {\n        this.gl = glContext;\n\n        this.initShaders();\n    }\n\n    public initGPUDevice (device: GPUDevice): void {\n        this.device = device;\n\n        this.gpuShaderModule = device.createShaderModule({\n            label: 'particles shader module',\n            code: particlesShader\n        });\n\n        this.vsBindGroupLayout = this.device.createBindGroupLayout({\n            label: 'particles vs bind group layout',\n            entries: [ {\n                binding: 0,\n                visibility: GPUShaderStage.VERTEX,\n                buffer: {\n                    type: 'uniform',\n                    hasDynamicOffset: false,\n                    minBindingSize: 128\n                }\n            }] as const\n        });\n        this.fsBindGroupLayout = this.device.createBindGroupLayout({\n            label: 'particles bind group layout2',\n            entries: [\n                {\n                    binding: 0,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    buffer: {\n                    type: 'uniform',\n                        hasDynamicOffset: false,\n                        minBindingSize: 32\n                    }\n                },\n                {\n                    binding: 1,\n                    visibility: GPUShaderStage.FRAGMENT,\n                        sampler: {\n                        type: 'filtering'\n                    }\n                },\n                {\n                    binding: 2,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    texture: {\n                        sampleType: 'float',\n                        viewDimension: \"2d\",\n                        multisampled: false\n                    }\n                }\n            ] as const\n        });\n\n        this.gpuPipelineLayout = this.device.createPipelineLayout({\n            label: 'particles pipeline layout',\n            bindGroupLayouts: [\n                this.vsBindGroupLayout,\n                this.fsBindGroupLayout\n            ]\n        });\n\n        const createPipeline = (name: string, blend: GPUBlendState, depth: GPUDepthStencilState) => {\n            return device.createRenderPipeline({\n                label: `particles pipeline ${name}`,\n                layout: this.gpuPipelineLayout,\n                vertex: {\n                    module: this.gpuShaderModule,\n                    buffers: [{\n                        arrayStride: 12,\n                        attributes: [{\n                            shaderLocation: 0,\n                            offset: 0,\n                            format: 'float32x3' as const\n                        }]\n                    }, {\n                        arrayStride: 8,\n                        attributes: [{\n                            shaderLocation: 1,\n                            offset: 0,\n                            format: 'float32x2' as const\n                        }]\n                    }, {\n                        arrayStride: 16,\n                        attributes: [{\n                            shaderLocation: 2,\n                            offset: 0,\n                            format: 'float32x4' as const\n                        }]\n                    }]\n                },\n                fragment: {\n                    module: this.gpuShaderModule,\n                    targets: [{\n                        format: navigator.gpu.getPreferredCanvasFormat(),\n                        blend\n                    }]\n                },\n                depthStencil: depth\n            });\n        };\n\n        this.gpuPipelines = [\n            createPipeline('blend', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'src-alpha',\n                    dstFactor: 'one-minus-src-alpha'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'one',\n                    dstFactor: 'one-minus-src-alpha'\n                }\n            }, {\n                depthWriteEnabled: false,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n            createPipeline('additive', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'src',\n                    dstFactor: 'one'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'src',\n                    dstFactor: 'one'\n                }\n            }, {\n                depthWriteEnabled: false,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n            createPipeline('modulate', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'zero',\n                    dstFactor: 'src'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'zero',\n                    dstFactor: 'one'\n                }\n            }, {\n                depthWriteEnabled: false,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n            createPipeline('modulate2x', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'dst',\n                    dstFactor: 'src'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'zero',\n                    dstFactor: 'one'\n                }\n            }, {\n                depthWriteEnabled: false,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n            createPipeline('alphaKey', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'src-alpha',\n                    dstFactor: 'one'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'src-alpha',\n                    dstFactor: 'one'\n                }\n            }, {\n                depthWriteEnabled: false,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n        ];\n\n        this.gpuVSUniformsBuffer = this.device.createBuffer({\n            label: 'particles vs uniforms',\n            size: 128,\n            usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n        });\n        this.gpuVSUniformsBindGroup = this.device.createBindGroup({\n            layout: this.vsBindGroupLayout,\n            entries: [\n                {\n                    binding: 0,\n                    resource: { buffer: this.gpuVSUniformsBuffer }\n                }\n            ]\n        });\n    }\n\n    private initShaders (): void {\n        const vertex = this.vertexShader = getShader(this.gl, vertexShader, this.gl.VERTEX_SHADER);\n        const fragment = this.fragmentShader = getShader(this.gl, fragmentShader, this.gl.FRAGMENT_SHADER);\n\n        const shaderProgram = this.shaderProgram = this.gl.createProgram();\n        this.gl.attachShader(shaderProgram, vertex);\n        this.gl.attachShader(shaderProgram, fragment);\n        this.gl.linkProgram(shaderProgram);\n\n        if (!this.gl.getProgramParameter(shaderProgram, this.gl.LINK_STATUS)) {\n            alert('Could not initialise shaders');\n        }\n\n        this.gl.useProgram(shaderProgram);\n\n        this.shaderProgramLocations.vertexPositionAttribute =\n            this.gl.getAttribLocation(shaderProgram, 'aVertexPosition');\n        this.shaderProgramLocations.textureCoordAttribute =\n            this.gl.getAttribLocation(shaderProgram, 'aTextureCoord');\n        this.shaderProgramLocations.colorAttribute =\n            this.gl.getAttribLocation(shaderProgram, 'aColor');\n\n        this.shaderProgramLocations.pMatrixUniform = this.gl.getUniformLocation(shaderProgram, 'uPMatrix');\n        this.shaderProgramLocations.mvMatrixUniform = this.gl.getUniformLocation(shaderProgram, 'uMVMatrix');\n        this.shaderProgramLocations.samplerUniform = this.gl.getUniformLocation(shaderProgram, 'uSampler');\n        this.shaderProgramLocations.replaceableColorUniform =\n            this.gl.getUniformLocation(shaderProgram, 'uReplaceableColor');\n        this.shaderProgramLocations.replaceableTypeUniform =\n            this.gl.getUniformLocation(shaderProgram, 'uReplaceableType');\n        this.shaderProgramLocations.discardAlphaLevelUniform =\n            this.gl.getUniformLocation(shaderProgram, 'uDiscardAlphaLevel');\n    }\n\n    private updateParticle (particle: Particle, delta: number): void {\n        delta /= 1000;\n\n        particle.lifeSpan -= delta;\n        if (particle.lifeSpan <= 0) {\n            return;\n        }\n        particle.speed[2] -= particle.gravity * delta;\n\n        particle.pos[0] += particle.speed[0] * delta;\n        particle.pos[1] += particle.speed[1] * delta;\n        particle.pos[2] += particle.speed[2] * delta;\n    }\n\n    private resizeEmitterBuffers (emitter: ParticleEmitterWrapper, size: number): void {\n        if (size <= emitter.capacity) {\n            return;\n        }\n\n        size = Math.max(size, emitter.baseCapacity);\n\n        let tailVertices;\n        let headVertices;\n        let tailTexCoords;\n        let headTexCoords;\n\n        if (emitter.type & ParticleEmitter2FramesFlags.Tail) {\n            tailVertices = new Float32Array(size * 4 * 3);  // 4 vertices * xyz\n            tailTexCoords = new Float32Array(size * 4 * 2); // 4 vertices * xy\n        }\n        if (emitter.type & ParticleEmitter2FramesFlags.Head) {\n            headVertices = new Float32Array(size * 4 * 3);  // 4 vertices * xyz\n            headTexCoords = new Float32Array(size * 4 * 2); // 4 vertices * xy\n        }\n\n        const colors = new Float32Array(size * 4 * 4);    // 4 vertices * rgba\n        const indices = new Uint16Array(size * 6);        // 4 vertices * 2 triangles\n\n        if (emitter.capacity) {\n            indices.set(emitter.indices);\n        }\n\n        for (let i = emitter.capacity; i < size; ++i) {\n            indices[i * 6    ] = i * 4    ;\n            indices[i * 6 + 1] = i * 4 + 1;\n            indices[i * 6 + 2] = i * 4 + 2;\n            indices[i * 6 + 3] = i * 4 + 2;\n            indices[i * 6 + 4] = i * 4 + 1;\n            indices[i * 6 + 5] = i * 4 + 3;\n        }\n\n        if (tailVertices) {\n            emitter.tailVertices = tailVertices;\n            emitter.tailTexCoords = tailTexCoords;\n        }\n        if (headVertices) {\n            emitter.headVertices = headVertices;\n            emitter.headTexCoords = headTexCoords;\n        }\n        emitter.colors = colors;\n        emitter.indices = indices;\n\n        emitter.capacity = size;\n\n        if (!emitter.indexBuffer) {\n            if (this.gl) {\n                if (emitter.type & ParticleEmitter2FramesFlags.Tail) {\n                    emitter.tailVertexBuffer = this.gl.createBuffer();\n                    emitter.tailTexCoordBuffer = this.gl.createBuffer();\n                }\n                if (emitter.type & ParticleEmitter2FramesFlags.Head) {\n                    emitter.headVertexBuffer = this.gl.createBuffer();\n                    emitter.headTexCoordBuffer = this.gl.createBuffer();\n                }\n                emitter.colorBuffer = this.gl.createBuffer();\n                emitter.indexBuffer = this.gl.createBuffer();\n            } else if (this.device) {\n                if (emitter.type & ParticleEmitter2FramesFlags.Tail) {\n                    emitter.tailVertexGPUBuffer?.destroy();\n                    emitter.tailVertexGPUBuffer = this.device.createBuffer({\n                        label: `particles tail vertex buffer ${emitter.index}`,\n                        size: tailVertices.byteLength,\n                        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST\n                    });\n                    emitter.tailTexCoordGPUBuffer?.destroy();\n                    emitter.tailTexCoordGPUBuffer = this.device.createBuffer({\n                        label: `particles tail texCoords buffer ${emitter.index}`,\n                        size: tailTexCoords.byteLength,\n                        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST\n                    });\n                }\n                if (emitter.type & ParticleEmitter2FramesFlags.Head) {\n                    emitter.headVertexGPUBuffer?.destroy();\n                    emitter.headVertexGPUBuffer = this.device.createBuffer({\n                        label: `particles head vertex buffer ${emitter.index}`,\n                        size: headVertices.byteLength,\n                        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST\n                    });\n                    emitter.headTexCoordGPUBuffer?.destroy();\n                    emitter.headTexCoordGPUBuffer = this.device.createBuffer({\n                        label: `particles head texCoords buffer ${emitter.index}`,\n                        size: headTexCoords.byteLength,\n                        usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST\n                    });\n                }\n                emitter.colorGPUBuffer?.destroy();\n                emitter.colorGPUBuffer = this.device.createBuffer({\n                    label: `particles color buffer ${emitter.index}`,\n                    size: colors.byteLength,\n                    usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST\n                });\n                emitter.indexGPUBuffer?.destroy();\n                emitter.indexGPUBuffer = this.device.createBuffer({\n                    label: `particles index buffer ${emitter.index}`,\n                    size: indices.byteLength,\n                    usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST\n                });\n            }\n        }\n    }\n\n    public update (delta: number): void {\n        for (const emitter of this.emitters) {\n            this.updateEmitter(emitter, delta);\n        }\n    }\n\n    public render (mvMatrix: mat4, pMatrix: mat4): void {\n        this.gl.enable(this.gl.CULL_FACE);\n        this.gl.useProgram(this.shaderProgram);\n\n        this.gl.uniformMatrix4fv(this.shaderProgramLocations.pMatrixUniform, false, pMatrix);\n        this.gl.uniformMatrix4fv(this.shaderProgramLocations.mvMatrixUniform, false, mvMatrix);\n\n        this.gl.enableVertexAttribArray(this.shaderProgramLocations.vertexPositionAttribute);\n        this.gl.enableVertexAttribArray(this.shaderProgramLocations.textureCoordAttribute);\n        this.gl.enableVertexAttribArray(this.shaderProgramLocations.colorAttribute);\n\n        for (const emitter of this.emitters) {\n            if (!emitter.particles.length) {\n                continue;\n            }\n\n            this.setLayerProps(emitter);\n            this.setGeneralBuffers(emitter);\n\n            if (emitter.type & ParticleEmitter2FramesFlags.Tail) {\n                this.renderEmitterType(emitter, ParticleEmitter2FramesFlags.Tail);\n            }\n            if (emitter.type & ParticleEmitter2FramesFlags.Head) {\n                this.renderEmitterType(emitter, ParticleEmitter2FramesFlags.Head);\n            }\n        }\n\n        this.gl.disableVertexAttribArray(this.shaderProgramLocations.vertexPositionAttribute);\n        this.gl.disableVertexAttribArray(this.shaderProgramLocations.textureCoordAttribute);\n        this.gl.disableVertexAttribArray(this.shaderProgramLocations.colorAttribute);\n    }\n\n    private renderGPUEmitterType(pass: GPURenderPassEncoder, emitter: ParticleEmitterWrapper, type: ParticleEmitter2FramesFlags): void {\n        if (type === ParticleEmitter2FramesFlags.Tail) {\n            this.device.queue.writeBuffer(emitter.tailTexCoordGPUBuffer, 0, emitter.tailTexCoords);\n            pass.setVertexBuffer(1, emitter.tailTexCoordGPUBuffer);\n        } else {\n            this.device.queue.writeBuffer(emitter.headTexCoordGPUBuffer, 0, emitter.headTexCoords);\n            pass.setVertexBuffer(1, emitter.headTexCoordGPUBuffer);\n        }\n\n        if (type === ParticleEmitter2FramesFlags.Tail) {\n            this.device.queue.writeBuffer(emitter.tailVertexGPUBuffer, 0, emitter.tailVertices);\n            pass.setVertexBuffer(0, emitter.tailVertexGPUBuffer);\n        } else {\n            this.device.queue.writeBuffer(emitter.headVertexGPUBuffer, 0, emitter.headVertices);\n            pass.setVertexBuffer(0, emitter.headVertexGPUBuffer);\n        }\n\n        pass.drawIndexed(emitter.particles.length * 6);\n    }\n\n    public renderGPU (pass: GPURenderPassEncoder, mvMatrix: mat4, pMatrix: mat4): void {\n        const VSUniformsValues = new ArrayBuffer(128);\n        const VSUniformsViews = {\n            mvMatrix: new Float32Array(VSUniformsValues, 0, 16),\n            pMatrix: new Float32Array(VSUniformsValues, 64, 16)\n        };\n        VSUniformsViews.mvMatrix.set(mvMatrix);\n        VSUniformsViews.pMatrix.set(pMatrix);\n        this.device.queue.writeBuffer(this.gpuVSUniformsBuffer, 0, VSUniformsValues);\n\n        pass.setBindGroup(0, this.gpuVSUniformsBindGroup);\n\n        for (const emitter of this.emitters) {\n            if (!emitter.particles.length) {\n                continue;\n            }\n\n            const pipeline = this.gpuPipelines[emitter.props.FilterMode] || this.gpuPipelines[0];\n            pass.setPipeline(pipeline);\n\n            const textureID = emitter.props.TextureID;\n            const texture = this.rendererData.model.Textures[textureID];\n\n            const fsUniformsValues = new ArrayBuffer(32);\n            const fsUniformsViews = {\n                replaceableColor: new Float32Array(fsUniformsValues, 0, 3),\n                replaceableType: new Uint32Array(fsUniformsValues, 12, 1),\n                discardAlphaLevel: new Float32Array(fsUniformsValues, 16, 1),\n            };\n\n            fsUniformsViews.replaceableColor.set(this.rendererData.teamColor);\n            fsUniformsViews.replaceableType.set([texture.ReplaceableId || 0]);\n            if (emitter.props.FilterMode === ParticleEmitter2FilterMode.AlphaKey) {\n                fsUniformsViews.discardAlphaLevel.set([DISCARD_ALPHA_KEY_LEVEL]);\n            } else if (\n                emitter.props.FilterMode === ParticleEmitter2FilterMode.Modulate ||\n                emitter.props.FilterMode === ParticleEmitter2FilterMode.Modulate2x\n            ) {\n                fsUniformsViews.discardAlphaLevel.set([DISCARD_MODULATE_LEVEL]);\n            } else {\n                fsUniformsViews.discardAlphaLevel.set([0]);\n            }\n\n            if (!emitter.fsUniformsBuffer) {\n                emitter.fsUniformsBuffer = this.device.createBuffer({\n                    label: `particles fs uniforms ${emitter.index}`,\n                    size: 32,\n                    usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n                });\n            }\n\n            this.device.queue.writeBuffer(emitter.fsUniformsBuffer, 0, fsUniformsValues);\n\n            const fsUniformsBindGroup = this.device.createBindGroup({\n                label: `particles fs uniforms ${emitter.index}`,\n                layout: this.fsBindGroupLayout,\n                entries: [\n                    {\n                        binding: 0,\n                        resource: { buffer: emitter.fsUniformsBuffer }\n                    },\n                    {\n                        binding: 1,\n                        resource: this.rendererData.gpuSamplers[textureID]\n                    },\n                    {\n                        binding: 2,\n                        resource: (this.rendererData.gpuTextures[texture.Image] || this.rendererData.gpuEmptyTexture).createView()\n                    }\n                ]\n            });\n\n            pass.setBindGroup(1, fsUniformsBindGroup);\n\n            this.device.queue.writeBuffer(emitter.colorGPUBuffer, 0, emitter.colors);\n            this.device.queue.writeBuffer(emitter.indexGPUBuffer, 0, emitter.indices);\n            pass.setVertexBuffer(2, emitter.colorGPUBuffer);\n            pass.setIndexBuffer(emitter.indexGPUBuffer, 'uint16');\n\n            if (emitter.type & ParticleEmitter2FramesFlags.Tail) {\n                this.renderGPUEmitterType(pass, emitter, ParticleEmitter2FramesFlags.Tail);\n            }\n            if (emitter.type & ParticleEmitter2FramesFlags.Head) {\n                this.renderGPUEmitterType(pass, emitter, ParticleEmitter2FramesFlags.Head);\n            }\n        }\n    }\n\n    private updateEmitter (emitter: ParticleEmitterWrapper, delta: number): void {\n        const visibility = this.interp.animVectorVal(emitter.props.Visibility, 1);\n\n        if (visibility > 0) {\n            if (emitter.props.Squirt && typeof emitter.props.EmissionRate !== 'number') {\n                const interp = this.interp.findKeyframes(emitter.props.EmissionRate);\n\n                if (interp && interp.left && interp.left.Frame !== emitter.squirtFrame) {\n                    emitter.squirtFrame = interp.left.Frame;\n                    if (interp.left.Vector[0] > 0) {\n                        emitter.emission += interp.left.Vector[0] * 1000;\n                    }\n                }\n            } else {\n                const emissionRate = this.interp.animVectorVal(emitter.props.EmissionRate, 0);\n\n                emitter.emission += emissionRate * delta;\n            }\n\n            while (emitter.emission >= 1000) {\n                emitter.emission -= 1000;\n                emitter.particles.push(\n                    this.createParticle(emitter, this.rendererData.nodes[emitter.props.ObjectId].matrix)\n                );\n            }\n        }\n\n        if (emitter.particles.length) {\n            const updatedParticles = [];\n            for (const particle of emitter.particles) {\n                this.updateParticle(particle, delta);\n                if (particle.lifeSpan > 0) {\n                    updatedParticles.push(particle);\n                } else {\n                    this.particleStorage.push(particle);\n                }\n            }\n            emitter.particles = updatedParticles;\n\n            if (emitter.type & ParticleEmitter2FramesFlags.Head) {\n                if (emitter.props.Flags & ParticleEmitter2Flags.XYQuad) {\n                    vec3.set(this.particleBaseVectors[0], -1,  1, 0);\n                    vec3.set(this.particleBaseVectors[1], -1, -1, 0);\n                    vec3.set(this.particleBaseVectors[2],  1,  1, 0);\n                    vec3.set(this.particleBaseVectors[3],  1, -1, 0);\n                } else {\n                    vec3.set(this.particleBaseVectors[0], 0, -1,  1);\n                    vec3.set(this.particleBaseVectors[1], 0, -1, -1);\n                    vec3.set(this.particleBaseVectors[2], 0,  1,  1);\n                    vec3.set(this.particleBaseVectors[3], 0,  1, -1);\n\n                    for (let i = 0; i < 4; ++i) {\n                        vec3.transformQuat(this.particleBaseVectors[i], this.particleBaseVectors[i],\n                            this.rendererData.cameraQuat);\n                    }\n                }\n            }\n\n            this.resizeEmitterBuffers(emitter, emitter.particles.length);\n            for (let i = 0; i < emitter.particles.length; ++i) {\n                this.updateParticleBuffers(emitter.particles[i], i, emitter);\n            }\n        }\n    }\n\n    private createParticle (emitter: ParticleEmitterWrapper, emitterMatrix: mat4) {\n        let particle: Particle;\n\n        if (this.particleStorage.length) {\n            particle = this.particleStorage.pop();\n        } else {\n            particle = {\n                emitter: null,\n                pos: vec3.create(),\n                angle: 0,\n                speed: vec3.create(),\n                gravity: null,\n                lifeSpan: null\n            };\n        }\n\n        const width: number = this.interp.animVectorVal(emitter.props.Width, 0);\n        const length: number = this.interp.animVectorVal(emitter.props.Length, 0);\n        let speedScale: number = this.interp.animVectorVal(emitter.props.Speed, 0);\n        const variation: number = this.interp.animVectorVal(emitter.props.Variation, 0);\n        const latitude: number = degToRad(this.interp.animVectorVal(emitter.props.Latitude, 0));\n\n        particle.emitter = emitter;\n\n        particle.pos[0] = emitter.props.PivotPoint[0] + rand(-width, width);\n        particle.pos[1] = emitter.props.PivotPoint[1] + rand(-length, length);\n        particle.pos[2] = emitter.props.PivotPoint[2];\n        vec3.transformMat4(particle.pos, particle.pos, emitterMatrix);\n\n        if (variation > 0) {\n            speedScale *= 1 + rand(-variation, variation);\n        }\n\n        vec3.set(particle.speed, 0, 0, speedScale);\n        particle.angle = rand(0, Math.PI * 2);\n        vec3.rotateY(particle.speed, particle.speed, rotateCenter, rand(0, latitude));\n        vec3.rotateZ(particle.speed, particle.speed, rotateCenter, particle.angle);\n        if (emitter.props.Flags & ParticleEmitter2Flags.LineEmitter) {\n            particle.speed[0] = 0;\n        }\n        vec3.transformMat4(particle.speed, particle.speed, emitterMatrix);\n        // minus translation of emitterMatrix\n        particle.speed[0] -= emitterMatrix[12];\n        particle.speed[1] -= emitterMatrix[13];\n        particle.speed[2] -= emitterMatrix[14];\n\n        particle.gravity = this.interp.animVectorVal(emitter.props.Gravity, 0);\n\n        particle.lifeSpan = emitter.props.LifeSpan;\n\n        return particle;\n    }\n\n    private updateParticleBuffers (particle: Particle, index: number, emitter: ParticleEmitterWrapper): void {\n        const globalT: number = 1 - particle.lifeSpan / emitter.props.LifeSpan;\n        const firstHalf: boolean = globalT < emitter.props.Time;\n        let t: number;\n\n        if (firstHalf) {\n            t = globalT / emitter.props.Time;\n        } else {\n            t = (globalT - emitter.props.Time) / (1 - emitter.props.Time);\n        }\n\n        this.updateParticleVertices(particle, index, emitter, firstHalf, t);\n        this.updateParticleTexCoords(index, emitter, firstHalf, t);\n        this.updateParticleColor(index, emitter, firstHalf, t);\n    }\n\n    private updateParticleVertices (particle: Particle, index: number, emitter: ParticleEmitterWrapper,\n                                    firstHalf: boolean, t: number) {\n        let firstScale;\n        let secondScale;\n        let scale;\n\n        if (firstHalf) {\n            firstScale = emitter.props.ParticleScaling[0];\n            secondScale = emitter.props.ParticleScaling[1];\n        } else {\n            firstScale = emitter.props.ParticleScaling[1];\n            secondScale = emitter.props.ParticleScaling[2];\n        }\n\n        // eslint-disable-next-line prefer-const\n        scale = lerp(firstScale, secondScale, t);\n\n        if (emitter.type & ParticleEmitter2FramesFlags.Head) {\n            for (let i = 0; i < 4; ++i) {\n                emitter.headVertices[index * 12 + i * 3]     = this.particleBaseVectors[i][0] * scale;\n                emitter.headVertices[index * 12 + i * 3 + 1] = this.particleBaseVectors[i][1] * scale;\n                emitter.headVertices[index * 12 + i * 3 + 2] = this.particleBaseVectors[i][2] * scale;\n\n                if (emitter.props.Flags & ParticleEmitter2Flags.XYQuad) {\n                    const x = emitter.headVertices[index * 12 + i * 3];\n                    const y = emitter.headVertices[index * 12 + i * 3 + 1];\n                    emitter.headVertices[index * 12 + i * 3]     = x * Math.cos(particle.angle) -\n                        y * Math.sin(particle.angle);\n                    emitter.headVertices[index * 12 + i * 3 + 1] = x * Math.sin(particle.angle) +\n                        y * Math.cos(particle.angle);\n                }\n            }\n        }\n        if (emitter.type & ParticleEmitter2FramesFlags.Tail) {\n            tailPos[0] = -particle.speed[0] * emitter.props.TailLength;\n            tailPos[1] = -particle.speed[1] * emitter.props.TailLength;\n            tailPos[2] = -particle.speed[2] * emitter.props.TailLength;\n\n            vec3.cross(tailCross, particle.speed, this.rendererData.cameraPos);\n            vec3.normalize(tailCross, tailCross);\n            vec3.scale(tailCross, tailCross, scale);\n\n            emitter.tailVertices[index * 12]             =  tailCross[0];\n            emitter.tailVertices[index * 12         + 1] =  tailCross[1];\n            emitter.tailVertices[index * 12         + 2] =  tailCross[2];\n\n            emitter.tailVertices[index * 12 +     3]     = -tailCross[0];\n            emitter.tailVertices[index * 12 +     3 + 1] = -tailCross[1];\n            emitter.tailVertices[index * 12 +     3 + 2] = -tailCross[2];\n\n            emitter.tailVertices[index * 12 + 2 * 3]     =  tailCross[0] + tailPos[0];\n            emitter.tailVertices[index * 12 + 2 * 3 + 1] =  tailCross[1] + tailPos[1];\n            emitter.tailVertices[index * 12 + 2 * 3 + 2] =  tailCross[2] + tailPos[2];\n\n            emitter.tailVertices[index * 12 + 3 * 3]     = -tailCross[0] + tailPos[0];\n            emitter.tailVertices[index * 12 + 3 * 3 + 1] = -tailCross[1] + tailPos[1];\n            emitter.tailVertices[index * 12 + 3 * 3 + 2] = -tailCross[2] + tailPos[2];\n        }\n\n        for (let i = 0; i < 4; ++i) {\n            if (emitter.headVertices) {\n                emitter.headVertices[index * 12 + i * 3]     += particle.pos[0];\n                emitter.headVertices[index * 12 + i * 3 + 1] += particle.pos[1];\n                emitter.headVertices[index * 12 + i * 3 + 2] += particle.pos[2];\n            }\n            if (emitter.tailVertices) {\n                emitter.tailVertices[index * 12 + i * 3]     += particle.pos[0];\n                emitter.tailVertices[index * 12 + i * 3 + 1] += particle.pos[1];\n                emitter.tailVertices[index * 12 + i * 3 + 2] += particle.pos[2];\n            }\n        }\n    }\n\n    private updateParticleTexCoords (index: number, emitter: ParticleEmitterWrapper, firstHalf: boolean, t: number) {\n        if (emitter.type & ParticleEmitter2FramesFlags.Head) {\n            this.updateParticleTexCoordsByType(index, emitter, firstHalf, t, ParticleEmitter2FramesFlags.Head);\n        }\n        if (emitter.type & ParticleEmitter2FramesFlags.Tail) {\n            this.updateParticleTexCoordsByType(index, emitter, firstHalf, t, ParticleEmitter2FramesFlags.Tail);\n        }\n    }\n\n    private updateParticleTexCoordsByType (index: number, emitter: ParticleEmitterWrapper, firstHalf: boolean,\n                                           t: number, type: ParticleEmitter2FramesFlags) {\n        let uvAnim;\n        let texCoords;\n        if (type === ParticleEmitter2FramesFlags.Tail) {\n            uvAnim = firstHalf ? emitter.props.TailUVAnim : emitter.props.TailDecayUVAnim;\n            texCoords = emitter.tailTexCoords;\n        } else {\n            uvAnim = firstHalf ? emitter.props.LifeSpanUVAnim : emitter.props.DecayUVAnim;\n            texCoords = emitter.headTexCoords;\n        }\n        const firstFrame = uvAnim[0];\n        const secondFrame = uvAnim[1];\n        const frame = Math.round(lerp(firstFrame, secondFrame, t));\n        const texCoordX = frame % emitter.props.Columns;\n        const texCoordY = Math.floor(frame / emitter.props.Rows);\n        const cellWidth = 1 / emitter.props.Columns;\n        const cellHeight = 1 / emitter.props.Rows;\n\n        texCoords[index * 8] = texCoordX * cellWidth;\n        texCoords[index * 8 + 1] = texCoordY * cellHeight;\n\n        texCoords[index * 8 + 2] = texCoordX * cellWidth;\n        texCoords[index * 8 + 3] = (1 + texCoordY) * cellHeight;\n\n        texCoords[index * 8 + 4] = (1 + texCoordX) * cellWidth;\n        texCoords[index * 8 + 5] = texCoordY * cellHeight;\n\n        texCoords[index * 8 + 6] = (1 + texCoordX) * cellWidth;\n        texCoords[index * 8 + 7] = (1 + texCoordY) * cellHeight;\n    }\n\n    private updateParticleColor(index: number, emitter: ParticleEmitterWrapper, firstHalf: boolean, t: number) {\n        if (firstHalf) {\n            firstColor[0] = emitter.props.SegmentColor[0][0];\n            firstColor[1] = emitter.props.SegmentColor[0][1];\n            firstColor[2] = emitter.props.SegmentColor[0][2];\n            firstColor[3] = emitter.props.Alpha[0] / 255;\n\n            secondColor[0] = emitter.props.SegmentColor[1][0];\n            secondColor[1] = emitter.props.SegmentColor[1][1];\n            secondColor[2] = emitter.props.SegmentColor[1][2];\n            secondColor[3] = emitter.props.Alpha[1] / 255;\n        } else {\n            firstColor[0] = emitter.props.SegmentColor[1][0];\n            firstColor[1] = emitter.props.SegmentColor[1][1];\n            firstColor[2] = emitter.props.SegmentColor[1][2];\n            firstColor[3] = emitter.props.Alpha[1] / 255;\n\n            secondColor[0] = emitter.props.SegmentColor[2][0];\n            secondColor[1] = emitter.props.SegmentColor[2][1];\n            secondColor[2] = emitter.props.SegmentColor[2][2];\n            secondColor[3] = emitter.props.Alpha[2] / 255;\n        }\n\n        vec4.lerp(color, firstColor, secondColor, t);\n\n        for (let i = 0; i < 4; ++i) {\n            emitter.colors[index * 16 + i * 4]     = color[0];\n            emitter.colors[index * 16 + i * 4 + 1] = color[1];\n            emitter.colors[index * 16 + i * 4 + 2] = color[2];\n            emitter.colors[index * 16 + i * 4 + 3] = color[3];\n        }\n    }\n\n    private setLayerProps (emitter: ParticleEmitterWrapper): void {\n        if (emitter.props.FilterMode === ParticleEmitter2FilterMode.AlphaKey) {\n            this.gl.uniform1f(this.shaderProgramLocations.discardAlphaLevelUniform, DISCARD_ALPHA_KEY_LEVEL);\n        } else if (emitter.props.FilterMode === ParticleEmitter2FilterMode.Modulate ||\n            emitter.props.FilterMode === ParticleEmitter2FilterMode.Modulate2x) {\n                this.gl.uniform1f(this.shaderProgramLocations.discardAlphaLevelUniform, DISCARD_MODULATE_LEVEL);\n        } else {\n            this.gl.uniform1f(this.shaderProgramLocations.discardAlphaLevelUniform, 0.);\n        }\n\n        if (emitter.props.FilterMode === ParticleEmitter2FilterMode.Blend) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);\n            this.gl.depthMask(false);\n        } else if (emitter.props.FilterMode === ParticleEmitter2FilterMode.Additive) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (emitter.props.FilterMode === ParticleEmitter2FilterMode.AlphaKey) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (emitter.props.FilterMode === ParticleEmitter2FilterMode.Modulate) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.ZERO, this.gl.SRC_COLOR, this.gl.ZERO, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (emitter.props.FilterMode === ParticleEmitter2FilterMode.Modulate2x) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.DST_COLOR, this.gl.SRC_COLOR, this.gl.ZERO, this.gl.ONE);\n            this.gl.depthMask(false);\n        }\n\n        const texture = this.rendererData.model.Textures[emitter.props.TextureID];\n        if (texture.Image) {\n            this.gl.activeTexture(this.gl.TEXTURE0);\n            this.gl.bindTexture(this.gl.TEXTURE_2D, this.rendererData.textures[texture.Image]);\n            this.gl.uniform1i(this.shaderProgramLocations.samplerUniform, 0);\n            this.gl.uniform1f(this.shaderProgramLocations.replaceableTypeUniform, 0);\n        } else if (texture.ReplaceableId === 1 || texture.ReplaceableId === 2) {\n            this.gl.uniform3fv(this.shaderProgramLocations.replaceableColorUniform, this.rendererData.teamColor);\n            this.gl.uniform1f(this.shaderProgramLocations.replaceableTypeUniform, texture.ReplaceableId);\n        }\n    }\n\n    private setGeneralBuffers (emitter: ParticleEmitterWrapper): void {\n        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, emitter.colorBuffer);\n        this.gl.bufferData(this.gl.ARRAY_BUFFER, emitter.colors, this.gl.DYNAMIC_DRAW);\n        this.gl.vertexAttribPointer(this.shaderProgramLocations.colorAttribute, 4, this.gl.FLOAT, false, 0, 0);\n\n        this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, emitter.indexBuffer);\n        this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, emitter.indices, this.gl.DYNAMIC_DRAW);\n    }\n\n    private renderEmitterType (emitter: ParticleEmitterWrapper, type: ParticleEmitter2FramesFlags): void {\n        if (type === ParticleEmitter2FramesFlags.Tail) {\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, emitter.tailTexCoordBuffer);\n            this.gl.bufferData(this.gl.ARRAY_BUFFER, emitter.tailTexCoords, this.gl.DYNAMIC_DRAW);\n        } else {\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, emitter.headTexCoordBuffer);\n            this.gl.bufferData(this.gl.ARRAY_BUFFER, emitter.headTexCoords, this.gl.DYNAMIC_DRAW);\n        }\n        this.gl.vertexAttribPointer(this.shaderProgramLocations.textureCoordAttribute, 2, this.gl.FLOAT, false, 0, 0);\n\n        if (type === ParticleEmitter2FramesFlags.Tail) {\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, emitter.tailVertexBuffer);\n            this.gl.bufferData(this.gl.ARRAY_BUFFER, emitter.tailVertices, this.gl.DYNAMIC_DRAW);\n        } else {\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, emitter.headVertexBuffer);\n            this.gl.bufferData(this.gl.ARRAY_BUFFER, emitter.headVertices, this.gl.DYNAMIC_DRAW);\n        }\n        this.gl.vertexAttribPointer(this.shaderProgramLocations.vertexPositionAttribute, 3, this.gl.FLOAT, false, 0, 0);\n\n        this.gl.drawElements(this.gl.TRIANGLES, emitter.particles.length * 6, this.gl.UNSIGNED_SHORT, 0);\n    }\n}\n","export default \"attribute vec3 aVertexPosition;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\n\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void) {\\n    vec4 position = vec4(aVertexPosition, 1.0);\\n    gl_Position = uPMatrix * uMVMatrix * position;\\n    vTextureCoord = aTextureCoord;\\n}\\n\"","export default \"precision mediump float;\\n\\nvarying vec2 vTextureCoord;\\n\\nuniform sampler2D uSampler;\\nuniform vec3 uReplaceableColor;\\nuniform float uReplaceableType;\\nuniform float uDiscardAlphaLevel;\\nuniform vec4 uColor;\\n\\nfloat hypot (vec2 z) {\\n    float t;\\n    float x = abs(z.x);\\n    float y = abs(z.y);\\n    t = min(x, y);\\n    x = max(x, y);\\n    t = t / x;\\n    return (z.x == 0.0 && z.y == 0.0) ? 0.0 : x * sqrt(1.0 + t * t);\\n}\\n\\nvoid main(void) {\\n    vec2 coords = vec2(vTextureCoord.s, vTextureCoord.t);\\n    if (uReplaceableType == 0.) {\\n        gl_FragColor = texture2D(uSampler, coords);\\n    } else if (uReplaceableType == 1.) {\\n        gl_FragColor = vec4(uReplaceableColor, 1.0);\\n    } else if (uReplaceableType == 2.) {\\n        float dist = hypot(coords - vec2(0.5, 0.5)) * 2.;\\n        float truncateDist = clamp(1. - dist * 1.4, 0., 1.);\\n        float alpha = sin(truncateDist);\\n        gl_FragColor = vec4(uReplaceableColor * alpha, 1.0);\\n    }\\n    gl_FragColor *= uColor;\\n\\n    if (gl_FragColor[3] < uDiscardAlphaLevel) {\\n        discard;\\n    }\\n}\\n\"","export default \"struct VSUniforms {\\n    mvMatrix: mat4x4f,\\n    pMatrix: mat4x4f,\\n}\\n\\nstruct FSUniforms {\\n    replaceableColor: vec3f,\\n    replaceableType: u32,\\n    discardAlphaLevel: f32,\\n    color: vec4f,\\n}\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n@group(1) @binding(0) var<uniform> fsUniforms: FSUniforms;\\n@group(1) @binding(1) var fsUniformSampler: sampler;\\n@group(1) @binding(2) var fsUniformTexture: texture_2d<f32>;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n    @location(1) textureCoord: vec2f,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) textureCoord: vec2f,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    var position: vec4f = vec4f(in.vertexPosition, 1.0);\\n\\n    var out: VSOut;\\n    out.position = vsUniforms.pMatrix * vsUniforms.mvMatrix * position;\\n    out.textureCoord = in.textureCoord;\\n    return out;\\n}\\n\\nfn hypot(z: vec2f) -> f32 {\\n    var t: f32 = 0;\\n    var x: f32 = abs(z.x);\\n    let y: f32 = abs(z.y);\\n    t = min(x, y);\\n    x = max(x, y);\\n    t = t / x;\\n    if (z.x == 0.0 && z.y == 0.0) {\\n        return 0.0;\\n    }\\n    return x * sqrt(1.0 + t * t);\\n}\\n\\n@fragment fn fs(\\n    in: VSOut\\n) -> @location(0) vec4f {\\n    let texCoord: vec2f = in.textureCoord;\\n    var color: vec4f = vec4f(0.0);\\n\\n    if (fsUniforms.replaceableType == 0) {\\n        color = textureSample(fsUniformTexture, fsUniformSampler, texCoord);\\n    } else if (fsUniforms.replaceableType == 1) {\\n        color = vec4f(fsUniforms.replaceableColor, 1.0);\\n    } else if (fsUniforms.replaceableType == 2) {\\n        let dist: f32 = hypot(texCoord - vec2(0.5, 0.5)) * 2.;\\n        let truncateDist: f32 = clamp(1. - dist * 1.4, 0., 1.);\\n        let alpha: f32 = sin(truncateDist);\\n        color = vec4f(fsUniforms.replaceableColor * alpha, 1.0);\\n    }\\n\\n    color *= fsUniforms.color;\\n\\n    // hand-made alpha-test\\n    if (color.a < fsUniforms.discardAlphaLevel) {\\n        discard;\\n    }\\n\\n    return color;\\n}\\n\"","/// <reference types=\"vite/client\" />\n/// <reference types=\"@webgpu/types\" />\n\nimport {getShader} from './util';\nimport {RendererData} from './rendererData';\nimport {ModelInterp} from './modelInterp';\nimport {FilterMode, Layer, LayerShading, Material, RibbonEmitter} from '../model';\nimport {mat4, vec3} from 'gl-matrix';\nimport vertexShader from './shaders/webgl/ribbon.vs.glsl?raw';\nimport fragmentShader from './shaders/webgl/ribbon.fs.glsl?raw';\nimport ribbonShader from './shaders/webgpu/ribbons.wgsl?raw';\n\ninterface RibbonEmitterWrapper {\n    index: number;\n\n    emission: number;\n    props: RibbonEmitter;\n    capacity: number;\n    baseCapacity: number;\n    creationTimes: number[];\n\n    // xyz\n    vertices: Float32Array<ArrayBuffer>;\n    vertexBuffer: WebGLBuffer;\n    vertexGPUBuffer: GPUBuffer;\n    // xy\n    texCoords: Float32Array<ArrayBuffer>;\n    texCoordBuffer: WebGLBuffer;\n    texCoordGPUBuffer: GPUBuffer;\n\n    fsUnifrmsPerLayer: GPUBuffer[];\n}\n\nexport class RibbonsController {\n    private gl: WebGL2RenderingContext | WebGLRenderingContext;\n    private shaderProgram: WebGLProgram;\n    private vertexShader: WebGLShader;\n    private fragmentShader: WebGLShader;\n\n    private device: GPUDevice;\n    private gpuShaderModule: GPUShaderModule;\n    private gpuPipelineLayout: GPUPipelineLayout;\n    private gpuPipelines: GPURenderPipeline[];\n    private vsBindGroupLayout: GPUBindGroupLayout | null;\n    private fsBindGroupLayout: GPUBindGroupLayout | null;\n    private gpuVSUniformsBuffer: GPUBuffer;\n    private gpuVSUniformsBindGroup: GPUBindGroup;\n\n    private shaderProgramLocations: {\n        vertexPositionAttribute: number,\n        textureCoordAttribute: number,\n        pMatrixUniform: WebGLUniformLocation | null,\n        mvMatrixUniform: WebGLUniformLocation | null,\n        samplerUniform: WebGLUniformLocation | null,\n        replaceableColorUniform: WebGLUniformLocation | null,\n        replaceableTypeUniform: WebGLUniformLocation | null,\n        discardAlphaLevelUniform: WebGLUniformLocation | null,\n        colorUniform: WebGLUniformLocation | null\n    };\n\n    private interp: ModelInterp;\n    private rendererData: RendererData;\n    private emitters: RibbonEmitterWrapper[];\n\n    constructor (interp: ModelInterp, rendererData: RendererData) {\n        this.shaderProgramLocations = {\n            vertexPositionAttribute: null,\n            textureCoordAttribute: null,\n            pMatrixUniform: null,\n            mvMatrixUniform: null,\n            samplerUniform: null,\n            replaceableColorUniform: null,\n            replaceableTypeUniform: null,\n            discardAlphaLevelUniform: null,\n            colorUniform: null\n        };\n\n        this.interp = interp;\n        this.rendererData = rendererData;\n        this.emitters = [];\n\n        if (rendererData.model.RibbonEmitters.length) {\n            for (let i = 0; i < rendererData.model.RibbonEmitters.length; ++i) {\n                const ribbonEmitter = rendererData.model.RibbonEmitters[i];\n\n                const emitter: RibbonEmitterWrapper = {\n                    index: i,\n\n                    emission: 0,\n                    props: ribbonEmitter,\n                    capacity: 0,\n                    baseCapacity: 0,\n                    creationTimes: [],\n                    vertices: null,\n                    vertexBuffer: null,\n                    vertexGPUBuffer: null,\n                    texCoords: null,\n                    texCoordBuffer: null,\n                    texCoordGPUBuffer: null,\n                    fsUnifrmsPerLayer: []\n                };\n\n                emitter.baseCapacity = Math.ceil(\n                    ModelInterp.maxAnimVectorVal(emitter.props.EmissionRate) * emitter.props.LifeSpan\n                ) + 1; // extra points\n\n                this.emitters.push(emitter);\n            }\n        }\n    }\n\n    public destroy (): void {\n        if (this.shaderProgram) {\n            if (this.vertexShader) {\n                this.gl.detachShader(this.shaderProgram, this.vertexShader);\n                this.gl.deleteShader(this.vertexShader);\n                this.vertexShader = null;\n            }\n            if (this.fragmentShader) {\n                this.gl.detachShader(this.shaderProgram, this.fragmentShader);\n                this.gl.deleteShader(this.fragmentShader);\n                this.fragmentShader = null;\n            }\n            this.gl.deleteProgram(this.shaderProgram);\n            this.shaderProgram = null;\n        }\n        if (this.gpuVSUniformsBuffer) {\n            this.gpuVSUniformsBuffer.destroy();\n            this.gpuVSUniformsBuffer = null;\n        }\n        for (const emitter of this.emitters) {\n            for (const buffer of emitter.fsUnifrmsPerLayer) {\n                buffer.destroy();\n            }\n        }\n        this.emitters = [];\n    }\n\n    public initGL (glContext: WebGLRenderingContext): void {\n        this.gl = glContext;\n\n        this.initShaders();\n    }\n\n    public initGPUDevice (device: GPUDevice): void {\n        this.device = device;\n\n        this.gpuShaderModule = device.createShaderModule({\n            label: 'ribbons shader module',\n            code: ribbonShader\n        });\n\n        this.vsBindGroupLayout = this.device.createBindGroupLayout({\n            label: 'ribbons vs bind group layout',\n            entries: [ {\n                binding: 0,\n                visibility: GPUShaderStage.VERTEX,\n                buffer: {\n                    type: 'uniform',\n                    hasDynamicOffset: false,\n                    minBindingSize: 128\n                }\n            }] as const\n        });\n        this.fsBindGroupLayout = this.device.createBindGroupLayout({\n            label: 'ribbons bind group layout2',\n            entries: [\n                {\n                    binding: 0,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    buffer: {\n                    type: 'uniform',\n                        hasDynamicOffset: false,\n                        minBindingSize: 48\n                    }\n                },\n                {\n                    binding: 1,\n                    visibility: GPUShaderStage.FRAGMENT,\n                        sampler: {\n                        type: 'filtering'\n                    }\n                },\n                {\n                    binding: 2,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    texture: {\n                        sampleType: 'float',\n                        viewDimension: \"2d\",\n                        multisampled: false\n                    }\n                }\n            ] as const\n        });\n\n        this.gpuPipelineLayout = this.device.createPipelineLayout({\n            label: 'ribbons pipeline layout',\n            bindGroupLayouts: [\n                this.vsBindGroupLayout,\n                this.fsBindGroupLayout\n            ]\n        });\n\n        const createPipeline = (name: string, blend: GPUBlendState, depth: GPUDepthStencilState) => {\n            return device.createRenderPipeline({\n                label: `ribbons pipeline ${name}`,\n                layout: this.gpuPipelineLayout,\n                vertex: {\n                    module: this.gpuShaderModule,\n                    buffers: [{\n                        arrayStride: 12,\n                        attributes: [{\n                            shaderLocation: 0,\n                            offset: 0,\n                            format: 'float32x3' as const\n                        }]\n                    }, {\n                        arrayStride: 8,\n                        attributes: [{\n                            shaderLocation: 1,\n                            offset: 0,\n                            format: 'float32x2' as const\n                        }]\n                    }]\n                },\n                fragment: {\n                    module: this.gpuShaderModule,\n                    targets: [{\n                        format: navigator.gpu.getPreferredCanvasFormat(),\n                        blend\n                    }]\n                },\n                depthStencil: depth,\n                primitive: {\n                    topology: 'triangle-strip'\n                }\n            });\n        };\n\n        this.gpuPipelines = [\n            createPipeline('none', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'one',\n                    dstFactor: 'zero'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'one',\n                    dstFactor: 'zero'\n                }\n            }, {\n                depthWriteEnabled: true,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n            createPipeline('transparent', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'src-alpha',\n                    dstFactor: 'one-minus-src-alpha'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'one',\n                    dstFactor: 'one-minus-src-alpha'\n                }\n            }, {\n                depthWriteEnabled: true,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n            createPipeline('blend', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'src-alpha',\n                    dstFactor: 'one-minus-src-alpha'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'one',\n                    dstFactor: 'one-minus-src-alpha'\n                }\n            }, {\n                depthWriteEnabled: false,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n            createPipeline('additive', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'src',\n                    dstFactor: 'one'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'src',\n                    dstFactor: 'one'\n                }\n            }, {\n                depthWriteEnabled: false,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n            createPipeline('addAlpha', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'src-alpha',\n                    dstFactor: 'one'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'src-alpha',\n                    dstFactor: 'one'\n                }\n            }, {\n                depthWriteEnabled: false,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n            createPipeline('modulate', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'zero',\n                    dstFactor: 'src'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'zero',\n                    dstFactor: 'one'\n                }\n            }, {\n                depthWriteEnabled: false,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            }),\n            createPipeline('modulate2x', {\n                color: {\n                    operation: 'add',\n                    srcFactor: 'dst',\n                    dstFactor: 'src'\n                },\n                alpha: {\n                    operation: 'add',\n                    srcFactor: 'zero',\n                    dstFactor: 'one'\n                }\n            }, {\n                depthWriteEnabled: false,\n                depthCompare: 'less-equal',\n                format: 'depth24plus'\n            })\n        ];\n\n        this.gpuVSUniformsBuffer = this.device.createBuffer({\n            label: 'ribbons vs uniforms',\n            size: 128,\n            usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n        });\n        this.gpuVSUniformsBindGroup = this.device.createBindGroup({\n            layout: this.vsBindGroupLayout,\n            entries: [\n                {\n                    binding: 0,\n                    resource: { buffer: this.gpuVSUniformsBuffer }\n                }\n            ]\n        });\n    }\n\n    public update (delta: number): void {\n        for (const emitter of this.emitters) {\n            this.updateEmitter(emitter, delta);\n        }\n    }\n\n    public render (mvMatrix: mat4, pMatrix: mat4): void {\n        this.gl.useProgram(this.shaderProgram);\n\n        this.gl.uniformMatrix4fv(this.shaderProgramLocations.pMatrixUniform, false, pMatrix);\n        this.gl.uniformMatrix4fv(this.shaderProgramLocations.mvMatrixUniform, false, mvMatrix);\n\n        this.gl.enableVertexAttribArray(this.shaderProgramLocations.vertexPositionAttribute);\n        this.gl.enableVertexAttribArray(this.shaderProgramLocations.textureCoordAttribute);\n\n        for (const emitter of this.emitters) {\n            if (emitter.creationTimes.length < 2) {\n                continue;\n            }\n\n            this.gl.uniform4f(\n                this.shaderProgramLocations.colorUniform,\n                emitter.props.Color[0], emitter.props.Color[1], emitter.props.Color[2],\n                this.interp.animVectorVal(emitter.props.Alpha, 1)\n            );\n\n            this.setGeneralBuffers(emitter);\n            const materialID: number = emitter.props.MaterialID;\n            const material: Material = this.rendererData.model.Materials[materialID];\n            for (let j = 0; j < material.Layers.length; ++j) {\n                this.setLayerProps(material.Layers[j], this.rendererData.materialLayerTextureID[materialID][j]);\n                this.renderEmitter(emitter);\n            }\n        }\n\n        this.gl.disableVertexAttribArray(this.shaderProgramLocations.vertexPositionAttribute);\n        this.gl.disableVertexAttribArray(this.shaderProgramLocations.textureCoordAttribute);\n    }\n\n    public renderGPU (pass: GPURenderPassEncoder, mvMatrix: mat4, pMatrix: mat4): void {\n        const VSUniformsValues = new ArrayBuffer(128);\n        const VSUniformsViews = {\n            mvMatrix: new Float32Array(VSUniformsValues, 0, 16),\n            pMatrix: new Float32Array(VSUniformsValues, 64, 16)\n        };\n        VSUniformsViews.mvMatrix.set(mvMatrix);\n        VSUniformsViews.pMatrix.set(pMatrix);\n        this.device.queue.writeBuffer(this.gpuVSUniformsBuffer, 0, VSUniformsValues);\n\n        for (const emitter of this.emitters) {\n            if (emitter.creationTimes.length < 2) {\n                continue;\n            }\n\n            this.device.queue.writeBuffer(emitter.vertexGPUBuffer, 0, emitter.vertices);\n            this.device.queue.writeBuffer(emitter.texCoordGPUBuffer, 0, emitter.texCoords);\n\n            pass.setVertexBuffer(0, emitter.vertexGPUBuffer);\n            pass.setVertexBuffer(1, emitter.texCoordGPUBuffer);\n\n            pass.setBindGroup(0, this.gpuVSUniformsBindGroup);\n\n            const materialID: number = emitter.props.MaterialID;\n            const material: Material = this.rendererData.model.Materials[materialID];\n\n            for (let j = 0; j < material.Layers.length; ++j) {\n                const textureID = this.rendererData.materialLayerTextureID[materialID][j];\n                const texture = this.rendererData.model.Textures[textureID];\n                const layer = material.Layers[j];\n\n                const pipeline = this.gpuPipelines[layer.FilterMode] || this.gpuPipelines[0];\n                pass.setPipeline(pipeline);\n\n                const fsUniformsValues = new ArrayBuffer(48);\n                const fsUniformsViews = {\n                    replaceableColor: new Float32Array(fsUniformsValues, 0, 3),\n                    replaceableType: new Uint32Array(fsUniformsValues, 12, 1),\n                    discardAlphaLevel: new Float32Array(fsUniformsValues, 16, 1),\n                    color: new Float32Array(fsUniformsValues, 32, 4),\n                };\n\n                fsUniformsViews.replaceableColor.set(this.rendererData.teamColor);\n                fsUniformsViews.replaceableType.set([texture.ReplaceableId || 0]);\n                fsUniformsViews.discardAlphaLevel.set([layer.FilterMode === FilterMode.Transparent ? .75 : 0]);\n                fsUniformsViews.color.set([\n                    emitter.props.Color[0],\n                    emitter.props.Color[1],\n                    emitter.props.Color[2],\n                    this.interp.animVectorVal(emitter.props.Alpha, 1)\n                ]);\n\n                if (!emitter.fsUnifrmsPerLayer[j]) {\n                    emitter.fsUnifrmsPerLayer[j] = this.device.createBuffer({\n                        label: `ribbons fs uniforms ${emitter.index} layer ${j}`,\n                        size: 48,\n                        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n                    });\n                }\n                const fsUniformsBuffer = emitter.fsUnifrmsPerLayer[j];\n\n                this.device.queue.writeBuffer(fsUniformsBuffer, 0, fsUniformsValues);\n\n                const fsUniformsBindGroup = this.device.createBindGroup({\n                    label: `ribbons fs uniforms ${emitter.index}`,\n                    layout: this.fsBindGroupLayout,\n                    entries: [\n                        {\n                            binding: 0,\n                            resource: { buffer: fsUniformsBuffer }\n                        },\n                        {\n                            binding: 1,\n                            resource: this.rendererData.gpuSamplers[textureID]\n                        },\n                        {\n                            binding: 2,\n                            resource: (this.rendererData.gpuTextures[texture.Image] || this.rendererData.gpuEmptyTexture).createView()\n                        }\n                    ]\n                });\n\n                pass.setBindGroup(1, fsUniformsBindGroup);\n\n                pass.draw(emitter.creationTimes.length * 2);\n            }\n        }\n    }\n\n    private initShaders (): void {\n        const vertex = this.vertexShader = getShader(this.gl, vertexShader, this.gl.VERTEX_SHADER);\n        const fragment = this.fragmentShader = getShader(this.gl, fragmentShader, this.gl.FRAGMENT_SHADER);\n\n        const shaderProgram = this.shaderProgram = this.gl.createProgram();\n        this.gl.attachShader(shaderProgram, vertex);\n        this.gl.attachShader(shaderProgram, fragment);\n        this.gl.linkProgram(shaderProgram);\n\n        if (!this.gl.getProgramParameter(shaderProgram, this.gl.LINK_STATUS)) {\n            alert('Could not initialise shaders');\n        }\n\n        this.gl.useProgram(shaderProgram);\n\n        this.shaderProgramLocations.vertexPositionAttribute =\n            this.gl.getAttribLocation(shaderProgram, 'aVertexPosition');\n        this.shaderProgramLocations.textureCoordAttribute =\n            this.gl.getAttribLocation(shaderProgram, 'aTextureCoord');\n\n        this.shaderProgramLocations.pMatrixUniform = this.gl.getUniformLocation(shaderProgram, 'uPMatrix');\n        this.shaderProgramLocations.mvMatrixUniform = this.gl.getUniformLocation(shaderProgram, 'uMVMatrix');\n        this.shaderProgramLocations.samplerUniform = this.gl.getUniformLocation(shaderProgram, 'uSampler');\n        this.shaderProgramLocations.replaceableColorUniform =\n            this.gl.getUniformLocation(shaderProgram, 'uReplaceableColor');\n        this.shaderProgramLocations.replaceableTypeUniform =\n            this.gl.getUniformLocation(shaderProgram, 'uReplaceableType');\n        this.shaderProgramLocations.discardAlphaLevelUniform =\n            this.gl.getUniformLocation(shaderProgram, 'uDiscardAlphaLevel');\n        this.shaderProgramLocations.colorUniform =\n            this.gl.getUniformLocation(shaderProgram, 'uColor');\n    }\n\n    private resizeEmitterBuffers (emitter: RibbonEmitterWrapper, size: number): void {\n        if (size <= emitter.capacity) {\n            return;\n        }\n\n        size = Math.min(size, emitter.baseCapacity);\n\n        const vertices = new Float32Array(size * 2 * 3);  // 2 vertices * xyz\n        const texCoords = new Float32Array(size * 2 * 2); // 2 vertices * xy\n\n        if (emitter.vertices) {\n            vertices.set(emitter.vertices);\n        }\n\n        emitter.vertices = vertices;\n        emitter.texCoords = texCoords;\n\n        emitter.capacity = size;\n\n        if (this.gl) {\n            if (!emitter.vertexBuffer) {\n                emitter.vertexBuffer = this.gl.createBuffer();\n                emitter.texCoordBuffer = this.gl.createBuffer();\n            }\n        } else if (this.device) {\n            emitter.vertexGPUBuffer?.destroy();\n            emitter.texCoordGPUBuffer?.destroy();\n\n            emitter.vertexGPUBuffer = this.device.createBuffer({\n                label: `ribbon vertex buffer ${emitter.index}`,\n                size: vertices.byteLength,\n                usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST\n            });\n            emitter.texCoordGPUBuffer = this.device.createBuffer({\n                label: `ribbon texCoord buffer ${emitter.index}`,\n                size: texCoords.byteLength,\n                usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST\n            });\n        }\n    }\n\n    private updateEmitter (emitter: RibbonEmitterWrapper, delta: number): void {\n        const now = Date.now();\n        const visibility = this.interp.animVectorVal(emitter.props.Visibility, 0);\n\n        if (visibility > 0) {\n            const emissionRate = emitter.props.EmissionRate;\n\n            emitter.emission += emissionRate * delta;\n\n            if (emitter.emission >= 1000) {\n                // only once per tick\n                emitter.emission = emitter.emission % 1000;\n\n                if (emitter.creationTimes.length + 1 > emitter.capacity) {\n                    this.resizeEmitterBuffers(emitter, emitter.creationTimes.length + 1);\n                }\n\n                this.appendVertices(emitter);\n\n                emitter.creationTimes.push(now);\n            }\n        }\n\n        if (emitter.creationTimes.length) {\n            while (emitter.creationTimes[0] + emitter.props.LifeSpan * 1000 < now) {\n                emitter.creationTimes.shift();\n                for (let i = 0; i + 6 + 5 < emitter.vertices.length; i += 6) {\n                    emitter.vertices[i]     = emitter.vertices[i + 6];\n                    emitter.vertices[i + 1] = emitter.vertices[i + 7];\n                    emitter.vertices[i + 2] = emitter.vertices[i + 8];\n                    emitter.vertices[i + 3] = emitter.vertices[i + 9];\n                    emitter.vertices[i + 4] = emitter.vertices[i + 10];\n                    emitter.vertices[i + 5] = emitter.vertices[i + 11];\n                }\n            }\n        }\n\n        // still exists\n        if (emitter.creationTimes.length) {\n            this.updateEmitterTexCoords(emitter, now);\n        }\n    }\n\n    private appendVertices (emitter: RibbonEmitterWrapper): void {\n        const first: vec3 = vec3.clone(emitter.props.PivotPoint as vec3);\n        const second: vec3 = vec3.clone(emitter.props.PivotPoint as vec3);\n\n        first[1] -= this.interp.animVectorVal(emitter.props.HeightBelow, 0);\n        second[1] += this.interp.animVectorVal(emitter.props.HeightAbove, 0);\n\n        const emitterMatrix: mat4 = this.rendererData.nodes[emitter.props.ObjectId].matrix;\n        vec3.transformMat4(first, first, emitterMatrix);\n        vec3.transformMat4(second, second, emitterMatrix);\n\n        const currentSize = emitter.creationTimes.length;\n        emitter.vertices[currentSize * 6]     = first[0];\n        emitter.vertices[currentSize * 6 + 1] = first[1];\n        emitter.vertices[currentSize * 6 + 2] = first[2];\n        emitter.vertices[currentSize * 6 + 3] = second[0];\n        emitter.vertices[currentSize * 6 + 4] = second[1];\n        emitter.vertices[currentSize * 6 + 5] = second[2];\n    }\n\n    private updateEmitterTexCoords (emitter: RibbonEmitterWrapper, now: number): void {\n        for (let i = 0; i < emitter.creationTimes.length; ++i) {\n            let relativePos = (now - emitter.creationTimes[i]) / (emitter.props.LifeSpan * 1000);\n            const textureSlot = this.interp.animVectorVal(emitter.props.TextureSlot, 0);\n\n            const texCoordX = textureSlot % emitter.props.Columns;\n            const texCoordY = Math.floor(textureSlot / emitter.props.Rows);\n            const cellWidth = 1 / emitter.props.Columns;\n            const cellHeight = 1 / emitter.props.Rows;\n\n            relativePos = texCoordX * cellWidth + relativePos * cellWidth;\n\n            emitter.texCoords[i * 2 * 2]     = relativePos;\n            emitter.texCoords[i * 2 * 2 + 1] = texCoordY * cellHeight;\n            emitter.texCoords[i * 2 * 2 + 2] = relativePos;\n            emitter.texCoords[i * 2 * 2 + 3] = (1 + texCoordY) * cellHeight;\n        }\n    }\n\n    private setLayerProps (layer: Layer, textureID: number): void {\n        const texture = this.rendererData.model.Textures[textureID];\n\n        if (layer.Shading & LayerShading.TwoSided) {\n            this.gl.disable(this.gl.CULL_FACE);\n        } else {\n            this.gl.enable(this.gl.CULL_FACE);\n        }\n\n        if (layer.FilterMode === FilterMode.Transparent) {\n            this.gl.uniform1f(this.shaderProgramLocations.discardAlphaLevelUniform, 0.75);\n        } else {\n            this.gl.uniform1f(this.shaderProgramLocations.discardAlphaLevelUniform, 0.);\n        }\n\n        if (layer.FilterMode === FilterMode.None) {\n            this.gl.disable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            // this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);\n            this.gl.depthMask(true);\n        } else if (layer.FilterMode === FilterMode.Transparent) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);\n            this.gl.depthMask(true);\n        } else if (layer.FilterMode === FilterMode.Blend) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);\n            this.gl.depthMask(false);\n        } else if (layer.FilterMode === FilterMode.Additive) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFunc(this.gl.SRC_COLOR, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (layer.FilterMode === FilterMode.AddAlpha) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (layer.FilterMode === FilterMode.Modulate) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.ZERO, this.gl.SRC_COLOR, this.gl.ZERO, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (layer.FilterMode === FilterMode.Modulate2x) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.DST_COLOR, this.gl.SRC_COLOR, this.gl.ZERO, this.gl.ONE);\n            this.gl.depthMask(false);\n        }\n\n        if (texture.Image) {\n            this.gl.activeTexture(this.gl.TEXTURE0);\n            this.gl.bindTexture(this.gl.TEXTURE_2D, this.rendererData.textures[texture.Image]);\n            this.gl.uniform1i(this.shaderProgramLocations.samplerUniform, 0);\n            this.gl.uniform1f(this.shaderProgramLocations.replaceableTypeUniform, 0);\n        } else if (texture.ReplaceableId === 1 || texture.ReplaceableId === 2) {\n            this.gl.uniform3fv(this.shaderProgramLocations.replaceableColorUniform, this.rendererData.teamColor);\n            this.gl.uniform1f(this.shaderProgramLocations.replaceableTypeUniform, texture.ReplaceableId);\n        }\n\n        if (layer.Shading & LayerShading.NoDepthTest) {\n            this.gl.disable(this.gl.DEPTH_TEST);\n        }\n        if (layer.Shading & LayerShading.NoDepthSet) {\n            this.gl.depthMask(false);\n        }\n\n        /*if (typeof layer.TVertexAnimId === 'number') {\n            let anim: TVertexAnim = this.rendererData.model.TextureAnims[layer.TVertexAnimId];\n            let translationRes = this.interp.vec3(translation, anim.Translation);\n            let rotationRes = this.interp.quat(rotation, anim.Rotation);\n            let scalingRes = this.interp.vec3(scaling, anim.Scaling);\n            mat4.fromRotationTranslationScale(\n                texCoordMat4,\n                rotationRes || defaultRotation,\n                translationRes || defaultTranslation,\n                scalingRes || defaultScaling\n            );\n            mat3.set(\n                texCoordMat3,\n                texCoordMat4[0], texCoordMat4[1], 0,\n                texCoordMat4[4], texCoordMat4[5], 0,\n                texCoordMat4[12], texCoordMat4[13], 0\n            );\n\n            this.gl.uniformMatrix3fv(this.shaderProgramLocations.tVertexAnimUniform, false, texCoordMat3);\n        } else {\n            this.gl.uniformMatrix3fv(this.shaderProgramLocations.tVertexAnimUniform, false, identifyMat3);\n        }*/\n    }\n\n    private setGeneralBuffers (emitter: RibbonEmitterWrapper): void {\n        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, emitter.texCoordBuffer);\n        this.gl.bufferData(this.gl.ARRAY_BUFFER, emitter.texCoords, this.gl.DYNAMIC_DRAW);\n        this.gl.vertexAttribPointer(this.shaderProgramLocations.textureCoordAttribute, 2, this.gl.FLOAT, false, 0, 0);\n\n        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, emitter.vertexBuffer);\n        this.gl.bufferData(this.gl.ARRAY_BUFFER, emitter.vertices, this.gl.DYNAMIC_DRAW);\n        this.gl.vertexAttribPointer(this.shaderProgramLocations.vertexPositionAttribute, 3, this.gl.FLOAT, false, 0, 0);\n    }\n\n    private renderEmitter (emitter: RibbonEmitterWrapper): void {\n        this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, emitter.creationTimes.length * 2);\n    }\n}\n","export default \"attribute vec3 aVertexPosition;\\nattribute vec3 aNormal;\\nattribute vec2 aTextureCoord;\\nattribute vec4 aGroup;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\nuniform mat4 uNodesMatrices[${MAX_NODES}];\\n\\nvarying vec3 vNormal;\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void) {\\n    vec4 position = vec4(aVertexPosition, 1.0);\\n    int count = 1;\\n    vec4 sum = uNodesMatrices[int(aGroup[0])] * position;\\n\\n    if (aGroup[1] < ${MAX_NODES}.) {\\n        sum += uNodesMatrices[int(aGroup[1])] * position;\\n        count += 1;\\n    }\\n    if (aGroup[2] < ${MAX_NODES}.) {\\n        sum += uNodesMatrices[int(aGroup[2])] * position;\\n        count += 1;\\n    }\\n    if (aGroup[3] < ${MAX_NODES}.) {\\n        sum += uNodesMatrices[int(aGroup[3])] * position;\\n        count += 1;\\n    }\\n    sum.xyz /= float(count);\\n    sum.w = 1.;\\n    position = sum;\\n\\n    gl_Position = uPMatrix * uMVMatrix * position;\\n    vTextureCoord = aTextureCoord;\\n    vNormal = aNormal;\\n}\"","export default \"attribute vec3 aVertexPosition;\\nattribute vec3 aNormal;\\nattribute vec2 aTextureCoord;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\n\\nvarying vec3 vNormal;\\nvarying vec2 vTextureCoord;\\n\\nvoid main(void) {\\n    vec4 position = vec4(aVertexPosition, 1.0);\\n    gl_Position = uPMatrix * uMVMatrix * position;\\n    vTextureCoord = aTextureCoord;\\n    vNormal = aNormal;\\n}\"","export default \"precision mediump float;\\n\\nvarying vec3 vNormal;\\nvarying vec2 vTextureCoord;\\n\\nuniform sampler2D uSampler;\\nuniform vec3 uReplaceableColor;\\nuniform float uReplaceableType;\\nuniform float uDiscardAlphaLevel;\\nuniform mat3 uTVertexAnim;\\nuniform float uWireframe;\\n\\nfloat hypot (vec2 z) {\\n    float t;\\n    float x = abs(z.x);\\n    float y = abs(z.y);\\n    t = min(x, y);\\n    x = max(x, y);\\n    t = t / x;\\n    return (z.x == 0.0 && z.y == 0.0) ? 0.0 : x * sqrt(1.0 + t * t);\\n}\\n\\nvoid main(void) {\\n    if (uWireframe > 0.) {\\n        gl_FragColor = vec4(1.);\\n        return;\\n    }\\n\\n    vec2 texCoord = (uTVertexAnim * vec3(vTextureCoord.s, vTextureCoord.t, 1.)).st;\\n\\n    if (uReplaceableType == 0.) {\\n        gl_FragColor = texture2D(uSampler, texCoord);\\n    } else if (uReplaceableType == 1.) {\\n        gl_FragColor = vec4(uReplaceableColor, 1.0);\\n    } else if (uReplaceableType == 2.) {\\n        float dist = hypot(texCoord - vec2(0.5, 0.5)) * 2.;\\n        float truncateDist = clamp(1. - dist * 1.4, 0., 1.);\\n        float alpha = sin(truncateDist);\\n        gl_FragColor = vec4(uReplaceableColor * alpha, 1.0);\\n    }\\n\\n    // hand-made alpha-test\\n    if (gl_FragColor[3] < uDiscardAlphaLevel) {\\n        discard;\\n    }\\n}\\n\"","export default \"attribute vec3 aVertexPosition;\\nattribute vec3 aNormal;\\nattribute vec2 aTextureCoord;\\nattribute vec4 aSkin;\\nattribute vec4 aBoneWeight;\\nattribute vec4 aTangent;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\nuniform mat4 uNodesMatrices[${MAX_NODES}];\\n\\nvarying vec3 vNormal;\\nvarying vec3 vTangent;\\nvarying vec3 vBinormal;\\nvarying vec2 vTextureCoord;\\nvarying mat3 vTBN;\\nvarying vec3 vFragPos;\\n\\nvoid main(void) {\\n    vec4 position = vec4(aVertexPosition, 1.0);\\n    mat4 sum;\\n\\n    // sum += uNodesMatrices[int(aSkin[0])] * 1.;\\n    sum += uNodesMatrices[int(aSkin[0])] * aBoneWeight[0];\\n    sum += uNodesMatrices[int(aSkin[1])] * aBoneWeight[1];\\n    sum += uNodesMatrices[int(aSkin[2])] * aBoneWeight[2];\\n    sum += uNodesMatrices[int(aSkin[3])] * aBoneWeight[3];\\n\\n    mat3 rotation = mat3(sum);\\n\\n    position = sum * position;\\n    position.w = 1.;\\n\\n    gl_Position = uPMatrix * uMVMatrix * position;\\n    vTextureCoord = aTextureCoord;\\n\\n    vec3 normal = aNormal;\\n    vec3 tangent = aTangent.xyz;\\n\\n    // https://learnopengl.com/Advanced-Lighting/Normal-Mapping\\n    tangent = normalize(tangent - dot(tangent, normal) * normal);\\n\\n    vec3 binormal = cross(normal, tangent) * aTangent.w;\\n\\n    normal = normalize(rotation * normal);\\n    tangent = normalize(rotation * tangent);\\n    binormal = normalize(rotation * binormal);\\n\\n    vNormal = normal;\\n    vTangent = tangent;\\n    vBinormal = binormal;\\n\\n    vTBN = mat3(tangent, binormal, normal);\\n\\n    vFragPos = position.xyz;\\n}\"","export default \"#version 300 es\\nin vec3 aVertexPosition;\\nin vec3 aNormal;\\nin vec2 aTextureCoord;\\nin vec4 aSkin;\\nin vec4 aBoneWeight;\\nin vec4 aTangent;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\nuniform mat4 uNodesMatrices[${MAX_NODES}];\\n\\nout vec3 vNormal;\\nout vec3 vTangent;\\nout vec3 vBinormal;\\nout vec2 vTextureCoord;\\nout mat3 vTBN;\\nout vec3 vFragPos;\\n\\nvoid main(void) {\\n    vec4 position = vec4(aVertexPosition, 1.0);\\n    mat4 sum;\\n\\n    // sum += uNodesMatrices[int(aSkin[0])] * 1.;\\n    sum += uNodesMatrices[int(aSkin[0])] * aBoneWeight[0];\\n    sum += uNodesMatrices[int(aSkin[1])] * aBoneWeight[1];\\n    sum += uNodesMatrices[int(aSkin[2])] * aBoneWeight[2];\\n    sum += uNodesMatrices[int(aSkin[3])] * aBoneWeight[3];\\n\\n    mat3 rotation = mat3(sum);\\n\\n    position = sum * position;\\n    position.w = 1.;\\n\\n    gl_Position = uPMatrix * uMVMatrix * position;\\n    vTextureCoord = aTextureCoord;\\n\\n    vec3 normal = aNormal;\\n    vec3 tangent = aTangent.xyz;\\n\\n    // https://learnopengl.com/Advanced-Lighting/Normal-Mapping\\n    tangent = normalize(tangent - dot(tangent, normal) * normal);\\n\\n    vec3 binormal = cross(normal, tangent) * aTangent.w;\\n\\n    normal = normalize(rotation * normal);\\n    tangent = normalize(rotation * tangent);\\n    binormal = normalize(rotation * binormal);\\n\\n    vNormal = normal;\\n    vTangent = tangent;\\n    vBinormal = binormal;\\n\\n    vTBN = mat3(tangent, binormal, normal);\\n\\n    vFragPos = position.xyz;\\n}\"","export default \"precision mediump float;\\n\\nvarying vec2 vTextureCoord;\\nvarying vec3 vNormal;\\nvarying vec3 vTangent;\\nvarying vec3 vBinormal;\\nvarying mat3 vTBN;\\nvarying vec3 vFragPos;\\n\\nuniform sampler2D uSampler;\\nuniform sampler2D uNormalSampler;\\nuniform sampler2D uOrmSampler;\\nuniform vec3 uReplaceableColor;\\nuniform float uDiscardAlphaLevel;\\nuniform mat3 uTVertexAnim;\\nuniform vec3 uLightPos;\\nuniform vec3 uLightColor;\\nuniform vec3 uCameraPos;\\nuniform vec3 uShadowParams;\\nuniform sampler2D uShadowMapSampler;\\nuniform mat4 uShadowMapLightMatrix;\\nuniform float uWireframe;\\n\\nconst float PI = 3.14159265359;\\nconst float gamma = 2.2;\\n\\nfloat distributionGGX(vec3 normal, vec3 halfWay, float roughness) {\\n    float a = roughness * roughness;\\n    float a2 = a * a;\\n    float nDotH = max(dot(normal, halfWay), 0.0);\\n    float nDotH2 = nDotH * nDotH;\\n\\n    float num = a2;\\n    float denom = (nDotH2 * (a2 - 1.0) + 1.0);\\n    denom = PI * denom * denom;\\n\\n    return num / denom;\\n}\\n\\nfloat geometrySchlickGGX(float nDotV, float roughness) {\\n    float r = roughness + 1.;\\n    float k = r * r / 8.;\\n    // float k = roughness * roughness / 2.;\\n\\n    float num = nDotV;\\n    float denom = nDotV * (1. - k) + k;\\n\\n    return num / denom;\\n}\\n\\nfloat geometrySmith(vec3 normal, vec3 viewDir, vec3 lightDir, float roughness) {\\n    float nDotV = max(dot(normal, viewDir), .0);\\n    float nDotL = max(dot(normal, lightDir), .0);\\n    float ggx2  = geometrySchlickGGX(nDotV, roughness);\\n    float ggx1  = geometrySchlickGGX(nDotL, roughness);\\n\\n    return ggx1 * ggx2;\\n}\\n\\nvec3 fresnelSchlick(float lightFactor, vec3 f0) {\\n    return f0 + (1. - f0) * pow(clamp(1. - lightFactor, 0., 1.), 5.);\\n}\\n\\nvoid main(void) {\\n    if (uWireframe > 0.) {\\n        gl_FragColor = vec4(1.);\\n        return;\\n    }\\n\\n    vec2 texCoord = (uTVertexAnim * vec3(vTextureCoord.s, vTextureCoord.t, 1.)).st;\\n\\n    vec4 orm = texture2D(uOrmSampler, texCoord);\\n\\n    float occlusion = orm.r;\\n    float roughness = orm.g;\\n    float metallic = orm.b;\\n    float teamColorFactor = orm.a;\\n\\n    vec4 baseColor = texture2D(uSampler, texCoord);\\n    vec3 teamColor = baseColor.rgb * uReplaceableColor;\\n    baseColor.rgb = mix(baseColor.rgb, teamColor, teamColorFactor);\\n    baseColor.rgb = pow(baseColor.rgb, vec3(gamma));\\n\\n    vec3 normal = texture2D(uNormalSampler, texCoord).rgb;\\n    normal = normal * 2.0 - 1.0;\\n    normal.x = -normal.x;\\n    normal.y = -normal.y;\\n    if (!gl_FrontFacing) {\\n        normal = -normal;\\n    }\\n    normal = normalize(vTBN * -normal);\\n\\n    vec3 viewDir = normalize(uCameraPos - vFragPos);\\n    vec3 reflected = reflect(-viewDir, normal);\\n\\n    vec3 lightDir = normalize(uLightPos - vFragPos);\\n    float lightFactor = max(dot(normal, lightDir), .0);\\n    vec3 radiance = uLightColor;\\n\\n    vec3 f0 = vec3(.04);\\n    f0 = mix(f0, baseColor.rgb, metallic);\\n\\n    vec3 totalLight = vec3(0.);\\n    vec3 halfWay = normalize(viewDir + lightDir);\\n    float ndf = distributionGGX(normal, halfWay, roughness);\\n    float g = geometrySmith(normal, viewDir, lightDir, roughness);\\n    vec3 f = fresnelSchlick(max(dot(halfWay, viewDir), 0.), f0);\\n\\n    vec3 kS = f;\\n    // vec3 kD = vec3(1.) - kS;\\n    vec3 kD = vec3(1.);\\n    // kD *= 1.0 - metallic;\\n    vec3 num = ndf * g * f;\\n    float denom = 4. * max(dot(normal, viewDir), 0.) * max(dot(normal, lightDir), 0.) + .0001;\\n    vec3 specular = num / denom;\\n\\n    totalLight = (kD * baseColor.rgb / PI + specular) * radiance * lightFactor;\\n\\n    if (uShadowParams[0] > .5) {\\n        float shadowBias = uShadowParams[1];\\n        float shadowStep = uShadowParams[2];\\n        vec4 fragInLightPos = uShadowMapLightMatrix * vec4(vFragPos, 1.);\\n        vec3 shadowMapCoord = fragInLightPos.xyz / fragInLightPos.w;\\n        shadowMapCoord.xyz = (shadowMapCoord.xyz + 1.0) * .5;\\n\\n        int passes = 5;\\n        float step = 1. / float(passes);\\n\\n        float lightDepth = texture2D(uShadowMapSampler, shadowMapCoord.xy).r;\\n        float lightDepth0 = texture2D(uShadowMapSampler, vec2(shadowMapCoord.x + shadowStep, shadowMapCoord.y)).r;\\n        float lightDepth1 = texture2D(uShadowMapSampler, vec2(shadowMapCoord.x, shadowMapCoord.y + shadowStep)).r;\\n        float lightDepth2 = texture2D(uShadowMapSampler, vec2(shadowMapCoord.x, shadowMapCoord.y - shadowStep)).r;\\n        float lightDepth3 = texture2D(uShadowMapSampler, vec2(shadowMapCoord.x - shadowStep, shadowMapCoord.y)).r;\\n        float currentDepth = shadowMapCoord.z;\\n\\n        float visibility = 0.;\\n        if (lightDepth > currentDepth - shadowBias) {\\n            visibility += step;\\n        }\\n        if (lightDepth0 > currentDepth - shadowBias) {\\n            visibility += step;\\n        }\\n        if (lightDepth1 > currentDepth - shadowBias) {\\n            visibility += step;\\n        }\\n        if (lightDepth2 > currentDepth - shadowBias) {\\n            visibility += step;\\n        }\\n        if (lightDepth3 > currentDepth - shadowBias) {\\n            visibility += step;\\n        }\\n\\n        totalLight *= visibility;\\n    }\\n\\n    vec3 color;\\n\\n    vec3 ambient = vec3(.03);\\n    ambient *= baseColor.rgb * occlusion;\\n    color = ambient + totalLight;\\n\\n    color = color / (vec3(1.) + color);\\n    color = pow(color, vec3(1. / gamma));\\n\\n    gl_FragColor = vec4(color, 1.);\\n\\n    // hand-made alpha-test\\n    if (gl_FragColor[3] < uDiscardAlphaLevel) {\\n        discard;\\n    }\\n}\\n\"","export default \"#version 300 es\\nprecision mediump float;\\n\\nin vec2 vTextureCoord;\\nin vec3 vNormal;\\nin vec3 vTangent;\\nin vec3 vBinormal;\\nin mat3 vTBN;\\nin vec3 vFragPos;\\n\\nout vec4 FragColor;\\n\\nuniform sampler2D uSampler;\\nuniform sampler2D uNormalSampler;\\nuniform sampler2D uOrmSampler;\\nuniform vec3 uReplaceableColor;\\nuniform float uDiscardAlphaLevel;\\nuniform mat3 uTVertexAnim;\\nuniform vec3 uLightPos;\\nuniform vec3 uLightColor;\\nuniform vec3 uCameraPos;\\nuniform vec3 uShadowParams;\\nuniform sampler2D uShadowMapSampler;\\nuniform mat4 uShadowMapLightMatrix;\\nuniform bool uHasEnv;\\nuniform samplerCube uIrradianceMap;\\nuniform samplerCube uPrefilteredEnv;\\nuniform sampler2D uBRDFLUT;\\nuniform float uWireframe;\\n\\nconst float PI = 3.14159265359;\\nconst float gamma = 2.2;\\nconst float MAX_REFLECTION_LOD = ${MAX_ENV_MIP_LEVELS};\\n\\nfloat distributionGGX(vec3 normal, vec3 halfWay, float roughness) {\\n    float a = roughness * roughness;\\n    float a2 = a * a;\\n    float nDotH = max(dot(normal, halfWay), 0.0);\\n    float nDotH2 = nDotH * nDotH;\\n\\n    float num = a2;\\n    float denom = (nDotH2 * (a2 - 1.0) + 1.0);\\n    denom = PI * denom * denom;\\n\\n    return num / denom;\\n}\\n\\nfloat geometrySchlickGGX(float nDotV, float roughness) {\\n    float r = roughness + 1.;\\n    float k = r * r / 8.;\\n    // float k = roughness * roughness / 2.;\\n\\n    float num = nDotV;\\n    float denom = nDotV * (1. - k) + k;\\n\\n    return num / denom;\\n}\\n\\nfloat geometrySmith(vec3 normal, vec3 viewDir, vec3 lightDir, float roughness) {\\n    float nDotV = max(dot(normal, viewDir), .0);\\n    float nDotL = max(dot(normal, lightDir), .0);\\n    float ggx2  = geometrySchlickGGX(nDotV, roughness);\\n    float ggx1  = geometrySchlickGGX(nDotL, roughness);\\n\\n    return ggx1 * ggx2;\\n}\\n\\nvec3 fresnelSchlick(float lightFactor, vec3 f0) {\\n    return f0 + (1. - f0) * pow(clamp(1. - lightFactor, 0., 1.), 5.);\\n}\\n\\nvec3 fresnelSchlickRoughness(float lightFactor, vec3 f0, float roughness) {\\n    return f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(clamp(1.0 - lightFactor, 0.0, 1.0), 5.0);\\n}\\n\\nvoid main(void) {\\n    if (uWireframe > 0.) {\\n        FragColor = vec4(1.);\\n        return;\\n    }\\n\\n    vec2 texCoord = (uTVertexAnim * vec3(vTextureCoord.s, vTextureCoord.t, 1.)).st;\\n\\n    vec4 orm = texture(uOrmSampler, texCoord);\\n\\n    float occlusion = orm.r;\\n    float roughness = orm.g;\\n    float metallic = orm.b;\\n    float teamColorFactor = orm.a;\\n\\n    vec4 baseColor = texture(uSampler, texCoord);\\n    vec3 teamColor = baseColor.rgb * uReplaceableColor;\\n    baseColor.rgb = mix(baseColor.rgb, teamColor, teamColorFactor);\\n    baseColor.rgb = pow(baseColor.rgb, vec3(gamma));\\n\\n    vec3 normal = texture(uNormalSampler, texCoord).rgb;\\n    normal = normal * 2.0 - 1.0;\\n    normal.x = -normal.x;\\n    normal.y = -normal.y;\\n    if (!gl_FrontFacing) {\\n        normal = -normal;\\n    }\\n    normal = normalize(vTBN * -normal);\\n\\n    vec3 viewDir = normalize(uCameraPos - vFragPos);\\n    vec3 reflected = reflect(-viewDir, normal);\\n\\n    vec3 lightDir = normalize(uLightPos - vFragPos);\\n    float lightFactor = max(dot(normal, lightDir), .0);\\n    vec3 radiance = uLightColor;\\n\\n    vec3 f0 = vec3(.04);\\n    f0 = mix(f0, baseColor.rgb, metallic);\\n\\n    vec3 totalLight = vec3(0.);\\n    vec3 halfWay = normalize(viewDir + lightDir);\\n    float ndf = distributionGGX(normal, halfWay, roughness);\\n    float g = geometrySmith(normal, viewDir, lightDir, roughness);\\n    vec3 f = fresnelSchlick(max(dot(halfWay, viewDir), 0.), f0);\\n\\n    vec3 kS = f;\\n    vec3 kD = vec3(1.);// - kS;\\n    if (uHasEnv) {\\n        kD *= 1.0 - metallic;\\n    }\\n    vec3 num = ndf * g * f;\\n    float denom = 4. * max(dot(normal, viewDir), 0.) * max(dot(normal, lightDir), 0.) + .0001;\\n    vec3 specular = num / denom;\\n\\n    totalLight = (kD * baseColor.rgb / PI + specular) * radiance * lightFactor;\\n\\n    if (uShadowParams[0] > .5) {\\n        float shadowBias = uShadowParams[1];\\n        float shadowStep = uShadowParams[2];\\n        vec4 fragInLightPos = uShadowMapLightMatrix * vec4(vFragPos, 1.);\\n        vec3 shadowMapCoord = fragInLightPos.xyz / fragInLightPos.w;\\n        shadowMapCoord.xyz = (shadowMapCoord.xyz + 1.0) * .5;\\n\\n        int passes = 5;\\n        float step = 1. / float(passes);\\n\\n        float lightDepth = texture(uShadowMapSampler, shadowMapCoord.xy).r;\\n        float lightDepth0 = texture(uShadowMapSampler, vec2(shadowMapCoord.x + shadowStep, shadowMapCoord.y)).r;\\n        float lightDepth1 = texture(uShadowMapSampler, vec2(shadowMapCoord.x, shadowMapCoord.y + shadowStep)).r;\\n        float lightDepth2 = texture(uShadowMapSampler, vec2(shadowMapCoord.x, shadowMapCoord.y - shadowStep)).r;\\n        float lightDepth3 = texture(uShadowMapSampler, vec2(shadowMapCoord.x - shadowStep, shadowMapCoord.y)).r;\\n        float currentDepth = shadowMapCoord.z;\\n\\n        float visibility = 0.;\\n        if (lightDepth > currentDepth - shadowBias) {\\n            visibility += step;\\n        }\\n        if (lightDepth0 > currentDepth - shadowBias) {\\n            visibility += step;\\n        }\\n        if (lightDepth1 > currentDepth - shadowBias) {\\n            visibility += step;\\n        }\\n        if (lightDepth2 > currentDepth - shadowBias) {\\n            visibility += step;\\n        }\\n        if (lightDepth3 > currentDepth - shadowBias) {\\n            visibility += step;\\n        }\\n\\n        totalLight *= visibility;\\n    }\\n\\n    vec3 color;\\n\\n    if (uHasEnv) {\\n        vec3 f = fresnelSchlickRoughness(max(dot(normal, viewDir), 0.0), f0, roughness);\\n        vec3 kS = f;\\n        vec3 kD = vec3(1.0) - kS;\\n        kD *= 1.0 - metallic;\\n\\n        vec3 diffuse = texture(uIrradianceMap, normal).rgb * baseColor.rgb;\\n        vec3 prefilteredColor = textureLod(uPrefilteredEnv, reflected, roughness * MAX_REFLECTION_LOD).rgb;\\n        vec2 envBRDF = texture(uBRDFLUT, vec2(max(dot(normal, viewDir), 0.0), roughness)).rg;\\n        specular = prefilteredColor * (f * envBRDF.x + envBRDF.y);\\n\\n        vec3 ambient = (kD * diffuse + specular) * occlusion;\\n        color = ambient + totalLight;\\n    } else {\\n        vec3 ambient = vec3(.03);\\n        ambient *= baseColor.rgb * occlusion;\\n        color = ambient + totalLight;\\n    }\\n\\n    color = color / (vec3(1.) + color);\\n    color = pow(color, vec3(1. / gamma));\\n\\n    FragColor = vec4(color, baseColor.a);\\n\\n    // hand-made alpha-test\\n    if (FragColor[3] < uDiscardAlphaLevel) {\\n        discard;\\n    }\\n}\\n\"","export default \"attribute vec3 aVertexPosition;\\nattribute vec3 aColor;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\n\\nvarying vec3 vColor;\\n\\nvoid main(void) {\\n    vec4 position = vec4(aVertexPosition, 1.0);\\n    gl_Position = uPMatrix * uMVMatrix * position;\\n    vColor = aColor;\\n}\"","export default \"precision mediump float;\\n\\nvarying vec3 vColor;\\n\\nvoid main(void) {\\n    gl_FragColor = vec4(vColor, 1.0);\\n}\"","export default \"attribute vec3 aPos;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\n\\nvarying vec3 vLocalPos;\\n\\nvoid main(void) {\\n    vLocalPos = aPos;\\n    gl_Position = uPMatrix * uMVMatrix * vec4(aPos, 1.0);\\n}\"","export default \"precision mediump float;\\n\\nvarying vec3 vLocalPos;\\n\\nuniform sampler2D uEquirectangularMap;\\n\\nconst vec2 invAtan = vec2(0.1591, 0.3183);\\n\\nvec2 SampleSphericalMap(vec3 v) {\\n    // vec2 uv = vec2(atan(v.z, v.x), asin(v.y));\\n    vec2 uv = vec2(atan(v.x, v.y), asin(-v.z));\\n    uv *= invAtan;\\n    uv += 0.5;\\n    return uv;\\n}\\n\\nvoid main(void) {\\n    vec2 uv = SampleSphericalMap(normalize(vLocalPos)); // make sure to normalize localPos\\n    vec3 color = texture2D(uEquirectangularMap, uv).rgb;\\n\\n    gl_FragColor = vec4(color, 1.0);\\n}\"","export default \"#version 300 es\\n\\nin vec3 aPos;\\nout vec3 vLocalPos;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\n\\nvoid main(void) {\\n    vLocalPos = aPos;\\n    mat4 rotView = mat4(mat3(uMVMatrix)); // remove translation from the view matrix\\n    vec4 clipPos = uPMatrix * rotView * 1000. * vec4(aPos, 1.0);\\n\\n    gl_Position = clipPos.xyww;\\n}\"","export default \"#version 300 es\\nprecision mediump float;\\n\\nin vec3 vLocalPos;\\n\\nout vec4 FragColor;\\n\\nuniform samplerCube uEnvironmentMap;\\n\\nvoid main(void) {\\n    // vec3 envColor = textureLod(uEnvironmentMap, vLocalPos, 0.0).rgb;\\n    vec3 envColor = texture(uEnvironmentMap, vLocalPos).rgb;\\n\\n    FragColor = vec4(envColor, 1.0);\\n}\"","export default \"attribute vec3 aPos;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\n\\nvarying vec3 vLocalPos;\\n\\nvoid main(void) {\\n    vLocalPos = aPos;\\n    gl_Position = uPMatrix * uMVMatrix * vec4(aPos, 1.0);\\n}\"","export default \"precision mediump float;\\n\\nvarying vec3 vLocalPos;\\n\\nuniform samplerCube uEnvironmentMap;\\n\\nconst float PI = 3.14159265359;\\nconst float gamma = 2.2;\\n\\nvoid main(void) {\\n    vec3 irradiance = vec3(0.0);\\n\\n    // the sample direction equals the hemisphere's orientation\\n    vec3 normal = normalize(vLocalPos);\\n\\n    vec3 up    = vec3(0.0, 1.0, 0.0);\\n    vec3 right = normalize(cross(up, normal));\\n    up         = normalize(cross(normal, right));\\n\\n    const float sampleDelta = 0.025;\\n    float nrSamples = 0.0;\\n    for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta)\\n    {\\n        for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta)\\n        {\\n            // spherical to cartesian (in tangent space)\\n            vec3 tangentSample = vec3(sin(theta) * cos(phi),  sin(theta) * sin(phi), cos(theta));\\n            // tangent space to world\\n            vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal;\\n\\n            irradiance += pow(textureCube(uEnvironmentMap, sampleVec).rgb, vec3(gamma)) * cos(theta) * sin(theta);\\n            nrSamples++;\\n        }\\n    }\\n    irradiance = PI * irradiance * (1.0 / float(nrSamples));\\n\\n    gl_FragColor = vec4(irradiance, 1.0);\\n}\"","export default \"#version 300 es\\n\\nin vec3 aPos;\\n\\nout vec3 vLocalPos;\\n\\nuniform mat4 uMVMatrix;\\nuniform mat4 uPMatrix;\\n\\nvoid main(void) {\\n    vLocalPos = aPos;\\n    gl_Position = uPMatrix * uMVMatrix * vec4(aPos, 1.0);\\n}\"","export default \"#version 300 es\\nprecision mediump float;\\n\\nout vec4 FragColor;\\n\\nin vec3 vLocalPos;\\n\\nuniform samplerCube uEnvironmentMap;\\nuniform float uRoughness;\\n\\nconst float PI = 3.14159265359;\\nconst float gamma = 2.2;\\n\\nfloat RadicalInverse_VdC(uint bits) {\\n    bits = (bits << 16u) | (bits >> 16u);\\n    bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\\n    bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\\n    bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\\n    bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\\n    return float(bits) * 2.3283064365386963e-10; // / 0x100000000\\n}\\n\\nvec2 Hammersley(uint i, uint N) {\\n    return vec2(float(i)/float(N), RadicalInverse_VdC(i));\\n}\\n\\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) {\\n    float a = roughness * roughness;\\n\\n    float phi = 2.0 * PI * Xi.x;\\n    float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));\\n    float sinTheta = sqrt(1.0 - cosTheta*cosTheta);\\n\\n    // from spherical coordinates to cartesian coordinates\\n    vec3 H;\\n    H.x = cos(phi) * sinTheta;\\n    H.y = sin(phi) * sinTheta;\\n    H.z = cosTheta;\\n\\n    // from tangent-space vector to world-space sample vector\\n    vec3 up        = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\\n    vec3 tangent   = normalize(cross(up, N));\\n    vec3 bitangent = cross(N, tangent);\\n\\n    vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;\\n\\n    return normalize(sampleVec);\\n}\\n\\nvoid main() {\\n    vec3 N = normalize(vLocalPos);\\n    vec3 R = N;\\n    vec3 V = R;\\n\\n    const uint SAMPLE_COUNT = 1024u;\\n    float totalWeight = 0.0;\\n    vec3 prefilteredColor = vec3(0.0);\\n    for(uint i = 0u; i < SAMPLE_COUNT; ++i)\\n    {\\n        vec2 Xi = Hammersley(i, SAMPLE_COUNT);\\n        vec3 H  = ImportanceSampleGGX(Xi, N, uRoughness);\\n        vec3 L  = normalize(2.0 * dot(V, H) * H - V);\\n\\n        float NdotL = max(dot(N, L), 0.0);\\n        if(NdotL > 0.0) {\\n            prefilteredColor += pow(texture(uEnvironmentMap, L).rgb, vec3(gamma)) * NdotL;\\n            totalWeight      += NdotL;\\n        }\\n    }\\n    prefilteredColor = prefilteredColor / totalWeight;\\n\\n    FragColor = vec4(prefilteredColor, 1.0);\\n}\"","export default \"#version 300 es\\n\\nin vec3 aPos;\\n\\nout vec2 vLocalPos;\\n\\nvoid main(void) {\\n    vLocalPos = aPos.xy;\\n    gl_Position = vec4(aPos, 1.0);\\n}\"","export default \"#version 300 es\\nprecision mediump float;\\n\\nin vec2 vLocalPos;\\n\\nout vec4 FragColor;\\n\\nconst float PI = 3.14159265359;\\n\\nfloat RadicalInverse_VdC(uint bits) {\\n    bits = (bits << 16u) | (bits >> 16u);\\n    bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\\n    bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\\n    bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\\n    bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\\n    return float(bits) * 2.3283064365386963e-10; // / 0x100000000\\n}\\n\\nvec2 Hammersley(uint i, uint N) {\\n    return vec2(float(i)/float(N), RadicalInverse_VdC(i));\\n}\\n\\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) {\\n    float a = roughness * roughness;\\n\\n    float phi = 2.0 * PI * Xi.x;\\n    float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));\\n    float sinTheta = sqrt(1.0 - cosTheta*cosTheta);\\n\\n    // from spherical coordinates to cartesian coordinates\\n    vec3 H;\\n    H.x = cos(phi) * sinTheta;\\n    H.y = sin(phi) * sinTheta;\\n    H.z = cosTheta;\\n\\n    // from tangent-space vector to world-space sample vector\\n    vec3 up        = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\\n    vec3 tangent   = normalize(cross(up, N));\\n    vec3 bitangent = cross(N, tangent);\\n\\n    vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;\\n\\n    return normalize(sampleVec);\\n}\\n\\nfloat geometrySchlickGGX(float nDotV, float roughness) {\\n    float r = roughness;\\n    float k = r * r / 2.;\\n\\n    float num = nDotV;\\n    float denom = nDotV * (1. - k) + k;\\n\\n    return num / denom;\\n}\\n\\nfloat geometrySmith(vec3 normal, vec3 viewDir, vec3 lightDir, float roughness) {\\n    float nDotV = max(dot(normal, viewDir), .0);\\n    float nDotL = max(dot(normal, lightDir), .0);\\n    float ggx2  = geometrySchlickGGX(nDotV, roughness);\\n    float ggx1  = geometrySchlickGGX(nDotL, roughness);\\n\\n    return ggx1 * ggx2;\\n}\\n\\nvec2 IntegrateBRDF(float NdotV, float roughness) {\\n    vec3 V;\\n    V.x = sqrt(1.0 - NdotV*NdotV);\\n    V.y = 0.0;\\n    V.z = NdotV;\\n\\n    float A = 0.0;\\n    float B = 0.0;\\n\\n    vec3 N = vec3(0.0, 0.0, 1.0);\\n\\n    const uint SAMPLE_COUNT = 1024u;\\n    for(uint i = 0u; i < SAMPLE_COUNT; ++i)\\n    {\\n        vec2 Xi = Hammersley(i, SAMPLE_COUNT);\\n        vec3 H  = ImportanceSampleGGX(Xi, N, roughness);\\n        vec3 L  = normalize(2.0 * dot(V, H) * H - V);\\n\\n        float NdotL = max(L.z, 0.0);\\n        float NdotH = max(H.z, 0.0);\\n        float VdotH = max(dot(V, H), 0.0);\\n\\n        if(NdotL > 0.0)\\n        {\\n            float G = geometrySmith(N, V, L, roughness);\\n            float G_Vis = (G * VdotH) / (NdotH * NdotV);\\n            float Fc = pow(1.0 - VdotH, 5.0);\\n\\n            A += (1.0 - Fc) * G_Vis;\\n            B += Fc * G_Vis;\\n        }\\n    }\\n    A /= float(SAMPLE_COUNT);\\n    B /= float(SAMPLE_COUNT);\\n    return vec2(A, B);\\n}\\n\\nvoid main() {\\n    FragColor = vec4(IntegrateBRDF((vLocalPos.x + 1.0) * .5, (vLocalPos.y + 1.0) * .5), 0., 1.);\\n}\"","export default \"struct VSUniforms {\\n    mvMatrix: mat4x4f,\\n    pMatrix: mat4x4f,\\n    nodesMatrices: array<mat4x4f, ${MAX_NODES}>,\\n}\\n\\nstruct FSUniforms {\\n    replaceableColor: vec3f,\\n    replaceableType: u32,\\n    discardAlphaLevel: f32,\\n    wireframe: u32,\\n    tVertexAnim: mat3x3f,\\n}\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n@group(1) @binding(0) var<uniform> fsUniforms: FSUniforms;\\n@group(1) @binding(1) var fsUniformSampler: sampler;\\n@group(1) @binding(2) var fsUniformTexture: texture_2d<f32>;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n    @location(1) normal: vec3f,\\n    @location(2) textureCoord: vec2f,\\n    @location(3) group: vec4<u32>,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) normal: vec3f,\\n    @location(1) textureCoord: vec2f,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    var position: vec4f = vec4f(in.vertexPosition, 1.0);\\n    var count: i32 = 1;\\n    var sum: vec4f = vsUniforms.nodesMatrices[in.group[0]] * position;\\n\\n    if (in.group[1] < ${MAX_NODES}) {\\n        sum += vsUniforms.nodesMatrices[in.group[1]] * position;\\n        count += 1;\\n    }\\n    if (in.group[2] < ${MAX_NODES}) {\\n        sum += vsUniforms.nodesMatrices[in.group[2]] * position;\\n        count += 1;\\n    }\\n    if (in.group[3] < ${MAX_NODES}) {\\n        sum += vsUniforms.nodesMatrices[in.group[3]] * position;\\n        count += 1;\\n    }\\n    sum /= f32(count);\\n    sum.w = 1.;\\n    position = sum;\\n\\n    var out: VSOut;\\n    out.position = vsUniforms.pMatrix * vsUniforms.mvMatrix * position;\\n    out.textureCoord = in.textureCoord;\\n    out.normal = in.normal;\\n    return out;\\n}\\n\\nfn hypot(z: vec2f) -> f32 {\\n    var t: f32 = 0;\\n    var x: f32 = abs(z.x);\\n    let y: f32 = abs(z.y);\\n    t = min(x, y);\\n    x = max(x, y);\\n    t = t / x;\\n    if (z.x == 0.0 && z.y == 0.0) {\\n        return 0.0;\\n    }\\n    return x * sqrt(1.0 + t * t);\\n}\\n\\n@fragment fn fs(\\n    in: VSOut\\n) -> @location(0) vec4f {\\n    if (fsUniforms.wireframe > 0) {\\n        return vec4f(1);\\n    }\\n\\n    let texCoord: vec2f = (fsUniforms.tVertexAnim * vec3f(in.textureCoord.x, in.textureCoord.y, 1.)).xy;\\n    var color: vec4f = vec4f(0.0);\\n\\n    if (fsUniforms.replaceableType == 0) {\\n        color = textureSample(fsUniformTexture, fsUniformSampler, texCoord);\\n    } else if (fsUniforms.replaceableType == 1) {\\n        color = vec4f(fsUniforms.replaceableColor, 1.0);\\n    } else if (fsUniforms.replaceableType == 2) {\\n        let dist: f32 = hypot(texCoord - vec2(0.5, 0.5)) * 2.;\\n        let truncateDist: f32 = clamp(1. - dist * 1.4, 0., 1.);\\n        let alpha: f32 = sin(truncateDist);\\n        color = vec4f(fsUniforms.replaceableColor * alpha, 1.0);\\n    }\\n\\n    // hand-made alpha-test\\n    if (color.a < fsUniforms.discardAlphaLevel) {\\n        discard;\\n    }\\n\\n    return color;\\n}\\n\"","export default \"struct VSUniforms {\\n    mvMatrix: mat4x4f,\\n    pMatrix: mat4x4f,\\n    nodesMatrices: array<mat4x4f, ${MAX_NODES}>,\\n}\\n\\nstruct FSUniforms {\\n    replaceableColor: vec3f,\\n    // replaceableType: u32,\\n    discardAlphaLevel: f32,\\n    tVertexAnim: mat3x3f,\\n    lightPos: vec3f,\\n    hasEnv: u32,\\n    lightColor: vec3f,\\n    wireframe: u32,\\n    cameraPos: vec3f,\\n    shadowParams: vec3f,\\n    shadowMapLightMatrix: mat4x4f,\\n}\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n@group(1) @binding(0) var<uniform> fsUniforms: FSUniforms;\\n@group(1) @binding(1) var fsUniformDiffuseSampler: sampler;\\n@group(1) @binding(2) var fsUniformDiffuseTexture: texture_2d<f32>;\\n@group(1) @binding(3) var fsUniformNormalSampler: sampler;\\n@group(1) @binding(4) var fsUniformNormalTexture: texture_2d<f32>;\\n@group(1) @binding(5) var fsUniformOrmSampler: sampler;\\n@group(1) @binding(6) var fsUniformOrmTexture: texture_2d<f32>;\\n@group(1) @binding(7) var fsUniformShadowSampler: sampler_comparison;\\n@group(1) @binding(8) var fsUniformShadowTexture: texture_depth_2d;\\n@group(1) @binding(9) var irradienceMapSampler: sampler;\\n@group(1) @binding(10) var irradienceMapTexture: texture_cube<f32>;\\n@group(1) @binding(11) var prefilteredEnvSampler: sampler;\\n@group(1) @binding(12) var prefilteredEnvTexture: texture_cube<f32>;\\n@group(1) @binding(13) var brdfLutSampler: sampler;\\n@group(1) @binding(14) var brdfLutTexture: texture_2d<f32>;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n    @location(1) normal: vec3f,\\n    @location(2) textureCoord: vec2f,\\n    @location(3) tangent: vec4f,\\n    @location(4) skin: vec4<u32>,\\n    @location(5) boneWeight: vec4f,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) normal: vec3f,\\n    @location(1) textureCoord: vec2f,\\n    @location(2) tangent: vec3f,\\n    @location(3) binormal: vec3f,\\n    @location(4) fragPos: vec3f,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    var position: vec4f = vec4f(in.vertexPosition, 1.0);\\n    var sum: mat4x4f;\\n\\n    sum += vsUniforms.nodesMatrices[in.skin[0]] * in.boneWeight[0];\\n    sum += vsUniforms.nodesMatrices[in.skin[1]] * in.boneWeight[1];\\n    sum += vsUniforms.nodesMatrices[in.skin[2]] * in.boneWeight[2];\\n    sum += vsUniforms.nodesMatrices[in.skin[3]] * in.boneWeight[3];\\n\\n    let rotation: mat3x3f = mat3x3f(sum[0].xyz, sum[1].xyz, sum[2].xyz);\\n\\n    position = sum * position;\\n    position.w = 1;\\n\\n    var out: VSOut;\\n    out.position = vsUniforms.pMatrix * vsUniforms.mvMatrix * position;\\n    out.textureCoord = in.textureCoord;\\n    out.normal = in.normal;\\n\\n    var normal: vec3f = in.normal;\\n    var tangent: vec3f = in.tangent.xyz;\\n\\n    // https://learnopengl.com/Advanced-Lighting/Normal-Mapping\\n    tangent = normalize(tangent - dot(tangent, normal) * normal);\\n\\n    var binormal: vec3f = cross(normal, tangent) * in.tangent.w;\\n\\n    normal = normalize(rotation * normal);\\n    tangent = normalize(rotation * tangent);\\n    binormal = normalize(rotation * binormal);\\n\\n    out.normal = normal;\\n    out.tangent = tangent;\\n    out.binormal = binormal;\\n\\n    out.fragPos = position.xyz;\\n\\n    return out;\\n}\\n\\nfn hypot(z: vec2f) -> f32 {\\n    var t: f32 = 0;\\n    var x: f32 = abs(z.x);\\n    let y: f32 = abs(z.y);\\n    t = min(x, y);\\n    x = max(x, y);\\n    t = t / x;\\n    if (z.x == 0.0 && z.y == 0.0) {\\n        return 0.0;\\n    }\\n    return x * sqrt(1.0 + t * t);\\n}\\n\\nconst PI: f32 = 3.14159265359;\\nconst gamma: f32 = 2.2;\\nconst MAX_REFLECTION_LOD: f32 = ${MAX_ENV_MIP_LEVELS};\\n\\nfn distributionGGX(normal: vec3f, halfWay: vec3f, roughness: f32) -> f32 {\\n    let a: f32 = roughness * roughness;\\n    let a2: f32 = a * a;\\n    let nDotH: f32 = max(dot(normal, halfWay), 0.0);\\n    let nDotH2: f32 = nDotH * nDotH;\\n\\n    let num: f32 = a2;\\n    var denom: f32 = (nDotH2 * (a2 - 1.0) + 1.0);\\n    denom = PI * denom * denom;\\n\\n    return num / denom;\\n}\\n\\nfn geometrySchlickGGX(nDotV: f32, roughness: f32) -> f32 {\\n    let r: f32 = roughness + 1.;\\n    let k: f32 = r * r / 8.;\\n    // float k = roughness * roughness / 2.;\\n\\n    let num: f32 = nDotV;\\n    let denom: f32 = nDotV * (1. - k) + k;\\n\\n    return num / denom;\\n}\\n\\nfn geometrySmith(normal: vec3f, viewDir: vec3f, lightDir: vec3f, roughness: f32) -> f32 {\\n    let nDotV: f32 = max(dot(normal, viewDir), .0);\\n    let nDotL: f32 = max(dot(normal, lightDir), .0);\\n    let ggx2: f32  = geometrySchlickGGX(nDotV, roughness);\\n    let ggx1: f32  = geometrySchlickGGX(nDotL, roughness);\\n\\n    return ggx1 * ggx2;\\n}\\n\\nfn fresnelSchlick(lightFactor: f32, f0: vec3f) -> vec3f {\\n    return f0 + (1. - f0) * pow(clamp(1. - lightFactor, 0., 1.), 5.);\\n}\\n\\nfn fresnelSchlickRoughness(lightFactor: f32, f0: vec3f, roughness: f32) -> vec3f {\\n    return f0 + (max(vec3(1.0 - roughness), f0) - f0) * pow(clamp(1.0 - lightFactor, 0.0, 1.0), 5.0);\\n}\\n\\n@fragment fn fs(\\n    in: VSOut,\\n    @builtin(front_facing) isFront: bool\\n) -> @location(0) vec4f {\\n    if (fsUniforms.wireframe > 0) {\\n        return vec4f(1);\\n    }\\n\\n    let texCoord: vec2f = (fsUniforms.tVertexAnim * vec3f(in.textureCoord.x, in.textureCoord.y, 1.)).xy;\\n    var baseColor: vec4f = textureSample(fsUniformDiffuseTexture, fsUniformDiffuseSampler, texCoord);\\n\\n    // hand-made alpha-test\\n    if (baseColor.a < fsUniforms.discardAlphaLevel) {\\n        discard;\\n    }\\n\\n    let orm: vec4f = textureSample(fsUniformOrmTexture, fsUniformOrmSampler, texCoord);\\n\\n    let occlusion: f32 = orm.r;\\n    let roughness: f32 = orm.g;\\n    let metallic: f32 = orm.b;\\n    let teamColorFactor: f32 = orm.a;\\n\\n    var teamColor: vec3f = baseColor.rgb * fsUniforms.replaceableColor;\\n    baseColor = vec4(mix(baseColor.rgb, teamColor, teamColorFactor), baseColor.a);\\n    baseColor = vec4(pow(baseColor.rgb, vec3f(gamma)), baseColor.a);\\n\\n    let TBN: mat3x3f = mat3x3f(in.tangent, in.binormal, in.normal);\\n\\n    var normal: vec3f = textureSample(fsUniformNormalTexture, fsUniformNormalSampler, texCoord).xyz;\\n    normal = normal * 2 - 1;\\n    normal.x = -normal.x;\\n    normal.y = -normal.y;\\n    if (!isFront) {\\n        normal = -normal;\\n    }\\n    normal = normalize(TBN * -normal);\\n\\n    let viewDir: vec3f = normalize(fsUniforms.cameraPos - in.fragPos);\\n    let reflected = reflect(-viewDir, normal);\\n\\n    let lightDir: vec3f = normalize(fsUniforms.lightPos - in.fragPos);\\n    let lightFactor: f32 = max(dot(normal, lightDir), 0);\\n    let radiance: vec3f = fsUniforms.lightColor;\\n\\n    var f0 = vec3f(.04);\\n    f0 = mix(f0, baseColor.rgb, metallic);\\n\\n    var totalLight: vec3f = vec3f(0);\\n    let halfWay: vec3f = normalize(viewDir + lightDir);\\n    let ndf: f32 = distributionGGX(normal, halfWay, roughness);\\n    let g: f32 = geometrySmith(normal, viewDir, lightDir, roughness);\\n    let f: vec3f = fresnelSchlick(max(dot(halfWay, viewDir), 0), f0);\\n\\n    let kS = f;\\n    var kD = vec3f(1);// - kS;\\n    if (fsUniforms.hasEnv > 0) {\\n        kD *= 1 - metallic;\\n    }\\n    let num: vec3f = ndf * g * f;\\n    let denom: f32 = 4. * max(dot(normal, viewDir), 0.) * max(dot(normal, lightDir), 0.) + .0001;\\n    var specular: vec3f = num / denom;\\n\\n    totalLight = (kD * baseColor.rgb / PI + specular) * radiance * lightFactor;\\n\\n    if (fsUniforms.shadowParams[0] > .5) {\\n        let shadowBias: f32 = fsUniforms.shadowParams[1];\\n        let shadowStep: f32 = fsUniforms.shadowParams[2];\\n        let fragInLightPos: vec4f = fsUniforms.shadowMapLightMatrix * vec4f(in.fragPos, 1.);\\n        var shadowMapCoord: vec3f = fragInLightPos.xyz / fragInLightPos.w;\\n        shadowMapCoord = vec3f((shadowMapCoord.xy + 1) * .5, shadowMapCoord.z);\\n        shadowMapCoord.y = 1 - shadowMapCoord.y;\\n\\n        let passes: u32 = 5;\\n        let step: f32 = 1. / f32(passes);\\n\\n        let currentDepth: f32 = shadowMapCoord.z;\\n        var lightDepth: f32 = textureSampleCompare(fsUniformShadowTexture, fsUniformShadowSampler, shadowMapCoord.xy, currentDepth - shadowBias);\\n        let lightDepth0: f32 = textureSampleCompare(fsUniformShadowTexture, fsUniformShadowSampler, vec2f(shadowMapCoord.x + shadowStep, shadowMapCoord.y), currentDepth - shadowBias);\\n        let lightDepth1: f32 = textureSampleCompare(fsUniformShadowTexture, fsUniformShadowSampler, vec2f(shadowMapCoord.x, shadowMapCoord.y + shadowStep), currentDepth - shadowBias);\\n        let lightDepth2: f32 = textureSampleCompare(fsUniformShadowTexture, fsUniformShadowSampler, vec2f(shadowMapCoord.x, shadowMapCoord.y - shadowStep), currentDepth - shadowBias);\\n        let lightDepth3: f32 = textureSampleCompare(fsUniformShadowTexture, fsUniformShadowSampler, vec2f(shadowMapCoord.x - shadowStep, shadowMapCoord.y), currentDepth - shadowBias);\\n\\n        var visibility: f32 = 0.;\\n        if (lightDepth > .5) {\\n            visibility += step;\\n        }\\n        if (lightDepth0 > .5) {\\n            visibility += step;\\n        }\\n        if (lightDepth1 > .5) {\\n            visibility += step;\\n        }\\n        if (lightDepth2 > .5) {\\n            visibility += step;\\n        }\\n        if (lightDepth3 > .5) {\\n            visibility += step;\\n        }\\n\\n        totalLight *= visibility;\\n    }\\n\\n    var color: vec3f = vec3f(0.0);\\n\\n    if (fsUniforms.hasEnv > 0) {\\n        let f: vec3f = fresnelSchlickRoughness(max(dot(normal, viewDir), 0.0), f0, roughness);\\n        let kS: vec3f = f;\\n        var kD: vec3f = vec3f(1.0) - kS;\\n        kD *= 1.0 - metallic;\\n\\n        let diffuse: vec3f = textureSample(irradienceMapTexture, irradienceMapSampler, normal).rgb * baseColor.rgb;\\n        let prefilteredColor: vec3f = textureSampleLevel(prefilteredEnvTexture, prefilteredEnvSampler, reflected, roughness * MAX_REFLECTION_LOD).rgb;\\n        let envBRDF: vec2f = textureSample(brdfLutTexture, brdfLutSampler, vec2f(max(dot(normal, viewDir), 0.0), roughness)).rg;\\n        specular = prefilteredColor * (f * envBRDF.x + envBRDF.y);\\n\\n        let ambient: vec3f = (kD * diffuse + specular) * occlusion;\\n        color = ambient + totalLight;\\n    } else {\\n        var ambient: vec3f = vec3(.03);\\n        ambient *= baseColor.rgb * occlusion;\\n        color = ambient + totalLight;\\n    }\\n\\n    color = color / (vec3f(1) + color);\\n    color = pow(color, vec3f(1 / gamma));\\n\\n    return vec4f(color, baseColor.a);\\n}\\n\"","export default \"struct VSUniforms {\\n    mvMatrix: mat4x4f,\\n    pMatrix: mat4x4f,\\n    nodesMatrices: array<mat4x4f, ${MAX_NODES}>,\\n}\\n\\nstruct FSUniforms {\\n    replaceableColor: vec3f,\\n    // replaceableType: u32,\\n    discardAlphaLevel: f32,\\n    tVertexAnim: mat3x3f,\\n    lightPos: vec3f,\\n    lightColor: vec3f,\\n    cameraPos: vec3f,\\n    shadowParams: vec3f,\\n    shadowMapLightMatrix: mat4x4f,\\n    // env\\n}\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n@group(1) @binding(0) var<uniform> fsUniforms: FSUniforms;\\n@group(1) @binding(1) var fsUniformDiffuseSampler: sampler;\\n@group(1) @binding(2) var fsUniformDiffuseTexture: texture_2d<f32>;\\n@group(1) @binding(3) var fsUniformNormalSampler: sampler;\\n@group(1) @binding(4) var fsUniformNormalTexture: texture_2d<f32>;\\n@group(1) @binding(5) var fsUniformOrmSampler: sampler;\\n@group(1) @binding(6) var fsUniformOrmTexture: texture_2d<f32>;\\n@group(1) @binding(7) var fsUniformShadowSampler: sampler_comparison;\\n// @group(1) @binding(7) var fsUniformShadowSampler: sampler;\\n@group(1) @binding(8) var fsUniformShadowTexture: texture_depth_2d;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n    @location(1) normal: vec3f,\\n    @location(2) textureCoord: vec2f,\\n    @location(3) tangent: vec4f,\\n    @location(4) skin: vec4<u32>,\\n    @location(5) boneWeight: vec4f,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) textureCoord: vec2f,\\n    @location(1) depth: f32,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    var position: vec4f = vec4f(in.vertexPosition, 1.0);\\n    var sum: mat4x4f;\\n\\n    sum += vsUniforms.nodesMatrices[in.skin[0]] * in.boneWeight[0];\\n    sum += vsUniforms.nodesMatrices[in.skin[1]] * in.boneWeight[1];\\n    sum += vsUniforms.nodesMatrices[in.skin[2]] * in.boneWeight[2];\\n    sum += vsUniforms.nodesMatrices[in.skin[3]] * in.boneWeight[3];\\n\\n    position = sum * position;\\n    position.w = 1;\\n\\n    var out: VSOut;\\n    out.position = vsUniforms.pMatrix * vsUniforms.mvMatrix * position;\\n    out.textureCoord = in.textureCoord;\\n\\n    out.depth = out.position.z / out.position.w;\\n\\n    return out;\\n}\\n\\nstruct FSOut {\\n    @builtin(frag_depth) depth: f32,\\n    @location(0) color: vec4f\\n}\\n\\n@fragment fn fs(\\n    in: VSOut,\\n    @builtin(front_facing) isFront: bool\\n) -> FSOut {\\n    let texCoord: vec2f = (fsUniforms.tVertexAnim * vec3f(in.textureCoord.x, in.textureCoord.y, 1.)).xy;\\n    var baseColor: vec4f = textureSample(fsUniformDiffuseTexture, fsUniformDiffuseSampler, texCoord);\\n\\n    // hand-made alpha-test\\n    if (baseColor.a < fsUniforms.discardAlphaLevel) {\\n        discard;\\n    }\\n\\n    var out: FSOut;\\n    out.color = vec4f(1, 1, 1, 1);\\n    out.depth = in.depth;\\n    return out;\\n}\\n\"","export default \"struct VSUniforms {\\n    mvMatrix: mat4x4f,\\n    pMatrix: mat4x4f,\\n}\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n    @location(1) color: vec3f,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) color: vec3f,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    var position: vec4f = vec4f(in.vertexPosition, 1.0);\\n\\n    var out: VSOut;\\n    out.position = vsUniforms.pMatrix * vsUniforms.mvMatrix * position;\\n    out.color = in.color;\\n    return out;\\n}\\n\\n@fragment fn fs(\\n    in: VSOut\\n) -> @location(0) vec4f {\\n    return vec4f(in.color, 1);\\n}\\n\"","export default \"struct VSUniforms {\\n    mvMatrix: mat4x4f,\\n    pMatrix: mat4x4f,\\n}\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n@group(1) @binding(0) var fsUniformSampler: sampler;\\n@group(1) @binding(1) var fsUniformTexture: texture_cube<f32>;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) localPos: vec3f,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    let rotView: mat4x4f = mat4x4f(\\n        vec4f(vsUniforms.mvMatrix[0].xyz, 0),\\n        vec4f(vsUniforms.mvMatrix[1].xyz, 0),\\n        vec4f(vsUniforms.mvMatrix[2].xyz, 0),\\n        vec4f(0, 0, 0, 1)\\n    );\\n\\n    let clipPos: vec4f = vsUniforms.pMatrix * rotView * 1000. * vec4f(in.vertexPosition, 1.0);\\n\\n    var out: VSOut;\\n    out.position = clipPos;\\n    out.localPos = in.vertexPosition;\\n    return out;\\n}\\n\\n@fragment fn fs(\\n    in: VSOut\\n) -> @location(0) vec4f {\\n    return textureSample(fsUniformTexture, fsUniformSampler, in.localPos);\\n}\\n\"","export default \"const invAtan: vec2f = vec2f(0.1591, 0.3183);\\n\\nstruct VSUniforms {\\n    mvMatrix: mat4x4f,\\n    pMatrix: mat4x4f,\\n}\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n@group(1) @binding(0) var fsUniformSampler: sampler;\\n@group(1) @binding(1) var fsUniformTexture: texture_2d<f32>;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) localPos: vec3f,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    var out: VSOut;\\n    out.position = vsUniforms.pMatrix * vsUniforms.mvMatrix * vec4f(in.vertexPosition, 1);\\n    out.localPos = in.vertexPosition;\\n    return out;\\n}\\n\\nfn SampleSphericalMap(v: vec3f) -> vec2f {\\n    // vec2 uv = vec2(atan(v.z, v.x), asin(v.y));\\n    var uv: vec2f = vec2f(atan2(v.x, v.y), asin(-v.z));\\n    uv *= invAtan;\\n    uv += 0.5;\\n    return uv;\\n}\\n\\n@fragment fn fs(\\n    in: VSOut\\n) -> @location(0) vec4f {\\n    let uv: vec2f = SampleSphericalMap(normalize(in.localPos)); // make sure to normalize localPos\\n    let color: vec3f = textureSample(fsUniformTexture, fsUniformSampler, uv).rgb;\\n\\n    return vec4f(color, 1.0);\\n}\\n\"","export default \"const PI: f32 = 3.14159265359;\\nconst gamma: f32 = 2.2;\\nconst sampleDelta: f32 = 0.025;\\n\\nstruct VSUniforms {\\n    mvMatrix: mat4x4f,\\n    pMatrix: mat4x4f,\\n}\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n@group(1) @binding(0) var fsUniformSampler: sampler;\\n@group(1) @binding(1) var fsUniformTexture: texture_cube<f32>;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) localPos: vec3f,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    var out: VSOut;\\n    out.position = vsUniforms.pMatrix * vsUniforms.mvMatrix * vec4f(in.vertexPosition, 1);\\n    out.localPos = in.vertexPosition;\\n    return out;\\n}\\n\\n@fragment fn fs(\\n    in: VSOut\\n) -> @location(0) vec4f {\\n    var irradiance: vec3f = vec3f(0);\\n\\n    // the sample direction equals the hemisphere's orientation\\n    let normal: vec3f = normalize(in.localPos);\\n\\n    var up: vec3f = vec3f(0.0, 1.0, 0.0);\\n    let right: vec3f = normalize(cross(up, normal));\\n    up = normalize(cross(normal, right));\\n\\n    var nrSamples: i32 = 0;\\n    for (var phi: f32 = 0.0; phi < 2.0 * PI; phi += sampleDelta)\\n    {\\n        for (var theta: f32 = 0.0; theta < 0.5 * PI; theta += sampleDelta)\\n        {\\n            // spherical to cartesian (in tangent space)\\n            let tangentSample: vec3f = vec3f(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta));\\n            // tangent space to world\\n            let sampleVec: vec3f = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal;\\n\\n            irradiance += pow(textureSample(fsUniformTexture, fsUniformSampler, sampleVec).rgb, vec3f(gamma)) * cos(theta) * sin(theta);\\n            nrSamples++;\\n        }\\n    }\\n    irradiance = PI * irradiance * (1.0 / f32(nrSamples));\\n\\n    return vec4f(irradiance, 1.0);\\n}\\n\"","export default \"const PI: f32 = 3.14159265359;\\nconst gamma: f32 = 2.2;\\n\\nstruct VSUniforms {\\n    mvMatrix: mat4x4f,\\n    pMatrix: mat4x4f,\\n}\\n\\nstruct FSUniforms {\\n    roughness: f32,\\n}\\n\\n@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;\\n@group(1) @binding(0) var<uniform> fsUniforms: FSUniforms;\\n@group(1) @binding(1) var fsUniformSampler: sampler;\\n@group(1) @binding(2) var fsUniformTexture: texture_cube<f32>;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) localPos: vec3f,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    var out: VSOut;\\n    out.position = vsUniforms.pMatrix * vsUniforms.mvMatrix * vec4f(in.vertexPosition, 1);\\n    out.localPos = in.vertexPosition;\\n    return out;\\n}\\n\\nfn RadicalInverse_VdC(bits: u32) -> f32 {\\n    var res: u32 = bits;\\n    res = (res << 16u) | (res >> 16u);\\n    res = ((res & 0x55555555u) << 1u) | ((res & 0xAAAAAAAAu) >> 1u);\\n    res = ((res & 0x33333333u) << 2u) | ((res & 0xCCCCCCCCu) >> 2u);\\n    res = ((res & 0x0F0F0F0Fu) << 4u) | ((res & 0xF0F0F0F0u) >> 4u);\\n    res = ((res & 0x00FF00FFu) << 8u) | ((res & 0xFF00FF00u) >> 8u);\\n    return f32(res) * 2.3283064365386963e-10; // / 0x100000000\\n}\\n\\nfn Hammersley(i: u32, N: u32) -> vec2f {\\n    return vec2f(f32(i)/f32(N), RadicalInverse_VdC(i));\\n}\\n\\nfn ImportanceSampleGGX(Xi: vec2f, N: vec3f, roughness: f32) -> vec3f {\\n    let a: f32 = roughness * roughness;\\n\\n    let phi: f32 = 2.0 * PI * Xi.x;\\n    let cosTheta: f32 = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));\\n    let sinTheta: f32 = sqrt(1.0 - cosTheta*cosTheta);\\n\\n    // from spherical coordinates to cartesian coordinates\\n    var H: vec3f;\\n    H.x = cos(phi) * sinTheta;\\n    H.y = sin(phi) * sinTheta;\\n    H.z = cosTheta;\\n\\n    // from tangent-space vector to world-space sample vector\\n    var up: vec3f;\\n    if (abs(N.z) < 0.999) {\\n        up = vec3f(0.0, 0.0, 1.0);\\n    } else {\\n        up = vec3f(1.0, 0.0, 0.0);\\n    }\\n    let tangent: vec3f   = normalize(cross(up, N));\\n    let bitangent: vec3f = cross(N, tangent);\\n\\n    let sampleVec: vec3f = tangent * H.x + bitangent * H.y + N * H.z;\\n\\n    return normalize(sampleVec);\\n}\\n\\n@fragment fn fs(\\n    in: VSOut\\n) -> @location(0) vec4f {\\n    let N: vec3f = normalize(in.localPos);\\n    let R: vec3f = N;\\n    let V: vec3f = R;\\n\\n    const SAMPLE_COUNT: u32 = 1024u;\\n    var totalWeight: f32 = 0.0;\\n    var prefilteredColor: vec3f = vec3f(0.0);\\n    for(var i: u32 = 0u; i < SAMPLE_COUNT; i++)\\n    {\\n        let Xi: vec2f = Hammersley(i, SAMPLE_COUNT);\\n        let H: vec3f  = ImportanceSampleGGX(Xi, N, fsUniforms.roughness);\\n        let L: vec3f  = normalize(2.0 * dot(V, H) * H - V);\\n\\n        let NdotL: f32 = max(dot(N, L), 0.0);\\n        if(NdotL > 0.0) {\\n            prefilteredColor += pow(textureSampleLevel(fsUniformTexture, fsUniformSampler, L, 0).rgb, vec3f(gamma)) * NdotL;\\n            totalWeight      += NdotL;\\n        }\\n    }\\n    prefilteredColor = prefilteredColor / totalWeight;\\n\\n    return vec4f(prefilteredColor, 1.0);\\n}\\n\"","export default \"const PI: f32 = 3.14159265359;\\n\\nstruct VSIn {\\n    @location(0) vertexPosition: vec3f,\\n}\\n\\nstruct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) localPos: vec3f,\\n}\\n\\n@vertex fn vs(\\n    in: VSIn\\n) -> VSOut {\\n    var out: VSOut;\\n    out.position = vec4f(in.vertexPosition, 1);\\n    out.localPos = in.vertexPosition;\\n    return out;\\n}\\n\\nfn RadicalInverse_VdC(bits: u32) -> f32 {\\n    var res: u32 = bits;\\n    res = (res << 16u) | (res >> 16u);\\n    res = ((res & 0x55555555u) << 1u) | ((res & 0xAAAAAAAAu) >> 1u);\\n    res = ((res & 0x33333333u) << 2u) | ((res & 0xCCCCCCCCu) >> 2u);\\n    res = ((res & 0x0F0F0F0Fu) << 4u) | ((res & 0xF0F0F0F0u) >> 4u);\\n    res = ((res & 0x00FF00FFu) << 8u) | ((res & 0xFF00FF00u) >> 8u);\\n    return f32(res) * 2.3283064365386963e-10; // / 0x100000000\\n}\\n\\nfn Hammersley(i: u32, N: u32) -> vec2f {\\n    return vec2f(f32(i)/f32(N), RadicalInverse_VdC(i));\\n}\\n\\nfn ImportanceSampleGGX(Xi: vec2f, N: vec3f, roughness: f32) -> vec3f {\\n    let a: f32 = roughness * roughness;\\n\\n    let phi: f32 = 2.0 * PI * Xi.x;\\n    let cosTheta: f32 = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y));\\n    let sinTheta: f32 = sqrt(1.0 - cosTheta*cosTheta);\\n\\n    // from spherical coordinates to cartesian coordinates\\n    var H: vec3f;\\n    H.x = cos(phi) * sinTheta;\\n    H.y = sin(phi) * sinTheta;\\n    H.z = cosTheta;\\n\\n    // from tangent-space vector to world-space sample vector\\n    var up: vec3f;\\n    if (abs(N.z) < 0.999) {\\n        up = vec3f(0.0, 0.0, 1.0);\\n    } else {\\n        up = vec3f(1.0, 0.0, 0.0);\\n    }\\n    let tangent: vec3f   = normalize(cross(up, N));\\n    let bitangent: vec3f = cross(N, tangent);\\n\\n    let sampleVec: vec3f = tangent * H.x + bitangent * H.y + N * H.z;\\n\\n    return normalize(sampleVec);\\n}\\n\\nfn geometrySchlickGGX(nDotV: f32, roughness: f32) -> f32 {\\n    let r: f32 = roughness + 1.;\\n    let k: f32 = r * r / 8.;\\n    // float k = roughness * roughness / 2.;\\n\\n    let num: f32 = nDotV;\\n    let denom: f32 = nDotV * (1. - k) + k;\\n\\n    return num / denom;\\n}\\n\\nfn geometrySmith(normal: vec3f, viewDir: vec3f, lightDir: vec3f, roughness: f32) -> f32 {\\n    let nDotV: f32 = max(dot(normal, viewDir), .0);\\n    let nDotL: f32 = max(dot(normal, lightDir), .0);\\n    let ggx2: f32  = geometrySchlickGGX(nDotV, roughness);\\n    let ggx1: f32  = geometrySchlickGGX(nDotL, roughness);\\n\\n    return ggx1 * ggx2;\\n}\\n\\nfn IntegrateBRDF(NdotV: f32, roughness: f32) -> vec2f {\\n    var V: vec3f;\\n    V.x = sqrt(1.0 - NdotV*NdotV);\\n    V.y = 0.0;\\n    V.z = NdotV;\\n\\n    var A: f32 = 0.0;\\n    var B: f32 = 0.0;\\n\\n    let N: vec3f = vec3f(0.0, 0.0, 1.0);\\n\\n    const SAMPLE_COUNT: u32 = 1024u;\\n    for(var i: u32 = 0u; i < SAMPLE_COUNT; i++) {\\n        let Xi: vec2f = Hammersley(i, SAMPLE_COUNT);\\n        let H: vec3f  = ImportanceSampleGGX(Xi, N, roughness);\\n        let L: vec3f  = normalize(2.0 * dot(V, H) * H - V);\\n\\n        let NdotL: f32 = max(L.z, 0.0);\\n        let NdotH: f32 = max(H.z, 0.0);\\n        let VdotH: f32 = max(dot(V, H), 0.0);\\n\\n        if (NdotL > 0.0) {\\n            let G: f32 = geometrySmith(N, V, L, roughness);\\n            let G_Vis: f32 = (G * VdotH) / (NdotH * NdotV);\\n            let Fc: f32 = pow(1.0 - VdotH, 5.0);\\n\\n            A += (1.0 - Fc) * G_Vis;\\n            B += Fc * G_Vis;\\n        }\\n    }\\n    A /= f32(SAMPLE_COUNT);\\n    B /= f32(SAMPLE_COUNT);\\n\\n    return vec2f(A, B);\\n}\\n\\n@fragment fn fs(\\n    in: VSOut\\n) -> @location(0) vec4f {\\n    return vec4f(IntegrateBRDF((in.localPos.x + 1.0) * .5, (in.localPos.y + 1.0) * .5), 0., 1.);\\n}\\n\"","export default \"struct VSOut {\\n    @builtin(position) position: vec4f,\\n    @location(0) texCoord: vec2f,\\n};\\n\\n@vertex fn vs(\\n    @location(0) position: vec2f\\n) -> VSOut {\\n    var vsOutput: VSOut;\\n    vsOutput.position = vec4f(position * 2.0 - 1.0, 0.0, 1.0);\\n    vsOutput.texCoord = vec2f(position.x, 1.0 - position.y);\\n    return vsOutput;\\n}\\n\\n@group(0) @binding(0) var textureSampler: sampler;\\n@group(0) @binding(1) var textureView: texture_2d<f32>;\\n\\n@fragment fn fs(\\n    fsInput: VSOut\\n) -> @location(0) vec4f {\\n    return textureSample(textureView, textureSampler, fsInput.texCoord);\\n}\"","import shader from './shaders/webgpu/mips.wgsl?raw';\n\nlet sampler: GPUSampler;\nlet module: GPUShaderModule;\nlet buffer: GPUBuffer;\nconst pipelineByFormat = new WeakMap();\n\nexport function generateMips(device: GPUDevice, texture: GPUTexture): void {\n    if (!buffer) {\n        buffer = device.createBuffer({\n            label: 'mips vertex buffer',\n            size: 4 * 2 * 6,\n            usage: GPUBufferUsage.VERTEX,\n            mappedAtCreation: true\n        });\n        new Float32Array(\n            buffer.getMappedRange(0, buffer.size)\n        ).set([\n            0, 0,\n            1, 0,\n            0, 1,\n            0, 1,\n            1, 0,\n            1, 1\n        ]);\n        buffer.unmap();\n\n        module = device.createShaderModule({\n            label: 'mips shader module',\n            code: shader\n        });\n\n        sampler = device.createSampler({\n            label: 'mips sampler',\n            minFilter: 'linear'\n        });\n    }\n\n    if (!pipelineByFormat[texture.format]) {\n        pipelineByFormat[texture.format] = device.createRenderPipeline({\n            label: 'mips pipeline',\n            layout: 'auto',\n            vertex: {\n                module,\n                buffers: [{\n                    arrayStride: 8,\n                    attributes: [{\n                        shaderLocation: 0,\n                        offset: 0,\n                        format: 'float32x2' as const\n                    }]\n                }]\n            },\n            fragment: {\n                module,\n                targets: [{ format: texture.format }]\n            }\n        });\n    }\n\n    const pipeline = pipelineByFormat[texture.format];\n\n    const encoder = device.createCommandEncoder({\n        label: 'mips encoder'\n    });\n\n    for (let i = 1; i < texture.mipLevelCount; ++i) {\n        for (let j = 0; j < texture.depthOrArrayLayers; ++j) {\n            const bindGroup = device.createBindGroup({\n                layout: pipeline.getBindGroupLayout(0),\n                entries: [\n                    {\n                        binding: 0,\n                        resource: sampler\n                    },\n                    {\n                        binding: 1,\n                        resource: texture.createView({\n                            dimension: '2d',\n                            baseMipLevel: i - 1,\n                            mipLevelCount: 1,\n                            baseArrayLayer: j,\n                            arrayLayerCount: 1\n                        })\n                    }\n                ]\n            });\n\n            const renderPassDescriptor = {\n                label: 'mips render pass',\n                colorAttachments: [\n                    {\n                        view: texture.createView({\n                            dimension: '2d',\n                            baseMipLevel: i,\n                            mipLevelCount: 1,\n                            baseArrayLayer: j,\n                            arrayLayerCount: 1\n                        }),\n                        loadOp: 'clear',\n                        storeOp: 'store'\n                    },\n                ],\n            } as const;\n\n            const pass = encoder.beginRenderPass(renderPassDescriptor);\n            pass.setPipeline(pipeline);\n            pass.setVertexBuffer(0, buffer);\n            pass.setBindGroup(0, bindGroup);\n            pass.draw(6);\n            pass.end();\n        }\n    }\n    const commandBuffer = encoder.finish();\n    device.queue.submit([commandBuffer]);\n}\n","/// <reference types=\"vite/client\" />\n/// <reference types=\"@webgpu/types\" />\n\nimport type {DdsInfo} from 'dds-parser';\nimport {\n    Model, Node, AnimVector, NodeFlags, Layer, LayerShading, FilterMode,\n    TextureFlags, TVertexAnim, Geoset\n} from '../model';\nimport {vec3, quat, mat3, mat4} from 'gl-matrix';\nimport {mat4fromRotationOrigin, getShader, isWebGL2} from './util';\nimport {ModelInterp} from './modelInterp';\nimport {RendererData, NodeWrapper} from './rendererData';\nimport {ParticlesController} from './particles';\nimport {RibbonsController} from './ribbons';\nimport vertexShaderHardwareSkinningSource from './shaders/webgl/sdHardwareSkinning.vs.glsl?raw';\nimport vertexShaderSoftwareSkinning from './shaders/webgl/sdSoftwareSkinning.vs.glsl?raw';\nimport fragmentShader from './shaders/webgl/sd.fs.glsl?raw';\nimport vertexShaderHDHardwareSkinningOldSource from './shaders/webgl/hdHardwareSkinningOld.vs.glsl?raw';\nimport vertexShaderHDHardwareSkinningNewSource from './shaders/webgl/hdHardwareSkinningNew.vs.glsl?raw';\nimport fragmentShaderHDOld from './shaders/webgl/hdOld.fs.glsl?raw';\nimport fragmentShaderHDNewSource from './shaders/webgl/hdNew.fs.glsl?raw';\nimport skeletonVertexShader from './shaders/webgl/skeleton.vs.glsl?raw';\nimport skeletonFragmentShader from './shaders/webgl/skeleton.fs.glsl?raw';\nimport envToCubemapVertexShader from './shaders/webgl/envToCubemap.vs.glsl?raw';\nimport envToCubemapFragmentShader from './shaders/webgl/envToCubemap.fs.glsl?raw';\nimport envVertexShader from './shaders/webgl/env.vs.glsl?raw';\nimport envFragmentShader from './shaders/webgl/env.fs.glsl?raw';\nimport convoluteEnvDiffuseVertexShader from './shaders/webgl/convoluteEnvDiffuse.vs.glsl?raw';\nimport convoluteEnvDiffuseFragmentShader from './shaders/webgl/convoluteEnvDiffuse.fs.glsl?raw';\nimport prefilterEnvVertexShader from './shaders/webgl/prefilterEnv.vs.glsl?raw';\nimport prefilterEnvFragmentShader from './shaders/webgl/prefilterEnv.fs.glsl?raw';\nimport integrateBRDFVertexShader from './shaders/webgl/integrateBRDF.vs.glsl?raw';\nimport integrateBRDFFragmentShader from './shaders/webgl/integrateBRDF.fs.glsl?raw';\nimport sdShaderSource from './shaders/webgpu/sd.wgsl?raw';\nimport hdShaderSource from './shaders/webgpu/hd.wgsl?raw';\nimport depthShaderSource from './shaders/webgpu/depth.wgsl?raw';\nimport skeletonShaderSource from './shaders/webgpu/skeleton.wgsl?raw';\nimport envShader from './shaders/webgpu/env.wgsl?raw';\nimport envToCubemapShader from './shaders/webgpu/envToCubemap.wgsl?raw';\nimport convoluteEnvDiffuseShader from './shaders/webgpu/convoluteEnvDiffuse.wgsl?raw';\nimport prefilterEnvShader from './shaders/webgpu/prefilterEnv.wgsl?raw';\nimport integrateBRDFFShader from './shaders/webgpu/integrateBRDF.wgsl?raw';\nimport { generateMips } from './generateMips';\n\n// actually, all is number\nexport type DDS_FORMAT = WEBGL_compressed_texture_s3tc['COMPRESSED_RGBA_S3TC_DXT1_EXT'] |\n    WEBGL_compressed_texture_s3tc['COMPRESSED_RGBA_S3TC_DXT3_EXT'] |\n    WEBGL_compressed_texture_s3tc['COMPRESSED_RGBA_S3TC_DXT5_EXT'] |\n    WEBGL_compressed_texture_s3tc['COMPRESSED_RGB_S3TC_DXT1_EXT'];\n\nconst MAX_NODES = 254;\n\nconst ENV_MAP_SIZE = 2048;\nconst ENV_CONVOLUTE_DIFFUSE_SIZE = 32;\nconst ENV_PREFILTER_SIZE = 128;\nconst MAX_ENV_MIP_LEVELS = 8;\nconst BRDF_LUT_SIZE = 512;\n\nconst MULTISAMPLE = 4;\n\nconst FILTER_MODES_WITH_DEPTH_WRITE = new Set([0, 1]);\n\ninterface WebGLProgramObject<A extends string, U extends string> {\n    program: WebGLProgram;\n    vertexShader: WebGLShader;\n    fragmentShader: WebGLShader;\n    attributes: Record<A, GLuint>;\n    uniforms: Record<U, WebGLUniformLocation>;\n}\n\nconst vertexShaderHardwareSkinning = /*#__PURE__*/ vertexShaderHardwareSkinningSource.replace(/\\$\\{MAX_NODES}/g, String(MAX_NODES));\nconst vertexShaderHDHardwareSkinningOld = /*#__PURE__*/ vertexShaderHDHardwareSkinningOldSource.replace(/\\$\\{MAX_NODES}/g, String(MAX_NODES));\nconst vertexShaderHDHardwareSkinningNew = /*#__PURE__*/ vertexShaderHDHardwareSkinningNewSource.replace(/\\$\\{MAX_NODES}/g, String(MAX_NODES));\nconst fragmentShaderHDNew = /*#__PURE__*/ fragmentShaderHDNewSource.replace(/\\$\\{MAX_ENV_MIP_LEVELS}/g, String(MAX_ENV_MIP_LEVELS.toFixed(1)));\nconst sdShader = /*#__PURE__*/ sdShaderSource.replace(/\\$\\{MAX_NODES}/g, String(MAX_NODES));\nconst hdShader = /*#__PURE__*/ hdShaderSource.replace(/\\$\\{MAX_NODES}/g, String(MAX_NODES)).replace(/\\$\\{MAX_ENV_MIP_LEVELS}/g, String(MAX_ENV_MIP_LEVELS.toFixed(1)));\nconst depthShader = /*#__PURE__*/ depthShaderSource.replace(/\\$\\{MAX_NODES}/g, String(MAX_NODES));\n\nconst translation = vec3.create();\nconst rotation = quat.create();\nconst scaling = vec3.create();\n\nconst defaultTranslation = vec3.fromValues(0, 0, 0);\nconst defaultRotation = quat.fromValues(0, 0, 0, 1);\nconst defaultScaling = vec3.fromValues(1, 1, 1);\n\nconst tempParentRotationQuat: quat = quat.create();\nconst tempParentRotationMat: mat4 = mat4.create();\nconst tempCameraMat: mat4 = mat4.create();\nconst tempTransformedPivotPoint: vec3 = vec3.create();\nconst tempAxis: vec3 = vec3.create();\nconst tempLockQuat: quat = quat.create();\nconst tempLockMat: mat4 = mat4.create();\nconst tempXAxis: vec3 = vec3.create();\nconst tempCameraVec: vec3 = vec3.create();\nconst tempCross0: vec3 = vec3.create();\nconst tempCross1: vec3 = vec3.create();\n\nconst tempPos: vec3 = vec3.create();\nconst tempSum: vec3 = vec3.create();\nconst tempVec3: vec3 = vec3.create();\n\nconst identifyMat3: mat3 = mat3.create();\nconst texCoordMat4: mat4 = mat4.create();\nconst texCoordMat3: mat3 = mat3.create();\n\nconst GPU_LAYER_PROPS: [string, GPUBlendState, GPUDepthStencilState][] = [['none', {\n    color: {\n        operation: 'add',\n        srcFactor: 'one',\n        dstFactor: 'zero'\n    },\n    alpha: {\n        operation: 'add',\n        srcFactor: 'one',\n        dstFactor: 'zero'\n    }\n}, {\n    depthWriteEnabled: true,\n    depthCompare: 'less-equal',\n    format: 'depth24plus'\n}], ['transparent', {\n    color: {\n        operation: 'add',\n        srcFactor: 'src-alpha',\n        dstFactor: 'one-minus-src-alpha'\n    },\n    alpha: {\n        operation: 'add',\n        srcFactor: 'one',\n        dstFactor: 'one-minus-src-alpha'\n    }\n}, {\n    depthWriteEnabled: true,\n    depthCompare: 'less-equal',\n    format: 'depth24plus'\n}], ['blend', {\n    color: {\n        operation: 'add',\n        srcFactor: 'src-alpha',\n        dstFactor: 'one-minus-src-alpha'\n    },\n    alpha: {\n        operation: 'add',\n        srcFactor: 'one',\n        dstFactor: 'one-minus-src-alpha'\n    }\n}, {\n    depthWriteEnabled: false,\n    depthCompare: 'less-equal',\n    format: 'depth24plus'\n}], ['additive', {\n    color: {\n        operation: 'add',\n        srcFactor: 'src',\n        dstFactor: 'one'\n    },\n    alpha: {\n        operation: 'add',\n        srcFactor: 'src',\n        dstFactor: 'one'\n    }\n}, {\n    depthWriteEnabled: false,\n    depthCompare: 'less-equal',\n    format: 'depth24plus'\n}], ['addAlpha', {\n    color: {\n        operation: 'add',\n        srcFactor: 'src-alpha',\n        dstFactor: 'one'\n    },\n    alpha: {\n        operation: 'add',\n        srcFactor: 'src-alpha',\n        dstFactor: 'one'\n    }\n}, {\n    depthWriteEnabled: false,\n    depthCompare: 'less-equal',\n    format: 'depth24plus'\n}], ['modulate', {\n    color: {\n        operation: 'add',\n        srcFactor: 'zero',\n        dstFactor: 'src'\n    },\n    alpha: {\n        operation: 'add',\n        srcFactor: 'zero',\n        dstFactor: 'one'\n    }\n}, {\n    depthWriteEnabled: false,\n    depthCompare: 'less-equal',\n    format: 'depth24plus'\n}], ['modulate2x', {\n    color: {\n        operation: 'add',\n        srcFactor: 'dst',\n        dstFactor: 'src'\n    },\n    alpha: {\n        operation: 'add',\n        srcFactor: 'zero',\n        dstFactor: 'one'\n    }\n}, {\n    depthWriteEnabled: false,\n    depthCompare: 'less-equal',\n    format: 'depth24plus'\n}]];\n\nexport class ModelRenderer {\n    private isHD: boolean;\n\n    private canvas: HTMLCanvasElement;\n    private gl: WebGL2RenderingContext | WebGLRenderingContext;\n    private device: GPUDevice;\n    private gpuContext: GPUCanvasContext;\n    private anisotropicExt: EXT_texture_filter_anisotropic | null;\n    private colorBufferFloatExt: EXT_color_buffer_float | null;\n    private vertexShader: WebGLShader | null;\n    private fragmentShader: WebGLShader | null;\n    private shaderProgram: WebGLProgram | null;\n    private vsBindGroupLayout: GPUBindGroupLayout | null;\n    private fsBindGroupLayout: GPUBindGroupLayout | null;\n    private gpuShaderModule: GPUShaderModule | null;\n    private gpuDepthShaderModule: GPUShaderModule | null;\n    private gpuPipelines: Record<string, GPURenderPipeline> = {};\n    private gpuWireframePipeline: GPURenderPipeline | null;\n    private gpuShadowPipeline: GPURenderPipeline | null;\n    private gpuPipelineLayout: GPUPipelineLayout | null;\n    private gpuRenderPassDescriptor: GPURenderPassDescriptor | null;\n    private shaderProgramLocations: {\n        vertexPositionAttribute: number | null;\n        normalsAttribute: number | null;\n        textureCoordAttribute: number | null;\n        groupAttribute: number | null;\n        skinAttribute: number | null;\n        weightAttribute: number | null;\n        tangentAttribute: number | null;\n        pMatrixUniform: WebGLUniformLocation | null;\n        mvMatrixUniform: WebGLUniformLocation | null;\n        samplerUniform: WebGLUniformLocation | null;\n        normalSamplerUniform: WebGLUniformLocation | null;\n        ormSamplerUniform: WebGLUniformLocation | null;\n        replaceableColorUniform: WebGLUniformLocation | null;\n        replaceableTypeUniform: WebGLUniformLocation | null;\n        discardAlphaLevelUniform: WebGLUniformLocation | null;\n        tVertexAnimUniform: WebGLUniformLocation | null;\n        wireframeUniform: WebGLUniformLocation | null;\n        nodesMatricesAttributes: (WebGLUniformLocation | null)[];\n        lightPosUniform: WebGLUniformLocation | null;\n        lightColorUniform: WebGLUniformLocation | null;\n        cameraPosUniform: WebGLUniformLocation | null;\n        shadowParamsUniform: WebGLUniformLocation | null;\n        shadowMapSamplerUniform: WebGLUniformLocation | null;\n        shadowMapLightMatrixUniform: WebGLUniformLocation | null;\n        hasEnvUniform: WebGLUniformLocation | null;\n        irradianceMapUniform: WebGLUniformLocation | null;\n        prefilteredEnvUniform: WebGLUniformLocation | null;\n        brdfLUTUniform: WebGLUniformLocation | null;\n    };\n    private skeletonShaderProgram: WebGLProgram | null;\n    private skeletonVertexShader: WebGLShader | null;\n    private skeletonFragmentShader: WebGLShader | null;\n    private skeletonShaderProgramLocations: {\n        vertexPositionAttribute: number | null;\n        colorAttribute: number | null;\n        pMatrixUniform: WebGLUniformLocation | null;\n        mvMatrixUniform: WebGLUniformLocation | null;\n    };\n    private skeletonVertexBuffer: WebGLBuffer | null;\n    private skeletonColorBuffer: WebGLBuffer | null;\n    private skeletonShaderModule: GPUShaderModule;\n    private skeletonBindGroupLayout: GPUBindGroupLayout;\n    private skeletonPipelineLayout: GPUPipelineLayout;\n    private skeletonPipeline: GPURenderPipeline;\n    private skeletonGPUVertexBuffer: GPUBuffer;\n    private skeletonGPUColorBuffer: GPUBuffer;\n    private skeletonGPUUniformsBuffer: GPUBuffer;\n\n    private model: Model;\n    private interp: ModelInterp;\n    private rendererData: RendererData;\n    private particlesController: ParticlesController;\n    private ribbonsController: RibbonsController;\n\n    private softwareSkinning: boolean;\n    private vertexBuffer: WebGLBuffer[] = [];\n    private normalBuffer: WebGLBuffer[] = [];\n    private vertices: Float32Array[] = []; // Array per geoset for software skinning\n    private texCoordBuffer: WebGLBuffer[] = [];\n    private indexBuffer: WebGLBuffer[] = [];\n    private wireframeIndexBuffer: WebGLBuffer[] = [];\n    private wireframeIndexGPUBuffer: GPUBuffer[] = [];\n    private groupBuffer: WebGLBuffer[] = [];\n    private skinWeightBuffer: WebGLBuffer[] = [];\n    private tangentBuffer: WebGLBuffer[] = [];\n\n    private envShaderModeule: GPUShaderModule;\n    private envPiepeline: GPURenderPipeline;\n    private envVSBindGroupLayout: GPUBindGroupLayout | null;\n    private envFSBindGroupLayout: GPUBindGroupLayout | null;\n    private envVSUniformsBuffer: GPUBuffer;\n    private envVSBindGroup: GPUBindGroup;\n    private envSampler: GPUSampler;\n    private cubeVertexBuffer: WebGLBuffer;\n    private cubeGPUVertexBuffer: GPUBuffer;\n    private squareVertexBuffer: WebGLBuffer;\n    private brdfLUT: WebGLTexture;\n    private gpuBrdfLUT: GPUTexture;\n    private gpuBrdfSampler: GPUSampler;\n\n    private envToCubemap: WebGLProgramObject<'aPos', 'uPMatrix' | 'uMVMatrix' | 'uEquirectangularMap'>;\n    private envToCubemapShaderModule: GPUShaderModule;\n    private envToCubemapPiepeline: GPURenderPipeline;\n    private envToCubemapVSBindGroupLayout: GPUBindGroupLayout | null;\n    private envToCubemapFSBindGroupLayout: GPUBindGroupLayout | null;\n    private envToCubemapSampler: GPUSampler;\n    private envSphere: WebGLProgramObject<'aPos', 'uPMatrix' | 'uMVMatrix' | 'uEnvironmentMap'>;\n    private convoluteDiffuseEnv: WebGLProgramObject<'aPos', 'uPMatrix' | 'uMVMatrix' | 'uEnvironmentMap'>;\n    private convoluteDiffuseEnvShaderModule: GPUShaderModule;\n    private convoluteDiffuseEnvPiepeline: GPURenderPipeline;\n    private convoluteDiffuseEnvVSBindGroupLayout: GPUBindGroupLayout | null;\n    private convoluteDiffuseEnvFSBindGroupLayout: GPUBindGroupLayout | null;\n    private convoluteDiffuseEnvSampler: GPUSampler;\n    private prefilterEnv: WebGLProgramObject<'aPos', 'uPMatrix' | 'uMVMatrix' | 'uEnvironmentMap' | 'uRoughness'>;\n    private prefilterEnvShaderModule: GPUShaderModule;\n    private prefilterEnvPiepeline: GPURenderPipeline;\n    private prefilterEnvVSBindGroupLayout: GPUBindGroupLayout | null;\n    private prefilterEnvFSBindGroupLayout: GPUBindGroupLayout | null;\n    private prefilterEnvSampler: GPUSampler;\n    private integrateBRDF: WebGLProgramObject<'aPos', never>;\n\n    private gpuMultisampleTexture: GPUTexture;\n    private gpuDepthTexture: GPUTexture;\n    private gpuVertexBuffer: GPUBuffer[] = [];\n    private gpuNormalBuffer: GPUBuffer[] = [];\n    private gpuTexCoordBuffer: GPUBuffer[] = [];\n    private gpuGroupBuffer: GPUBuffer[] = [];\n    private gpuIndexBuffer: GPUBuffer[] = [];\n    private gpuSkinWeightBuffer: GPUBuffer[] = [];\n    private gpuTangentBuffer: GPUBuffer[] = [];\n    private gpuVSUniformsBuffer: GPUBuffer;\n    private gpuVSUniformsBindGroup: GPUBindGroup;\n    private gpuFSUniformsBuffers: GPUBuffer[][] = [];\n\n    constructor(model: Model) {\n        this.isHD = model.Geosets?.some(it => it.SkinWeights?.length > 0);\n\n        this.shaderProgramLocations = {\n            vertexPositionAttribute: null,\n            normalsAttribute: null,\n            textureCoordAttribute: null,\n            groupAttribute: null,\n            skinAttribute: null,\n            weightAttribute: null,\n            tangentAttribute: null,\n            pMatrixUniform: null,\n            mvMatrixUniform: null,\n            samplerUniform: null,\n            normalSamplerUniform: null,\n            ormSamplerUniform: null,\n            replaceableColorUniform: null,\n            replaceableTypeUniform: null,\n            discardAlphaLevelUniform: null,\n            tVertexAnimUniform: null,\n            wireframeUniform: null,\n            nodesMatricesAttributes: null,\n            lightPosUniform: null,\n            lightColorUniform: null,\n            cameraPosUniform: null,\n            shadowParamsUniform: null,\n            shadowMapSamplerUniform: null,\n            shadowMapLightMatrixUniform: null,\n            hasEnvUniform: null,\n            irradianceMapUniform: null,\n            prefilteredEnvUniform: null,\n            brdfLUTUniform: null\n        };\n        this.skeletonShaderProgramLocations = {\n            vertexPositionAttribute: null,\n            colorAttribute: null,\n            mvMatrixUniform: null,\n            pMatrixUniform: null\n        };\n\n        this.model = model;\n\n        this.rendererData = {\n            model,\n            frame: 0,\n            animation: null,\n            animationInfo: null,\n            globalSequencesFrames: [],\n            rootNode: null,\n            nodes: [],\n            geosetAnims: [],\n            geosetAlpha: [],\n            materialLayerTextureID: [],\n            materialLayerNormalTextureID: [],\n            materialLayerOrmTextureID: [],\n            materialLayerReflectionTextureID: [],\n            teamColor: null,\n            cameraPos: null,\n            cameraQuat: null,\n            lightPos: null,\n            lightColor: null,\n            shadowBias: 0,\n            shadowSmoothingStep: 0,\n            textures: {},\n            gpuTextures: {},\n            gpuSamplers: [],\n            gpuDepthSampler: null,\n            gpuEmptyTexture: null,\n            gpuEmptyCubeTexture: null,\n            gpuDepthEmptyTexture: null,\n            envTextures: {},\n            gpuEnvTextures: {},\n            requiredEnvMaps: {},\n            irradianceMap: {},\n            gpuIrradianceMap: {},\n            prefilteredEnvMap: {},\n            gpuPrefilteredEnvMap: {}\n        };\n\n        this.rendererData.teamColor = vec3.fromValues(1., 0., 0.);\n        this.rendererData.cameraPos = vec3.create();\n        this.rendererData.cameraQuat = quat.create();\n        this.rendererData.lightPos = vec3.fromValues(1000, 1000, 1000);\n        this.rendererData.lightColor = vec3.fromValues(1, 1, 1);\n\n        this.setSequence(0);\n\n        this.rendererData.rootNode = {\n            // todo\n            node: {} as Node,\n            matrix: mat4.create(),\n            childs: []\n        };\n        for (const node of model.Nodes) {\n            if (node) {\n                this.rendererData.nodes[node.ObjectId] = {\n                    node,\n                    matrix: mat4.create(),\n                    childs: []\n                };\n            }\n        }\n        for (const node of model.Nodes) {\n            if (node) {\n                if (!node.Parent && node.Parent !== 0) {\n                    this.rendererData.rootNode.childs.push(this.rendererData.nodes[node.ObjectId]);\n                } else {\n                    this.rendererData.nodes[node.Parent].childs.push(this.rendererData.nodes[node.ObjectId]);\n                }\n            }\n        }\n\n        if (model.GlobalSequences) {\n            for (let i = 0; i < model.GlobalSequences.length; ++i) {\n                this.rendererData.globalSequencesFrames[i] = 0;\n            }\n        }\n\n        for (let i = 0; i < model.GeosetAnims.length; ++i) {\n            this.rendererData.geosetAnims[model.GeosetAnims[i].GeosetId] = model.GeosetAnims[i];\n        }\n\n        for (let i = 0; i < model.Materials.length; ++i) {\n            this.rendererData.materialLayerTextureID[i] = new Array(model.Materials[i].Layers.length);\n            this.rendererData.materialLayerNormalTextureID[i] = new Array(model.Materials[i].Layers.length);\n            this.rendererData.materialLayerOrmTextureID[i] = new Array(model.Materials[i].Layers.length);\n            this.rendererData.materialLayerReflectionTextureID[i] = new Array(model.Materials[i].Layers.length);\n        }\n\n        this.interp = new ModelInterp(this.rendererData);\n        this.particlesController = new ParticlesController(this.interp, this.rendererData);\n        this.ribbonsController = new RibbonsController(this.interp, this.rendererData);\n    }\n\n    public destroy (): void {\n        if (this.particlesController) {\n            this.particlesController.destroy();\n            this.particlesController = null;\n        }\n        if (this.ribbonsController) {\n            this.ribbonsController.destroy();\n            this.ribbonsController = null;\n        }\n\n        if (this.device) {\n            for (const buffer of this.wireframeIndexGPUBuffer) {\n                buffer.destroy();\n            }\n            this.gpuMultisampleTexture?.destroy();\n            this.gpuDepthTexture?.destroy();\n\n            for (const buffer of this.gpuVertexBuffer) {\n                buffer.destroy();\n            }\n            for (const buffer of this.gpuNormalBuffer) {\n                buffer.destroy();\n            }\n            for (const buffer of this.gpuTexCoordBuffer) {\n                buffer.destroy();\n            }\n            for (const buffer of this.gpuGroupBuffer) {\n                buffer.destroy();\n            }\n            for (const buffer of this.gpuIndexBuffer) {\n                buffer.destroy();\n            }\n            for (const buffer of this.gpuSkinWeightBuffer) {\n                buffer.destroy();\n            }\n            for (const buffer of this.gpuTangentBuffer) {\n                buffer.destroy();\n            }\n            this.gpuVSUniformsBuffer?.destroy();\n            for (const materialID in this.gpuFSUniformsBuffers) {\n                for (const buffer of this.gpuFSUniformsBuffers[materialID]) {\n                    buffer.destroy();\n                }\n            }\n\n            if (this.skeletonGPUVertexBuffer) {\n                this.skeletonGPUVertexBuffer.destroy();\n                this.skeletonGPUVertexBuffer = null;\n            }\n            if (this.skeletonGPUColorBuffer) {\n                this.skeletonGPUColorBuffer.destroy();\n                this.skeletonGPUColorBuffer = null;\n            }\n            if (this.skeletonGPUUniformsBuffer) {\n                this.skeletonGPUUniformsBuffer.destroy();\n                this.skeletonGPUUniformsBuffer = null;\n            }\n            if (this.envVSUniformsBuffer) {\n                this.envVSUniformsBuffer.destroy();\n                this.envVSUniformsBuffer = null;\n            }\n            if (this.cubeGPUVertexBuffer) {\n                this.cubeGPUVertexBuffer.destroy();\n                this.cubeGPUVertexBuffer = null;\n            }\n            for (const buffer of this.wireframeIndexGPUBuffer) {\n                buffer?.destroy();\n            }\n        }\n\n        if (this.gl) {\n            if (this.skeletonShaderProgram) {\n                if (this.skeletonVertexShader) {\n                    this.gl.detachShader(this.skeletonShaderProgram, this.skeletonVertexShader);\n                    this.gl.deleteShader(this.skeletonVertexShader);\n                    this.skeletonVertexShader = null;\n                }\n                if (this.skeletonFragmentShader) {\n                    this.gl.detachShader(this.skeletonShaderProgram, this.skeletonFragmentShader);\n                    this.gl.deleteShader(this.skeletonFragmentShader);\n                    this.skeletonFragmentShader = null;\n                }\n                this.gl.deleteProgram(this.skeletonShaderProgram);\n                this.skeletonShaderProgram = null;\n            }\n\n            if (this.shaderProgram) {\n                if (this.vertexShader) {\n                    this.gl.detachShader(this.shaderProgram, this.vertexShader);\n                    this.gl.deleteShader(this.vertexShader);\n                    this.vertexShader = null;\n                }\n                if (this.fragmentShader) {\n                    this.gl.detachShader(this.shaderProgram, this.fragmentShader);\n                    this.gl.deleteShader(this.fragmentShader);\n                    this.fragmentShader = null;\n                }\n                this.gl.deleteProgram(this.shaderProgram);\n                this.shaderProgram = null;\n            }\n\n            this.destroyShaderProgramObject(this.envToCubemap);\n            this.destroyShaderProgramObject(this.envSphere);\n            this.destroyShaderProgramObject(this.convoluteDiffuseEnv);\n            this.destroyShaderProgramObject(this.prefilterEnv);\n            this.destroyShaderProgramObject(this.integrateBRDF);\n\n            this.gl.deleteBuffer(this.cubeVertexBuffer);\n            this.gl.deleteBuffer(this.squareVertexBuffer);\n        }\n    }\n\n    private initRequiredEnvMaps (): void {\n        if (this.model.Version >= 1000 && (isWebGL2(this.gl) || this.device)) {\n            this.model.Materials.forEach(material => {\n                let layer;\n                if (\n                    material.Shader === 'Shader_HD_DefaultUnit' && material.Layers.length === 6 && typeof material.Layers[5].TextureID === 'number' ||\n                    this.model.Version >= 1100 && (layer = material.Layers.find(it => it.ShaderTypeId === 1 && it.ReflectionsTextureID)) && typeof layer.ReflectionsTextureID === 'number'\n                ) {\n                    const id = this.model.Version >= 1100 && layer ? layer.ReflectionsTextureID : material.Layers[5].TextureID;\n                    this.rendererData.requiredEnvMaps[this.model.Textures[id].Image] = true;\n                }\n            });\n        }\n    }\n\n    public initGL (glContext: WebGL2RenderingContext | WebGLRenderingContext): void {\n        this.gl = glContext;\n        // Max bones + MV + P\n        this.softwareSkinning = this.gl.getParameter(this.gl.MAX_VERTEX_UNIFORM_VECTORS) < 4 * (MAX_NODES + 2);\n        this.anisotropicExt = (\n            this.gl.getExtension('EXT_texture_filter_anisotropic') ||\n            this.gl.getExtension('MOZ_EXT_texture_filter_anisotropic') ||\n            this.gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic')\n        );\n        this.colorBufferFloatExt = this.gl.getExtension('EXT_color_buffer_float');\n\n        this.initRequiredEnvMaps();\n\n        this.initShaders();\n        this.initBuffers();\n        this.initCube();\n        this.initSquare();\n        this.initBRDFLUT();\n        this.particlesController.initGL(glContext);\n        this.ribbonsController.initGL(glContext);\n    }\n\n    public async initGPUDevice (canvas: HTMLCanvasElement, device: GPUDevice, context: GPUCanvasContext): Promise<void> {\n        this.canvas = canvas;\n        this.device = device;\n        this.gpuContext = context;\n\n        this.initRequiredEnvMaps();\n\n        this.initGPUShaders();\n        this.initGPUPipeline();\n        this.initGPUBuffers();\n        this.initGPUUniformBuffers();\n        this.initGPUMultisampleTexture();\n        this.initGPUDepthTexture();\n        this.initGPUEmptyTexture();\n        this.initCube();\n        this.initGPUBRDFLUT();\n        this.particlesController.initGPUDevice(device);\n        this.ribbonsController.initGPUDevice(device);\n    }\n\n    public setTextureImage (path: string, img: HTMLImageElement): void {\n        if (this.device) {\n            const texture = this.rendererData.gpuTextures[path] = this.device.createTexture({\n                size: [img.width, img.height],\n                format: 'rgba8unorm',\n                usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT\n            });\n            this.device.queue.copyExternalImageToTexture(\n                {\n                    source: img\n                },\n                { texture },\n                {\n                    width: img.width,\n                    height: img.height\n                }\n            );\n            generateMips(this.device, texture);\n            this.processEnvMaps(path);\n        } else {\n            this.rendererData.textures[path] = this.gl.createTexture();\n            this.gl.bindTexture(this.gl.TEXTURE_2D, this.rendererData.textures[path]);\n            // this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n            this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, img);\n            const flags = this.model.Textures.find(it => it.Image === path)?.Flags || 0;\n            this.setTextureParameters(flags, true);\n\n            this.gl.generateMipmap(this.gl.TEXTURE_2D);\n\n            this.processEnvMaps(path);\n\n            this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n        }\n    }\n\n    public setTextureImageData (path: string, imageData: ImageData[]): void {\n        let count = 1;\n        for (let i = 1; i < imageData.length; ++i, ++count) {\n            if (\n                imageData[i].width !== imageData[i - 1].width / 2 ||\n                imageData[i].height !== imageData[i - 1].height / 2\n            ) {\n                break;\n            }\n        }\n\n        if (this.device) {\n            const texture = this.rendererData.gpuTextures[path] = this.device.createTexture({\n                size: [imageData[0].width, imageData[0].height],\n                format: 'rgba8unorm',\n                usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n                mipLevelCount: count\n            });\n            for (let i = 0; i < count; ++i) {\n                this.device.queue.writeTexture(\n                    {\n                        texture,\n                        mipLevel: i\n                    },\n                    imageData[i].data,\n                    { bytesPerRow: imageData[i].width * 4 },\n                    { width: imageData[i].width, height: imageData[i].height },\n                );\n            }\n            this.processEnvMaps(path);\n        } else {\n            this.rendererData.textures[path] = this.gl.createTexture();\n            this.gl.bindTexture(this.gl.TEXTURE_2D, this.rendererData.textures[path]);\n            // this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n            for (let i = 0; i < count; ++i) {\n                this.gl.texImage2D(this.gl.TEXTURE_2D, i, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, imageData[i]);\n            }\n            const flags = this.model.Textures.find(it => it.Image === path)?.Flags || 0;\n            this.setTextureParameters(flags, false);\n            this.processEnvMaps(path);\n\n            this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n        }\n    }\n\n    public setTextureCompressedImage (path: string, format: DDS_FORMAT, imageData: ArrayBuffer, ddsInfo: DdsInfo): void {\n        this.rendererData.textures[path] = this.gl.createTexture();\n        this.gl.bindTexture(this.gl.TEXTURE_2D, this.rendererData.textures[path]);\n\n        const view = new Uint8Array(imageData);\n\n        let count = 1;\n        for (let i = 1; i < ddsInfo.images.length; ++i) {\n            const image = ddsInfo.images[i];\n            if (image.shape.width >= 2 && image.shape.height >= 2) {\n                count = i + 1;\n            }\n        }\n\n        if (isWebGL2(this.gl)) {\n            this.gl.texStorage2D(this.gl.TEXTURE_2D, count, format, ddsInfo.images[0].shape.width, ddsInfo.images[0].shape.height);\n\n            for (let i = 0; i < count; ++i) {\n                const image = ddsInfo.images[i];\n                this.gl.compressedTexSubImage2D(this.gl.TEXTURE_2D, i, 0, 0, image.shape.width, image.shape.height, format, view.subarray(image.offset, image.offset + image.length));\n            }\n        } else {\n            for (let i = 0; i < count; ++i) {\n                const image = ddsInfo.images[i];\n                this.gl.compressedTexImage2D(this.gl.TEXTURE_2D, i, format, image.shape.width, image.shape.height, 0, view.subarray(image.offset, image.offset + image.length));\n            }\n        }\n\n        const flags = this.model.Textures.find(it => it.Image === path)?.Flags || 0;\n        this.setTextureParameters(flags, isWebGL2(this.gl));\n        this.processEnvMaps(path);\n\n        this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n    }\n\n    public setGPUTextureCompressedImage (path: string, format: GPUTextureFormat, imageData: ArrayBuffer, ddsInfo: DdsInfo): void {\n        const view = new Uint8Array(imageData);\n\n        let count = 1;\n        for (let i = 1; i < ddsInfo.images.length; ++i) {\n            const image = ddsInfo.images[i];\n            if (image.shape.width >= 4 && image.shape.height >= 4) {\n                count = i + 1;\n            }\n        }\n        const texture = this.rendererData.gpuTextures[path] = this.device.createTexture({\n            size: [ddsInfo.shape.width, ddsInfo.shape.height],\n            format,\n            usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n            mipLevelCount: count\n        });\n        for (let i = 0; i < count; ++i) {\n            const image = ddsInfo.images[i];\n            this.device.queue.writeTexture(\n                {\n                    texture,\n                    mipLevel: i\n                },\n                view.subarray(image.offset, image.offset + image.length),\n                { bytesPerRow: image.shape.width * (format === 'bc1-rgba-unorm' ? 2 : 4) },\n                { width: image.shape.width, height: image.shape.height },\n            );\n        }\n\n        this.processEnvMaps(path);\n    }\n\n    public setCamera (cameraPos: vec3, cameraQuat: quat): void {\n        vec3.copy(this.rendererData.cameraPos, cameraPos);\n        quat.copy(this.rendererData.cameraQuat, cameraQuat);\n    }\n\n    public setLightPosition (lightPos: vec3): void {\n        vec3.copy(this.rendererData.lightPos, lightPos);\n    }\n\n    public setLightColor (lightColor: vec3): void {\n        vec3.copy(this.rendererData.lightColor, lightColor);\n    }\n\n    public setSequence (index: number): void {\n        this.rendererData.animation = index;\n        this.rendererData.animationInfo = this.model.Sequences[this.rendererData.animation];\n        this.rendererData.frame = this.rendererData.animationInfo.Interval[0];\n    }\n\n    public getSequence (): number {\n        return this.rendererData.animation;\n    }\n\n    public setFrame (frame: number): void {\n        const index = this.model.Sequences.findIndex(it => it.Interval[0] <= frame && it.Interval[1] >= frame);\n\n        if (index < 0) {\n            return;\n        }\n\n        this.rendererData.animation = index;\n        this.rendererData.animationInfo = this.model.Sequences[this.rendererData.animation];\n        this.rendererData.frame = frame;\n    }\n\n    public getFrame (): number {\n        return this.rendererData.frame;\n    }\n\n    public setTeamColor (color: vec3): void {\n        vec3.copy(this.rendererData.teamColor, color);\n    }\n\n    public update (delta: number): void {\n        this.rendererData.frame += delta;\n        if (this.rendererData.frame > this.rendererData.animationInfo.Interval[1]) {\n            this.rendererData.frame = this.rendererData.animationInfo.Interval[0];\n        }\n        this.updateGlobalSequences(delta);\n\n        this.updateNode(this.rendererData.rootNode);\n\n        this.particlesController.update(delta);\n        this.ribbonsController.update(delta);\n\n        for (let i = 0; i < this.model.Geosets.length; ++i) {\n            this.rendererData.geosetAlpha[i] = this.findAlpha(i);\n        }\n\n        for (let materialId = 0; materialId < this.rendererData.materialLayerTextureID.length; ++materialId) {\n            for (let layerId = 0; layerId < this.rendererData.materialLayerTextureID[materialId].length; ++layerId) {\n                const layer = this.model.Materials[materialId].Layers[layerId];\n                const TextureID: AnimVector|number = layer.TextureID;\n                const NormalTextureID: AnimVector|number = layer.NormalTextureID;\n                const ORMTextureID: AnimVector|number = layer.ORMTextureID;\n                const ReflectionsTextureID: AnimVector|number = layer.ReflectionsTextureID;\n\n                if (typeof TextureID === 'number') {\n                    this.rendererData.materialLayerTextureID[materialId][layerId] = TextureID;\n                } else {\n                    this.rendererData.materialLayerTextureID[materialId][layerId] = this.interp.num(TextureID);\n                }\n                if (typeof NormalTextureID !== 'undefined') {\n                    this.rendererData.materialLayerNormalTextureID[materialId][layerId] = typeof NormalTextureID === 'number' ? NormalTextureID : this.interp.num(NormalTextureID);\n                }\n                if (typeof ORMTextureID !== 'undefined') {\n                    this.rendererData.materialLayerOrmTextureID[materialId][layerId] = typeof ORMTextureID === 'number' ? ORMTextureID : this.interp.num(ORMTextureID);\n                }\n                if (typeof ReflectionsTextureID !== 'undefined') {\n                    this.rendererData.materialLayerReflectionTextureID[materialId][layerId] = typeof ReflectionsTextureID === 'number' ? ReflectionsTextureID : this.interp.num(ReflectionsTextureID);\n                }\n            }\n        }\n    }\n\n    public render (mvMatrix: mat4, pMatrix: mat4, {\n        wireframe,\n        env,\n        levelOfDetail = 0,\n        useEnvironmentMap = false,\n        shadowMapTexture,\n        shadowMapMatrix,\n        shadowBias,\n        shadowSmoothingStep,\n        depthTextureTarget\n    } : {\n        wireframe?: boolean;\n        env?: boolean;\n        levelOfDetail?: number;\n        useEnvironmentMap?: boolean;\n        shadowMapTexture?: WebGLTexture | GPUTexture;\n        shadowMapMatrix?: mat4;\n        shadowBias?: number;\n        shadowSmoothingStep?: number;\n        depthTextureTarget?: GPUTexture;\n    }): void {\n        if (depthTextureTarget && !this.isHD) {\n            return;\n        }\n\n        if (this.device) {\n            if (this.gpuMultisampleTexture.width !== this.canvas.width || this.gpuMultisampleTexture.height !== this.canvas.height) {\n                this.gpuMultisampleTexture.destroy();\n                this.initGPUMultisampleTexture();\n            }\n\n            if (this.gpuDepthTexture.width !== this.canvas.width || this.gpuDepthTexture.height !== this.canvas.height) {\n                this.gpuDepthTexture.destroy();\n                this.initGPUDepthTexture();\n            }\n\n            let renderPassDescriptor: GPURenderPassDescriptor;\n            if (depthTextureTarget) {\n                renderPassDescriptor = {\n                    label: 'shadow renderPass',\n                    colorAttachments: [],\n                    depthStencilAttachment: {\n                        view: depthTextureTarget.createView(),\n                        depthClearValue: 1,\n                        depthLoadOp: 'clear',\n                        depthStoreOp: 'store'\n                    }\n                };\n            } else {\n                renderPassDescriptor = this.gpuRenderPassDescriptor;\n                if (MULTISAMPLE > 1) {\n                    this.gpuRenderPassDescriptor.colorAttachments[0].view =\n                        this.gpuMultisampleTexture.createView();\n                    this.gpuRenderPassDescriptor.colorAttachments[0].resolveTarget =\n                        this.gpuContext.getCurrentTexture().createView();\n                } else {\n                    this.gpuRenderPassDescriptor.colorAttachments[0].view =\n                        this.gpuContext.getCurrentTexture().createView();\n                }\n\n                this.gpuRenderPassDescriptor.depthStencilAttachment = {\n                    view: this.gpuDepthTexture.createView(),\n                    depthClearValue: 1,\n                    depthLoadOp: 'clear',\n                    depthStoreOp: 'store'\n                };\n            }\n\n            const encoder = this.device.createCommandEncoder();\n            const pass = encoder.beginRenderPass(renderPassDescriptor);\n\n            if (env) {\n                this.renderEnvironmentGPU(pass, mvMatrix, pMatrix);\n            }\n\n            const VSUniformsValues = new ArrayBuffer(128 + 64 * MAX_NODES);\n            const VSUniformsViews = {\n                mvMatrix: new Float32Array(VSUniformsValues, 0, 16),\n                pMatrix: new Float32Array(VSUniformsValues, 64, 16),\n                nodesMatrices: new Float32Array(VSUniformsValues, 128, 16 * MAX_NODES),\n            };\n            VSUniformsViews.mvMatrix.set(mvMatrix);\n            VSUniformsViews.pMatrix.set(pMatrix);\n            for (let j = 0; j < MAX_NODES; ++j) {\n                if (this.rendererData.nodes[j]) {\n                    VSUniformsViews.nodesMatrices.set(this.rendererData.nodes[j].matrix, j * 16);\n                }\n            }\n            this.device.queue.writeBuffer(this.gpuVSUniformsBuffer, 0, VSUniformsValues);\n\n            for (let i = 0; i < this.model.Geosets.length; ++i) {\n                const geoset = this.model.Geosets[i];\n                if (this.rendererData.geosetAlpha[i] < 1e-6) {\n                    continue;\n                }\n                if (geoset.LevelOfDetail !== undefined && geoset.LevelOfDetail !== levelOfDetail) {\n                    continue;\n                }\n\n                if (wireframe && !this.wireframeIndexGPUBuffer[i]) {\n                    this.createWireframeGPUBuffer(i);\n                }\n\n                const materialID = geoset.MaterialID;\n                const material = this.model.Materials[materialID];\n\n                pass.setVertexBuffer(0, this.gpuVertexBuffer[i]);\n                pass.setVertexBuffer(1, this.gpuNormalBuffer[i]);\n                pass.setVertexBuffer(2, this.gpuTexCoordBuffer[i]);\n\n                if (this.isHD) {\n                    pass.setVertexBuffer(3, this.gpuTangentBuffer[i]);\n                    pass.setVertexBuffer(4, this.gpuSkinWeightBuffer[i]);\n                    pass.setVertexBuffer(5, this.gpuSkinWeightBuffer[i]);\n                } else {\n                    pass.setVertexBuffer(3, this.gpuGroupBuffer[i]);\n                }\n\n                pass.setIndexBuffer(wireframe ? this.wireframeIndexGPUBuffer[i] : this.gpuIndexBuffer[i], 'uint16');\n\n                if (this.isHD) {\n                    const baseLayer = material.Layers[0];\n                    if (depthTextureTarget && !FILTER_MODES_WITH_DEPTH_WRITE.has(baseLayer.FilterMode || 0)) {\n                        continue;\n                    }\n                    const pipeline = depthTextureTarget ?\n                        this.gpuShadowPipeline :\n                        (wireframe ? this.gpuWireframePipeline : this.getGPUPipeline(baseLayer));\n                    pass.setPipeline(pipeline);\n\n                    const textures = this.rendererData.materialLayerTextureID[materialID];\n                    const normalTextres = this.rendererData.materialLayerNormalTextureID[materialID];\n                    const ormTextres = this.rendererData.materialLayerOrmTextureID[materialID];\n                    const envTextres = this.rendererData.materialLayerReflectionTextureID[materialID];\n                    const diffuseTextureID = textures[0];\n                    const diffuseTexture = this.model.Textures[diffuseTextureID];\n                    const normalTextureID = baseLayer?.ShaderTypeId === 1 ? normalTextres[0] : textures[1];\n                    const normalTexture = this.model.Textures[normalTextureID];\n                    const ormTextureID = baseLayer?.ShaderTypeId === 1 ? ormTextres[0] : textures[2];\n                    const ormTexture = this.model.Textures[ormTextureID];\n                    const envTextureID = baseLayer?.ShaderTypeId === 1 ? envTextres[0] : textures[5];\n                    const envTexture = this.model.Textures[envTextureID];\n\n                    const envTextureImage = envTexture?.Image;\n                    const irradianceMap = this.rendererData.gpuIrradianceMap[envTextureImage];\n                    const prefilteredEnv = this.rendererData.gpuPrefilteredEnvMap[envTextureImage];\n\n                    const hasEnv = env && irradianceMap && prefilteredEnv;\n\n                    this.gpuFSUniformsBuffers[materialID] ||= [];\n                    let gpuFSUniformsBuffer = this.gpuFSUniformsBuffers[materialID][0];\n\n                    if (!gpuFSUniformsBuffer) {\n                        gpuFSUniformsBuffer = this.gpuFSUniformsBuffers[materialID][0] = this.device.createBuffer({\n                            label: `fs uniforms ${materialID}`,\n                            size: 192,\n                            usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n                        });\n                    }\n\n                    const tVetexAnim = this.getTexCoordMatrix(baseLayer);\n\n                    const FSUniformsValues = new ArrayBuffer(192);\n                    const FSUniformsViews = {\n                        replaceableColor: new Float32Array(FSUniformsValues, 0, 3),\n                        discardAlphaLevel: new Float32Array(FSUniformsValues, 12, 1),\n                        tVertexAnim: new Float32Array(FSUniformsValues, 16, 12),\n                        lightPos: new Float32Array(FSUniformsValues, 64, 3),\n                        hasEnv: new Uint32Array(FSUniformsValues, 76, 1),\n                        lightColor: new Float32Array(FSUniformsValues, 80, 3),\n                        wireframe: new Uint32Array(FSUniformsValues, 92, 1),\n                        cameraPos: new Float32Array(FSUniformsValues, 96, 3),\n                        shadowParams: new Float32Array(FSUniformsValues, 112, 3),\n                        shadowMapLightMatrix: new Float32Array(FSUniformsValues, 128, 16),\n                    };\n                    FSUniformsViews.replaceableColor.set(this.rendererData.teamColor);\n                    // FSUniformsViews.replaceableType.set([texture.ReplaceableId || 0]);\n                    FSUniformsViews.discardAlphaLevel.set([baseLayer.FilterMode === FilterMode.Transparent ? .75 : 0]);\n                    FSUniformsViews.tVertexAnim.set(tVetexAnim.slice(0, 3));\n                    FSUniformsViews.tVertexAnim.set(tVetexAnim.slice(3, 6), 4);\n                    FSUniformsViews.tVertexAnim.set(tVetexAnim.slice(6, 9), 8);\n                    FSUniformsViews.lightPos.set(this.rendererData.lightPos);\n                    FSUniformsViews.lightColor.set(this.rendererData.lightColor);\n                    FSUniformsViews.cameraPos.set(this.rendererData.cameraPos);\n                    if (shadowMapTexture && shadowMapMatrix) {\n                        FSUniformsViews.shadowParams.set([1, shadowBias ?? 1e-6, shadowSmoothingStep ?? 1 / 1024]);\n                        FSUniformsViews.shadowMapLightMatrix.set(shadowMapMatrix);\n                    } else {\n                        FSUniformsViews.shadowParams.set([0, 0, 0]);\n                        FSUniformsViews.shadowMapLightMatrix.set([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);\n                    }\n                    FSUniformsViews.hasEnv.set([hasEnv ? 1 : 0]);\n                    FSUniformsViews.wireframe.set([wireframe ? 1 : 0]);\n                    this.device.queue.writeBuffer(gpuFSUniformsBuffer, 0, FSUniformsValues);\n\n                    const fsBindGroup = this.device.createBindGroup({\n                        label: `fs uniforms ${materialID}`,\n                        layout: this.fsBindGroupLayout,\n                        entries: [\n                            {\n                                binding: 0,\n                                resource: { buffer: gpuFSUniformsBuffer }\n                            },\n                            {\n                                binding: 1,\n                                resource: this.rendererData.gpuSamplers[diffuseTextureID]\n                            },\n                            {\n                                binding: 2,\n                                resource: (this.rendererData.gpuTextures[diffuseTexture.Image] || this.rendererData.gpuEmptyTexture).createView()\n                            },\n                            {\n                                binding: 3,\n                                resource: this.rendererData.gpuSamplers[normalTextureID]\n                            },\n                            {\n                                binding: 4,\n                                resource: (this.rendererData.gpuTextures[normalTexture.Image] || this.rendererData.gpuEmptyTexture).createView()\n                            },\n                            {\n                                binding: 5,\n                                resource: this.rendererData.gpuSamplers[ormTextureID]\n                            },\n                            {\n                                binding: 6,\n                                resource: (this.rendererData.gpuTextures[ormTexture.Image] || this.rendererData.gpuEmptyTexture).createView()\n                            },\n                            {\n                                binding: 7,\n                                resource: this.rendererData.gpuDepthSampler\n                            },\n                            {\n                                binding: 8,\n                                resource: (shadowMapTexture as GPUTexture || this.rendererData.gpuDepthEmptyTexture).createView()\n                            },\n                            {\n                                binding: 9,\n                                resource: this.prefilterEnvSampler\n                            },\n                            {\n                                binding: 10,\n                                resource: (irradianceMap as GPUTexture || this.rendererData.gpuEmptyCubeTexture).createView({\n                                    dimension: 'cube'\n                                })\n                            },\n                            {\n                                binding: 11,\n                                resource: this.prefilterEnvSampler\n                            },\n                            {\n                                binding: 12,\n                                resource: (prefilteredEnv as GPUTexture || this.rendererData.gpuEmptyCubeTexture).createView({\n                                    dimension: 'cube'\n                                })\n                            },\n                            {\n                                binding: 13,\n                                resource: this.gpuBrdfSampler\n                            },\n                            {\n                                binding: 14,\n                                resource: this.gpuBrdfLUT.createView()\n                            }\n                        ]\n                    });\n\n                    pass.setBindGroup(0, this.gpuVSUniformsBindGroup);\n                    pass.setBindGroup(1, fsBindGroup);\n\n                    pass.drawIndexed(wireframe ? geoset.Faces.length * 2 : geoset.Faces.length);\n                } else {\n                    for (let j = 0; j < material.Layers.length; ++j) {\n                        const layer = material.Layers[j];\n                        const textureID = this.rendererData.materialLayerTextureID[materialID][j];\n                        const texture = this.model.Textures[textureID];\n\n                        const pipeline = wireframe ? this.gpuWireframePipeline : this.getGPUPipeline(layer);\n                        pass.setPipeline(pipeline);\n\n                        this.gpuFSUniformsBuffers[materialID] ||= [];\n                        let gpuFSUniformsBuffer = this.gpuFSUniformsBuffers[materialID][j];\n\n                        if (!gpuFSUniformsBuffer) {\n                            gpuFSUniformsBuffer = this.gpuFSUniformsBuffers[materialID][j] = this.device.createBuffer({\n                                label: `fs uniforms ${materialID} ${j}`,\n                                size: 80,\n                                usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n                            });\n                        }\n\n                        const tVetexAnim = this.getTexCoordMatrix(layer);\n\n                        const FSUniformsValues = new ArrayBuffer(80);\n                        const FSUniformsViews = {\n                            replaceableColor: new Float32Array(FSUniformsValues, 0, 3),\n                            replaceableType: new Uint32Array(FSUniformsValues, 12, 1),\n                            discardAlphaLevel: new Float32Array(FSUniformsValues, 16, 1),\n                            wireframe: new Uint32Array(FSUniformsValues, 20, 1),\n                            tVertexAnim: new Float32Array(FSUniformsValues, 32, 12),\n                        };\n                        FSUniformsViews.replaceableColor.set(this.rendererData.teamColor);\n                        FSUniformsViews.replaceableType.set([texture.ReplaceableId || 0]);\n                        FSUniformsViews.discardAlphaLevel.set([layer.FilterMode === FilterMode.Transparent ? .75 : 0]);\n                        FSUniformsViews.tVertexAnim.set(tVetexAnim.slice(0, 3));\n                        FSUniformsViews.tVertexAnim.set(tVetexAnim.slice(3, 6), 4);\n                        FSUniformsViews.tVertexAnim.set(tVetexAnim.slice(6, 9), 8);\n                        FSUniformsViews.wireframe.set([wireframe ? 1 : 0]);\n                        this.device.queue.writeBuffer(gpuFSUniformsBuffer, 0, FSUniformsValues);\n\n                        const fsBindGroup = this.device.createBindGroup({\n                            label: `fs uniforms ${materialID} ${j}`,\n                            layout: this.fsBindGroupLayout,\n                            entries: [\n                                {\n                                    binding: 0,\n                                    resource: { buffer: gpuFSUniformsBuffer }\n                                },\n                                {\n                                    binding: 1,\n                                    resource: this.rendererData.gpuSamplers[textureID]\n                                },\n                                {\n                                    binding: 2,\n                                    resource: (this.rendererData.gpuTextures[texture.Image] || this.rendererData.gpuEmptyTexture).createView()\n                                }\n                            ]\n                        });\n\n                        pass.setBindGroup(0, this.gpuVSUniformsBindGroup);\n                        pass.setBindGroup(1, fsBindGroup);\n\n                        pass.drawIndexed(wireframe ? geoset.Faces.length * 2 : geoset.Faces.length);\n                    }\n                }\n            }\n\n            this.particlesController.renderGPU(pass, mvMatrix, pMatrix);\n            this.ribbonsController.renderGPU(pass, mvMatrix, pMatrix);\n\n            pass.end();\n\n            const commandBuffer = encoder.finish();\n            this.device.queue.submit([commandBuffer]);\n\n            return;\n        }\n\n        if (env) {\n            this.renderEnvironment(mvMatrix, pMatrix);\n        }\n\n        this.gl.useProgram(this.shaderProgram);\n\n        this.gl.uniformMatrix4fv(this.shaderProgramLocations.pMatrixUniform, false, pMatrix);\n        this.gl.uniformMatrix4fv(this.shaderProgramLocations.mvMatrixUniform, false, mvMatrix);\n        this.gl.uniform1f(this.shaderProgramLocations.wireframeUniform, wireframe ? 1 : 0);\n\n        this.gl.enableVertexAttribArray(this.shaderProgramLocations.vertexPositionAttribute);\n        this.gl.enableVertexAttribArray(this.shaderProgramLocations.normalsAttribute);\n        this.gl.enableVertexAttribArray(this.shaderProgramLocations.textureCoordAttribute);\n\n        if (this.isHD) {\n            this.gl.enableVertexAttribArray(this.shaderProgramLocations.skinAttribute);\n            this.gl.enableVertexAttribArray(this.shaderProgramLocations.weightAttribute);\n            this.gl.enableVertexAttribArray(this.shaderProgramLocations.tangentAttribute);\n        } else {\n            if (!this.softwareSkinning) {\n                this.gl.enableVertexAttribArray(this.shaderProgramLocations.groupAttribute);\n            }\n        }\n\n        if (!this.softwareSkinning) {\n            for (let j = 0; j < MAX_NODES; ++j) {\n                if (this.rendererData.nodes[j]) {\n                    this.gl.uniformMatrix4fv(this.shaderProgramLocations.nodesMatricesAttributes[j], false,\n                        this.rendererData.nodes[j].matrix);\n                }\n            }\n        }\n\n\n        for (let i = 0; i < this.model.Geosets.length; ++i) {\n            const geoset = this.model.Geosets[i];\n            if (this.rendererData.geosetAlpha[i] < 1e-6) {\n                continue;\n            }\n            if (geoset.LevelOfDetail !== undefined && geoset.LevelOfDetail !== levelOfDetail) {\n                continue;\n            }\n\n            if (this.softwareSkinning) {\n                this.generateGeosetVertices(i);\n            }\n\n            const materialID = geoset.MaterialID;\n            const material = this.model.Materials[materialID];\n\n            // Shader_HD_DefaultUnit\n            if (this.isHD) {\n                this.gl.uniform3fv(this.shaderProgramLocations.lightPosUniform, this.rendererData.lightPos);\n                this.gl.uniform3fv(this.shaderProgramLocations.lightColorUniform, this.rendererData.lightColor);\n                // this.gl.uniform3fv(this.shaderProgramLocations.lightPosUniform, this.rendererData.cameraPos);\n                this.gl.uniform3fv(this.shaderProgramLocations.cameraPosUniform, this.rendererData.cameraPos);\n\n                if (shadowMapTexture && shadowMapMatrix) {\n                    this.gl.uniform3f(this.shaderProgramLocations.shadowParamsUniform, 1, shadowBias ?? 1e-6, shadowSmoothingStep ?? 1 / 1024);\n\n                    this.gl.activeTexture(this.gl.TEXTURE3);\n                    this.gl.bindTexture(this.gl.TEXTURE_2D, shadowMapTexture);\n                    this.gl.uniform1i(this.shaderProgramLocations.shadowMapSamplerUniform, 3);\n                    this.gl.uniformMatrix4fv(this.shaderProgramLocations.shadowMapLightMatrixUniform, false, shadowMapMatrix);\n                } else {\n                    this.gl.uniform3f(this.shaderProgramLocations.shadowParamsUniform, 0, 0, 0);\n                }\n\n                const envTextureId = this.model.Version >= 1100 && material.Layers.find(it => it.ShaderTypeId === 1 && typeof it.ReflectionsTextureID === 'number')?.ReflectionsTextureID || material.Layers[5]?.TextureID;\n                const envTexture = this.model.Textures[envTextureId as number]?.Image;\n                const irradianceMap = this.rendererData.irradianceMap[envTexture];\n                const prefilteredEnv = this.rendererData.prefilteredEnvMap[envTexture];\n                if (useEnvironmentMap && irradianceMap && prefilteredEnv) {\n                    this.gl.uniform1i(this.shaderProgramLocations.hasEnvUniform, 1);\n                    this.gl.activeTexture(this.gl.TEXTURE4);\n                    this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, irradianceMap);\n                    this.gl.uniform1i(this.shaderProgramLocations.irradianceMapUniform, 4);\n                    this.gl.activeTexture(this.gl.TEXTURE5);\n                    this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, prefilteredEnv);\n                    this.gl.uniform1i(this.shaderProgramLocations.prefilteredEnvUniform, 5);\n                    this.gl.activeTexture(this.gl.TEXTURE6);\n                    this.gl.bindTexture(this.gl.TEXTURE_2D, this.brdfLUT);\n                    this.gl.uniform1i(this.shaderProgramLocations.brdfLUTUniform, 6);\n                } else {\n                    this.gl.uniform1i(this.shaderProgramLocations.hasEnvUniform, 0);\n                    this.gl.uniform1i(this.shaderProgramLocations.irradianceMapUniform, 4);\n                    this.gl.uniform1i(this.shaderProgramLocations.prefilteredEnvUniform, 5);\n                    this.gl.uniform1i(this.shaderProgramLocations.brdfLUTUniform, 6);\n                }\n\n                this.setLayerPropsHD(materialID, material.Layers);\n\n                this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer[i]);\n                this.gl.vertexAttribPointer(this.shaderProgramLocations.vertexPositionAttribute, 3, this.gl.FLOAT, false, 0, 0);\n\n                this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.normalBuffer[i]);\n                this.gl.vertexAttribPointer(this.shaderProgramLocations.normalsAttribute, 3, this.gl.FLOAT, false, 0, 0);\n\n                this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.texCoordBuffer[i]);\n                this.gl.vertexAttribPointer(this.shaderProgramLocations.textureCoordAttribute, 2, this.gl.FLOAT, false, 0, 0);\n\n                this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.skinWeightBuffer[i]);\n                this.gl.vertexAttribPointer(this.shaderProgramLocations.skinAttribute, 4, this.gl.UNSIGNED_BYTE, false, 8, 0);\n                this.gl.vertexAttribPointer(this.shaderProgramLocations.weightAttribute, 4, this.gl.UNSIGNED_BYTE, true, 8, 4);\n\n                this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.tangentBuffer[i]);\n                this.gl.vertexAttribPointer(this.shaderProgramLocations.tangentAttribute, 4, this.gl.FLOAT, false, 0, 0);\n\n                if (wireframe && !this.wireframeIndexBuffer[i]) {\n                    this.createWireframeBuffer(i);\n                }\n\n                this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, wireframe ? this.wireframeIndexBuffer[i] : this.indexBuffer[i]);\n                this.gl.drawElements(\n                    wireframe ? this.gl.LINES : this.gl.TRIANGLES,\n                    wireframe ? geoset.Faces.length * 2 : geoset.Faces.length,\n                    this.gl.UNSIGNED_SHORT,\n                    0\n                );\n\n                if (shadowMapTexture && shadowMapMatrix) {\n                    this.gl.activeTexture(this.gl.TEXTURE3);\n                    this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n                }\n            } else {\n                for (let j = 0; j < material.Layers.length; ++j) {\n                    this.setLayerProps(material.Layers[j], this.rendererData.materialLayerTextureID[materialID][j]);\n\n                    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer[i]);\n                    this.gl.vertexAttribPointer(this.shaderProgramLocations.vertexPositionAttribute, 3, this.gl.FLOAT, false, 0, 0);\n\n                    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.normalBuffer[i]);\n                    this.gl.vertexAttribPointer(this.shaderProgramLocations.normalsAttribute, 3, this.gl.FLOAT, false, 0, 0);\n\n                    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.texCoordBuffer[i]);\n                    this.gl.vertexAttribPointer(this.shaderProgramLocations.textureCoordAttribute, 2, this.gl.FLOAT, false, 0, 0);\n\n                    if (!this.softwareSkinning) {\n                        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.groupBuffer[i]);\n                        this.gl.vertexAttribPointer(this.shaderProgramLocations.groupAttribute, 4, this.gl.UNSIGNED_SHORT, false, 0, 0);\n                    }\n\n                    if (wireframe && !this.wireframeIndexBuffer[i]) {\n                        this.createWireframeBuffer(i);\n                    }\n\n                    this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, wireframe ? this.wireframeIndexBuffer[i] : this.indexBuffer[i]);\n                    this.gl.drawElements(\n                        wireframe ? this.gl.LINES : this.gl.TRIANGLES,\n                        wireframe ? geoset.Faces.length * 2 : geoset.Faces.length,\n                        this.gl.UNSIGNED_SHORT,\n                        0\n                    );\n                }\n            }\n        }\n\n        this.gl.disableVertexAttribArray(this.shaderProgramLocations.vertexPositionAttribute);\n        this.gl.disableVertexAttribArray(this.shaderProgramLocations.normalsAttribute);\n        this.gl.disableVertexAttribArray(this.shaderProgramLocations.textureCoordAttribute);\n        if (this.isHD) {\n            this.gl.disableVertexAttribArray(this.shaderProgramLocations.skinAttribute);\n            this.gl.disableVertexAttribArray(this.shaderProgramLocations.weightAttribute);\n            this.gl.disableVertexAttribArray(this.shaderProgramLocations.tangentAttribute);\n        } else {\n            if (!this.softwareSkinning) {\n                this.gl.disableVertexAttribArray(this.shaderProgramLocations.groupAttribute);\n            }\n        }\n\n        this.particlesController.render(mvMatrix, pMatrix);\n        this.ribbonsController.render(mvMatrix, pMatrix);\n    }\n\n    private renderEnvironmentGPU (pass: GPURenderPassEncoder, mvMatrix: mat4, pMatrix: mat4) {\n        pass.setPipeline(this.envPiepeline);\n\n        const VSUniformsValues = new ArrayBuffer(128);\n        const VSUniformsViews = {\n            mvMatrix: new Float32Array(VSUniformsValues, 0, 16),\n            pMatrix: new Float32Array(VSUniformsValues, 64, 16)\n        };\n        VSUniformsViews.mvMatrix.set(mvMatrix);\n        VSUniformsViews.pMatrix.set(pMatrix);\n        this.device.queue.writeBuffer(this.envVSUniformsBuffer, 0, VSUniformsValues);\n\n        pass.setBindGroup(0, this.envVSBindGroup);\n\n        for (const path in this.rendererData.gpuEnvTextures) {\n            const fsUniformsBindGroup = this.device.createBindGroup({\n                label: `env fs uniforms ${path}`,\n                layout: this.envFSBindGroupLayout,\n                entries: [\n                    {\n                        binding: 0,\n                        resource: this.envSampler\n                    },\n                    {\n                        binding: 1,\n                        resource: this.rendererData.gpuEnvTextures[path].createView({ dimension: 'cube' })\n                    }\n                ]\n            });\n\n            pass.setBindGroup(1, fsUniformsBindGroup);\n\n            pass.setPipeline(this.envPiepeline);\n            pass.setVertexBuffer(0, this.cubeGPUVertexBuffer);\n\n            pass.draw(6 * 6);\n        }\n    }\n\n    private renderEnvironment (mvMatrix: mat4, pMatrix: mat4): void {\n        if (!isWebGL2(this.gl)) {\n            return;\n        }\n\n        this.gl.disable(this.gl.BLEND);\n        this.gl.disable(this.gl.DEPTH_TEST);\n        this.gl.disable(this.gl.CULL_FACE);\n\n        for (const path in this.rendererData.envTextures) {\n            this.gl.useProgram(this.envSphere.program);\n\n            this.gl.uniformMatrix4fv(this.envSphere.uniforms.uPMatrix, false, pMatrix);\n            this.gl.uniformMatrix4fv(this.envSphere.uniforms.uMVMatrix, false, mvMatrix);\n\n            this.gl.activeTexture(this.gl.TEXTURE0);\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, this.rendererData.envTextures[path]);\n            this.gl.uniform1i(this.envSphere.uniforms.uEnvironmentMap, 0);\n\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubeVertexBuffer);\n            this.gl.enableVertexAttribArray(this.envSphere.attributes.aPos);\n            this.gl.vertexAttribPointer(this.envSphere.attributes.aPos, 3, this.gl.FLOAT, false, 0, 0);\n            this.gl.drawArrays(this.gl.TRIANGLES, 0, 6 * 6);\n            this.gl.disableVertexAttribArray(this.envSphere.attributes.aPos);\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, null);\n        }\n    }\n\n    /**\n     * @param mvMatrix\n     * @param pMatrix\n     * @param nodes Nodes to highlight. null means draw all\n     */\n    public renderSkeleton (mvMatrix: mat4, pMatrix: mat4, nodes: string[] | null): void {\n        const coords = [];\n        const colors = [];\n        const line = (node0: NodeWrapper, node1: NodeWrapper) => {\n            vec3.transformMat4(tempPos, node0.node.PivotPoint, node0.matrix);\n            coords.push(\n                tempPos[0],\n                tempPos[1],\n                tempPos[2]\n            );\n            vec3.transformMat4(tempPos, node1.node.PivotPoint, node1.matrix);\n            coords.push(\n                tempPos[0],\n                tempPos[1],\n                tempPos[2]\n            );\n\n            colors.push(\n                0,\n                1,\n                0,\n                0,\n                0,\n                1,\n            );\n        };\n        const updateNode = (node: NodeWrapper) => {\n            if ((node.node.Parent || node.node.Parent === 0) && (!nodes || nodes.includes(node.node.Name))) {\n                line(node, this.rendererData.nodes[node.node.Parent]);\n            }\n            for (const child of node.childs) {\n                updateNode(child);\n            }\n        };\n        updateNode(this.rendererData.rootNode);\n        if (!coords.length) {\n            return;\n        }\n        const vertexBuffer = new Float32Array(coords);\n        const colorBuffer = new Float32Array(colors);\n\n        if (this.device) {\n            if (!this.skeletonShaderModule) {\n                this.skeletonShaderModule = this.device.createShaderModule({\n                    label: 'skeleton',\n                    code: skeletonShaderSource\n                });\n            }\n\n            if (!this.skeletonBindGroupLayout) {\n                this.skeletonBindGroupLayout = this.device.createBindGroupLayout({\n                    label: 'skeleton bind group layout',\n                    entries: [{\n                        binding: 0,\n                        visibility: GPUShaderStage.VERTEX,\n                        buffer: {\n                            type: 'uniform',\n                            hasDynamicOffset: false,\n                            minBindingSize: 128\n                        }\n                    }] as const\n                });\n            }\n\n            if (!this.skeletonPipelineLayout) {\n                this.skeletonPipelineLayout = this.device.createPipelineLayout({\n                    label: 'skeleton pipeline layout',\n                    bindGroupLayouts: [\n                        this.skeletonBindGroupLayout\n                    ]\n                });\n            }\n\n            if (!this.skeletonPipeline) {\n                this.skeletonPipeline = this.device.createRenderPipeline({\n                    label: 'skeleton pipeline',\n                    layout: this.skeletonPipelineLayout,\n                    vertex: {\n                        module: this.skeletonShaderModule,\n                        buffers: [{\n                            // vertices\n                            arrayStride: 12,\n                            attributes: [{\n                                shaderLocation: 0,\n                                offset: 0,\n                                format: 'float32x3' as const\n                            }]\n                        }, {\n                            // colors\n                            arrayStride: 12,\n                            attributes: [{\n                                shaderLocation: 1,\n                                offset: 0,\n                                format: 'float32x3' as const\n                            }]\n                        }]\n                    },\n                    fragment: {\n                        module: this.skeletonShaderModule,\n                        targets: [{\n                            format: navigator.gpu.getPreferredCanvasFormat(),\n                            blend: {\n                                color: {\n                                    operation: 'add',\n                                    srcFactor: 'src-alpha',\n                                    dstFactor: 'one-minus-src-alpha'\n                                },\n                                alpha: {\n                                    operation: 'add',\n                                    srcFactor: 'one',\n                                    dstFactor: 'one-minus-src-alpha'\n                                }\n                            } as const\n                        }]\n                    },\n                    primitive: {\n                        topology: 'line-list'\n                    }\n                });\n            }\n\n            this.skeletonGPUVertexBuffer?.destroy();\n            this.skeletonGPUColorBuffer?.destroy();\n            this.skeletonGPUUniformsBuffer?.destroy();\n\n            const vertex = this.skeletonGPUVertexBuffer = this.device.createBuffer({\n                label: 'skeleton vertex',\n                size: vertexBuffer.byteLength,\n                usage: GPUBufferUsage.VERTEX,\n                mappedAtCreation: true\n            });\n            new Float32Array(\n                vertex.getMappedRange(0, vertex.size)\n            ).set(vertexBuffer);\n            vertex.unmap();\n\n            const color = this.skeletonGPUColorBuffer = this.device.createBuffer({\n                label: 'skeleton color',\n                size: colorBuffer.byteLength,\n                usage: GPUBufferUsage.VERTEX,\n                mappedAtCreation: true\n            });\n            new Float32Array(\n                color.getMappedRange(0, color.size)\n            ).set(colorBuffer);\n            color.unmap();\n\n            const uniformsBuffer = this.skeletonGPUUniformsBuffer = this.device.createBuffer({\n                label: 'skeleton vs uniforms',\n                size: 128,\n                usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n            });\n            const uniformsBindGroup = this.device.createBindGroup({\n                label: 'skeleton uniforms bind group',\n                layout: this.skeletonBindGroupLayout,\n                entries: [\n                    {\n                        binding: 0,\n                        resource: { buffer: uniformsBuffer }\n                    }\n                ]\n            });\n\n            const renderPassDescriptor: GPURenderPassDescriptor = {\n                label: 'skeleton renderPass',\n                colorAttachments: [{\n                    view: this.gpuContext.getCurrentTexture().createView(),\n                    clearValue: [0.15, 0.15, 0.15, 1],\n                    loadOp: 'load',\n                    storeOp: 'store'\n                }] as const\n            };\n\n            const encoder = this.device.createCommandEncoder();\n            const pass = encoder.beginRenderPass(renderPassDescriptor);\n\n            const VSUniformsValues = new ArrayBuffer(128);\n            const VSUniformsViews = {\n                mvMatrix: new Float32Array(VSUniformsValues, 0, 16),\n                pMatrix: new Float32Array(VSUniformsValues, 64, 16),\n            };\n            VSUniformsViews.mvMatrix.set(mvMatrix);\n            VSUniformsViews.pMatrix.set(pMatrix);\n            this.device.queue.writeBuffer(uniformsBuffer, 0, VSUniformsValues);\n\n            pass.setVertexBuffer(0, vertex);\n            pass.setVertexBuffer(1, color);\n            pass.setPipeline(this.skeletonPipeline);\n            pass.setBindGroup(0, uniformsBindGroup);\n\n            pass.draw(vertexBuffer.length / 3);\n            pass.end();\n\n            const commandBuffer = encoder.finish();\n            this.device.queue.submit([commandBuffer]);\n\n            return;\n        }\n\n        if (!this.skeletonShaderProgram) {\n            this.skeletonShaderProgram = this.initSkeletonShaderProgram();\n        }\n\n        this.gl.disable(this.gl.BLEND);\n        this.gl.disable(this.gl.DEPTH_TEST);\n\n        this.gl.useProgram(this.skeletonShaderProgram);\n\n        this.gl.uniformMatrix4fv(this.skeletonShaderProgramLocations.pMatrixUniform, false, pMatrix);\n        this.gl.uniformMatrix4fv(this.skeletonShaderProgramLocations.mvMatrixUniform, false, mvMatrix);\n\n        this.gl.enableVertexAttribArray(this.skeletonShaderProgramLocations.vertexPositionAttribute);\n        this.gl.enableVertexAttribArray(this.skeletonShaderProgramLocations.colorAttribute);\n\n        if (!this.skeletonVertexBuffer) {\n            this.skeletonVertexBuffer = this.gl.createBuffer();\n        }\n        if (!this.skeletonColorBuffer) {\n            this.skeletonColorBuffer = this.gl.createBuffer();\n        }\n\n        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.skeletonVertexBuffer);\n        this.gl.bufferData(this.gl.ARRAY_BUFFER, vertexBuffer, this.gl.DYNAMIC_DRAW);\n        this.gl.vertexAttribPointer(this.skeletonShaderProgramLocations.vertexPositionAttribute, 3, this.gl.FLOAT, false, 0, 0);\n\n        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.skeletonColorBuffer);\n        this.gl.bufferData(this.gl.ARRAY_BUFFER, colorBuffer, this.gl.DYNAMIC_DRAW);\n        this.gl.vertexAttribPointer(this.skeletonShaderProgramLocations.colorAttribute, 3, this.gl.FLOAT, false, 0, 0);\n\n        this.gl.drawArrays(this.gl.LINES, 0, vertexBuffer.length / 3);\n\n        this.gl.disableVertexAttribArray(this.skeletonShaderProgramLocations.vertexPositionAttribute);\n        this.gl.disableVertexAttribArray(this.skeletonShaderProgramLocations.colorAttribute);\n    }\n\n    private initSkeletonShaderProgram (): WebGLProgram {\n        const vertex = this.skeletonVertexShader = getShader(this.gl, skeletonVertexShader, this.gl.VERTEX_SHADER);\n        const fragment = this.skeletonFragmentShader = getShader(this.gl, skeletonFragmentShader, this.gl.FRAGMENT_SHADER);\n\n        const shaderProgram = this.gl.createProgram();\n        this.gl.attachShader(shaderProgram, vertex);\n        this.gl.attachShader(shaderProgram, fragment);\n        this.gl.linkProgram(shaderProgram);\n\n        if (!this.gl.getProgramParameter(shaderProgram, this.gl.LINK_STATUS)) {\n            alert('Could not initialise shaders');\n        }\n\n        this.gl.useProgram(shaderProgram);\n\n        this.skeletonShaderProgramLocations.vertexPositionAttribute = this.gl.getAttribLocation(shaderProgram, 'aVertexPosition');\n        this.skeletonShaderProgramLocations.colorAttribute = this.gl.getAttribLocation(shaderProgram, 'aColor');\n        this.skeletonShaderProgramLocations.pMatrixUniform = this.gl.getUniformLocation(shaderProgram, 'uPMatrix');\n        this.skeletonShaderProgramLocations.mvMatrixUniform = this.gl.getUniformLocation(shaderProgram, 'uMVMatrix');\n\n        return shaderProgram;\n    }\n\n    private generateGeosetVertices (geosetIndex: number): void {\n        const geoset: Geoset = this.model.Geosets[geosetIndex];\n        const buffer = this.vertices[geosetIndex];\n\n        for (let i = 0; i < buffer.length; i += 3) {\n            const index = i / 3;\n            const group = geoset.Groups[geoset.VertexGroup[index]];\n\n            vec3.set(tempPos, geoset.Vertices[i], geoset.Vertices[i + 1], geoset.Vertices[i + 2]);\n            vec3.set(tempSum, 0, 0, 0);\n            for (let j = 0; j < group.length; ++j) {\n                vec3.add(\n                    tempSum, tempSum,\n                    vec3.transformMat4(tempVec3, tempPos, this.rendererData.nodes[group[j]].matrix)\n                );\n            }\n            vec3.scale(tempPos, tempSum, 1 / group.length);\n            buffer[i]     = tempPos[0];\n            buffer[i + 1] = tempPos[1];\n            buffer[i + 2] = tempPos[2];\n        }\n        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer[geosetIndex]);\n        this.gl.bufferData(this.gl.ARRAY_BUFFER, buffer, this.gl.DYNAMIC_DRAW);\n    }\n\n    private setTextureParameters (flags: TextureFlags | 0, hasMipmaps: boolean) {\n        if (flags & TextureFlags.WrapWidth) {\n            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.REPEAT);\n        } else {\n            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n        }\n        if (flags & TextureFlags.WrapHeight) {\n            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.REPEAT);\n        } else {\n            this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n        }\n        this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n        this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, hasMipmaps ? this.gl.LINEAR_MIPMAP_NEAREST : this.gl.LINEAR);\n\n        if (this.anisotropicExt) {\n            const max = this.gl.getParameter(this.anisotropicExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT);\n            this.gl.texParameterf(this.gl.TEXTURE_2D, this.anisotropicExt.TEXTURE_MAX_ANISOTROPY_EXT, max);\n        }\n    }\n\n    private processEnvMaps (path: string): void {\n        if (\n            !this.rendererData.requiredEnvMaps[path] ||\n            !(this.rendererData.textures[path] || this.rendererData.gpuTextures[path]) ||\n            !(isWebGL2(this.gl) || this.device) ||\n            !(this.colorBufferFloatExt || this.device)\n        ) {\n            return;\n        }\n\n        if (this.gl) {\n            this.gl.disable(this.gl.BLEND);\n            this.gl.disable(this.gl.DEPTH_TEST);\n            this.gl.disable(this.gl.CULL_FACE);\n        }\n\n        const pMatrix = mat4.create();\n        const mvMatrix = mat4.create();\n        const eye = vec3.fromValues(0, 0, 0);\n        let center;\n        let up;\n        if (this.device) {\n            center = [\n                vec3.fromValues(1, 0, 0),\n                vec3.fromValues(-1, 0, 0),\n                vec3.fromValues(0, -1, 0),\n                vec3.fromValues(0, 1, 0),\n                vec3.fromValues(0, 0, 1),\n                vec3.fromValues(0, 0, -1)\n            ];\n            up = [\n                vec3.fromValues(0, -1, 0),\n                vec3.fromValues(0, -1, 0),\n                vec3.fromValues(0, 0, -1),\n                vec3.fromValues(0, 0, 1),\n                vec3.fromValues(0, -1, 0),\n                vec3.fromValues(0, -1, 0)\n            ];\n        } else {\n            center = [\n                vec3.fromValues(1, 0, 0),\n                vec3.fromValues(-1, 0, 0),\n                vec3.fromValues(0, 1, 0),\n                vec3.fromValues(0, -1, 0),\n                vec3.fromValues(0, 0, 1),\n                vec3.fromValues(0, 0, -1)\n            ];\n            up = [\n                vec3.fromValues(0, -1, 0),\n                vec3.fromValues(0, -1, 0),\n                vec3.fromValues(0, 0, 1),\n                vec3.fromValues(0, 0, -1),\n                vec3.fromValues(0, -1, 0),\n                vec3.fromValues(0, -1, 0)\n            ];\n        }\n\n        mat4.perspective(pMatrix, Math.PI / 2, 1, .1, 10);\n\n        let framebuffer: WebGLFramebuffer;\n        let cubemap: WebGLTexture;\n        let gpuCubemap: GPUTexture;\n\n        if (this.device) {\n            gpuCubemap = this.rendererData.gpuEnvTextures[path] = this.device.createTexture({\n                label: `env cubemap ${path}`,\n                size: [ENV_MAP_SIZE, ENV_MAP_SIZE, 6],\n                format: navigator.gpu.getPreferredCanvasFormat(),\n                usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,\n                mipLevelCount: MAX_ENV_MIP_LEVELS\n            });\n\n            const encoder = this.device.createCommandEncoder({\n                label: 'env to cubemap'\n            });\n            const buffers: GPUBuffer[] = [];\n\n            for (let i = 0; i < 6; ++i) {\n                mat4.lookAt(mvMatrix, eye, center[i], up[i]);\n\n                const pass = encoder.beginRenderPass({\n                    label: 'env to cubemap',\n                    colorAttachments: [{\n                        view: gpuCubemap.createView({\n                            dimension: '2d',\n                            baseArrayLayer: i,\n                            baseMipLevel: 0,\n                            mipLevelCount: 1\n                        }),\n                        clearValue: [0, 0, 0, 1],\n                        loadOp: 'clear',\n                        storeOp: 'store'\n                    }] as const\n                });\n\n                const VSUniformsValues = new ArrayBuffer(128);\n                const VSUniformsViews = {\n                    mvMatrix: new Float32Array(VSUniformsValues, 0, 16),\n                    pMatrix: new Float32Array(VSUniformsValues, 64, 16)\n                };\n                VSUniformsViews.mvMatrix.set(mvMatrix);\n                VSUniformsViews.pMatrix.set(pMatrix);\n                const buffer = this.device.createBuffer({\n                    label: `env to cubemap vs uniforms ${i}`,\n                    size: 128,\n                    usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n                });\n                buffers.push(buffer);\n                this.device.queue.writeBuffer(buffer, 0, VSUniformsValues);\n\n                const bindGroup = this.device.createBindGroup({\n                    label: `env to cubemap vs bind group ${i}`,\n                    layout: this.envToCubemapVSBindGroupLayout,\n                    entries: [\n                        {\n                            binding: 0,\n                            resource: { buffer }\n                        }\n                    ]\n                });\n\n                pass.setBindGroup(0, bindGroup);\n\n                const fsUniformsBindGroup = this.device.createBindGroup({\n                    label: `env to cubemap fs uniforms ${i}`,\n                    layout: this.envToCubemapFSBindGroupLayout,\n                    entries: [\n                        {\n                            binding: 0,\n                            resource: this.envToCubemapSampler\n                        },\n                        {\n                            binding: 1,\n                            resource: this.rendererData.gpuTextures[path].createView()\n                        }\n                    ]\n                });\n\n                pass.setBindGroup(1, fsUniformsBindGroup);\n\n                pass.setPipeline(this.envToCubemapPiepeline);\n                pass.setVertexBuffer(0, this.cubeGPUVertexBuffer);\n\n                pass.draw(6 * 6);\n\n                pass.end();\n            }\n\n            const commandBuffer = encoder.finish();\n            this.device.queue.submit([commandBuffer]);\n            this.device.queue.onSubmittedWorkDone().finally(() => {\n                buffers.forEach(buffer => {\n                    buffer.destroy();\n                });\n            });\n        } else if (isWebGL2(this.gl)) {\n            framebuffer = this.gl.createFramebuffer();\n\n            this.gl.useProgram(this.envToCubemap.program);\n\n            cubemap = this.rendererData.envTextures[path] = this.gl.createTexture();\n            this.gl.activeTexture(this.gl.TEXTURE1);\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, cubemap);\n            for (let i = 0; i < 6; ++i) {\n                this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, this.gl.RGBA16F, ENV_MAP_SIZE, ENV_MAP_SIZE, 0, this.gl.RGBA, this.gl.FLOAT, null);\n            }\n\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_R, this.gl.CLAMP_TO_EDGE);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubeVertexBuffer);\n            this.gl.enableVertexAttribArray(this.envToCubemap.attributes.aPos);\n            this.gl.vertexAttribPointer(this.envToCubemap.attributes.aPos, 3, this.gl.FLOAT, false, 0, 0);\n\n            this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);\n\n            this.gl.uniformMatrix4fv(this.envToCubemap.uniforms.uPMatrix, false, pMatrix);\n            this.gl.activeTexture(this.gl.TEXTURE0);\n            this.gl.bindTexture(this.gl.TEXTURE_2D, this.rendererData.textures[path]);\n            this.gl.uniform1i(this.envToCubemap.uniforms.uEquirectangularMap, 0);\n            this.gl.viewport(0, 0, ENV_MAP_SIZE, ENV_MAP_SIZE);\n            for (let i = 0; i < 6; ++i) {\n                this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap, 0);\n                this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n\n                mat4.lookAt(mvMatrix, eye, center[i], up[i]);\n                this.gl.uniformMatrix4fv(this.envToCubemap.uniforms.uMVMatrix, false, mvMatrix);\n\n                this.gl.drawArrays(this.gl.TRIANGLES, 0, 6 * 6);\n            }\n\n            this.gl.disableVertexAttribArray(this.envToCubemap.attributes.aPos);\n\n            this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n        }\n\n        // generate mips\n        if (this.device) {\n            generateMips(this.device, gpuCubemap);\n        } else {\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, cubemap);\n            this.gl.generateMipmap(this.gl.TEXTURE_CUBE_MAP);\n\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, null);\n        }\n\n        // Diffuse env convolution\n\n        if (this.device) {\n            gpuCubemap = this.rendererData.gpuIrradianceMap[path] = this.device.createTexture({\n                label: `convolute diffuse ${path}`,\n                size: [ENV_CONVOLUTE_DIFFUSE_SIZE, ENV_CONVOLUTE_DIFFUSE_SIZE, 6],\n                format: navigator.gpu.getPreferredCanvasFormat(),\n                usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,\n                mipLevelCount: 5\n            });\n\n            const encoder = this.device.createCommandEncoder({\n                label: 'convolute diffuse'\n            });\n            const buffers: GPUBuffer[] = [];\n\n            for (let i = 0; i < 6; ++i) {\n                mat4.lookAt(mvMatrix, eye, center[i], up[i]);\n\n                const pass = encoder.beginRenderPass({\n                    label: 'convolute diffuse',\n                    colorAttachments: [{\n                        view: gpuCubemap.createView({\n                            dimension: '2d',\n                            baseArrayLayer: i,\n                            baseMipLevel: 0,\n                            mipLevelCount: 1\n                        }),\n                        clearValue: [0, 0, 0, 1],\n                        loadOp: 'clear',\n                        storeOp: 'store'\n                    }] as const\n                });\n\n                const VSUniformsValues = new ArrayBuffer(128);\n                const VSUniformsViews = {\n                    mvMatrix: new Float32Array(VSUniformsValues, 0, 16),\n                    pMatrix: new Float32Array(VSUniformsValues, 64, 16)\n                };\n                VSUniformsViews.mvMatrix.set(mvMatrix);\n                VSUniformsViews.pMatrix.set(pMatrix);\n                const buffer = this.device.createBuffer({\n                    label: `convolute diffuse vs uniforms ${i}`,\n                    size: 128,\n                    usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n                });\n                buffers.push(buffer);\n                this.device.queue.writeBuffer(buffer, 0, VSUniformsValues);\n\n                const bindGroup = this.device.createBindGroup({\n                    label: `convolute diffuse vs bind group ${i}`,\n                    layout: this.convoluteDiffuseEnvVSBindGroupLayout,\n                    entries: [\n                        {\n                            binding: 0,\n                            resource: { buffer }\n                        }\n                    ]\n                });\n\n                pass.setBindGroup(0, bindGroup);\n\n                const fsUniformsBindGroup = this.device.createBindGroup({\n                    label: `convolute diffuse fs uniforms ${i}`,\n                    layout: this.convoluteDiffuseEnvFSBindGroupLayout,\n                    entries: [\n                        {\n                            binding: 0,\n                            resource: this.convoluteDiffuseEnvSampler\n                        },\n                        {\n                            binding: 1,\n                            resource: this.rendererData.gpuEnvTextures[path].createView({\n                                dimension: 'cube'\n                            })\n                        }\n                    ]\n                });\n\n                pass.setBindGroup(1, fsUniformsBindGroup);\n\n                pass.setPipeline(this.convoluteDiffuseEnvPiepeline);\n                pass.setVertexBuffer(0, this.cubeGPUVertexBuffer);\n\n                pass.draw(6 * 6);\n\n                pass.end();\n            }\n\n            const commandBuffer = encoder.finish();\n            this.device.queue.submit([commandBuffer]);\n            this.device.queue.onSubmittedWorkDone().finally(() => {\n                buffers.forEach(buffer => {\n                    buffer.destroy();\n                });\n            });\n        } else if (isWebGL2(this.gl)) {\n            this.gl.useProgram(this.convoluteDiffuseEnv.program);\n            const diffuseCubemap = this.rendererData.irradianceMap[path] = this.gl.createTexture();\n\n            this.gl.activeTexture(this.gl.TEXTURE1);\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, diffuseCubemap);\n            for (let i = 0; i < 6; ++i) {\n                this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, this.gl.RGBA16F, ENV_CONVOLUTE_DIFFUSE_SIZE, ENV_CONVOLUTE_DIFFUSE_SIZE, 0, this.gl.RGBA, this.gl.FLOAT, null);\n            }\n\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_R, this.gl.CLAMP_TO_EDGE);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubeVertexBuffer);\n            this.gl.enableVertexAttribArray(this.convoluteDiffuseEnv.attributes.aPos);\n            this.gl.vertexAttribPointer(this.convoluteDiffuseEnv.attributes.aPos, 3, this.gl.FLOAT, false, 0, 0);\n\n            this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);\n\n            this.gl.uniformMatrix4fv(this.convoluteDiffuseEnv.uniforms.uPMatrix, false, pMatrix);\n            this.gl.activeTexture(this.gl.TEXTURE0);\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, this.rendererData.envTextures[path]);\n            this.gl.uniform1i(this.convoluteDiffuseEnv.uniforms.uEnvironmentMap, 0);\n            this.gl.viewport(0, 0, ENV_CONVOLUTE_DIFFUSE_SIZE, ENV_CONVOLUTE_DIFFUSE_SIZE);\n            for (let i = 0; i < 6; ++i) {\n                this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, diffuseCubemap, 0);\n                this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n\n                mat4.lookAt(mvMatrix, eye, center[i], up[i]);\n                this.gl.uniformMatrix4fv(this.convoluteDiffuseEnv.uniforms.uMVMatrix, false, mvMatrix);\n\n                this.gl.drawArrays(this.gl.TRIANGLES, 0, 6 * 6);\n            }\n\n            this.gl.disableVertexAttribArray(this.convoluteDiffuseEnv.attributes.aPos);\n\n            this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, diffuseCubemap);\n            this.gl.generateMipmap(this.gl.TEXTURE_CUBE_MAP);\n        }\n\n        // Prefilter env map with different roughness\n\n        if (this.device) {\n            const prefilterEnv = this.rendererData.gpuPrefilteredEnvMap[path] = this.device.createTexture({\n                label: `prefilter env ${path}`,\n                size: [ENV_PREFILTER_SIZE, ENV_PREFILTER_SIZE, 6],\n                format: navigator.gpu.getPreferredCanvasFormat(),\n                usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,\n                mipLevelCount: MAX_ENV_MIP_LEVELS\n            });\n\n            const encoder = this.device.createCommandEncoder({\n                label: 'prefilter env'\n            });\n            const buffers: GPUBuffer[] = [];\n\n            for (let mip = 0; mip < MAX_ENV_MIP_LEVELS; ++mip) {\n                const FSUniformsValues = new ArrayBuffer(4);\n                const FSUniformsViews = {\n                    roughness: new Float32Array(FSUniformsValues),\n                };\n                const roughness = mip / (MAX_ENV_MIP_LEVELS - 1);\n                FSUniformsViews.roughness.set([roughness]);\n                const fsBuffer = this.device.createBuffer({\n                    label: `prefilter env fs uniforms ${mip}`,\n                    size: 4,\n                    usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n                });\n                buffers.push(fsBuffer);\n                this.device.queue.writeBuffer(fsBuffer, 0, FSUniformsValues);\n\n                const fsUniformsBindGroup = this.device.createBindGroup({\n                    label: `prefilter env fs uniforms ${mip}`,\n                    layout: this.prefilterEnvFSBindGroupLayout,\n                    entries: [\n                        {\n                            binding: 0,\n                            resource: {\n                                buffer: fsBuffer\n                            }\n                        },\n                        {\n                            binding: 1,\n                            resource: this.prefilterEnvSampler\n                        },\n                        {\n                            binding: 2,\n                            resource: this.rendererData.gpuEnvTextures[path].createView({\n                                dimension: 'cube'\n                            })\n                        }\n                    ]\n                });\n\n                for (let i = 0; i < 6; ++i) {\n                    const pass = encoder.beginRenderPass({\n                        label: 'prefilter env',\n                        colorAttachments: [{\n                            view: prefilterEnv.createView({\n                                dimension: '2d',\n                                baseArrayLayer: i,\n                                baseMipLevel: mip,\n                                mipLevelCount: 1\n                            }),\n                            clearValue: [0, 0, 0, 1],\n                            loadOp: 'clear',\n                            storeOp: 'store'\n                        }] as const\n                    });\n\n                    mat4.lookAt(mvMatrix, eye, center[i], up[i]);\n\n                    const VSUniformsValues = new ArrayBuffer(128);\n                    const VSUniformsViews = {\n                        mvMatrix: new Float32Array(VSUniformsValues, 0, 16),\n                        pMatrix: new Float32Array(VSUniformsValues, 64, 16)\n                    };\n                    VSUniformsViews.mvMatrix.set(mvMatrix);\n                    VSUniformsViews.pMatrix.set(pMatrix);\n                    const vsBuffer = this.device.createBuffer({\n                        label: 'prefilter env vs uniforms',\n                        size: 128,\n                        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n                    });\n                    buffers.push(vsBuffer);\n                    this.device.queue.writeBuffer(vsBuffer, 0, VSUniformsValues);\n\n                    const fsBindGroup = this.device.createBindGroup({\n                        label: 'prefilter env vs bind group',\n                        layout: this.prefilterEnvVSBindGroupLayout,\n                        entries: [\n                            {\n                                binding: 0,\n                                resource: { buffer: vsBuffer }\n                            }\n                        ]\n                    });\n\n                    pass.setPipeline(this.prefilterEnvPiepeline);\n\n                    pass.setBindGroup(0, fsBindGroup);\n                    pass.setBindGroup(1, fsUniformsBindGroup);\n\n                    pass.setVertexBuffer(0, this.cubeGPUVertexBuffer);\n\n                    pass.draw(6 * 6);\n\n                    pass.end();\n                }\n            }\n\n            const commandBuffer = encoder.finish();\n            this.device.queue.submit([commandBuffer]);\n            this.device.queue.onSubmittedWorkDone().finally(() => {\n                buffers.forEach(buffer => {\n                    buffer.destroy();\n                });\n            });\n        } else if (isWebGL2(this.gl)) {\n            this.gl.useProgram(this.prefilterEnv.program);\n\n            const prefilterCubemap = this.rendererData.prefilteredEnvMap[path] = this.gl.createTexture();\n            this.gl.activeTexture(this.gl.TEXTURE1);\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, prefilterCubemap);\n            this.gl.texStorage2D(this.gl.TEXTURE_CUBE_MAP, MAX_ENV_MIP_LEVELS, this.gl.RGBA16F, ENV_PREFILTER_SIZE, ENV_PREFILTER_SIZE);\n            // for (let i = 0; i < 6; ++i) {\n            // this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, this.gl.RGB, ENV_PREFILTER_SIZE, ENV_PREFILTER_SIZE, 0, this.gl.RGB, this.gl.UNSIGNED_BYTE, null);\n            // }\n            for (let mip = 0; mip < MAX_ENV_MIP_LEVELS; ++mip) {\n                for (let i = 0; i < 6; ++i) {\n                    const size = ENV_PREFILTER_SIZE * .5 ** mip;\n                    const data = new Float32Array(size * size * 4);\n                    this.gl.texSubImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, mip, 0, 0, size, size, this.gl.RGBA, this.gl.FLOAT, data);\n                }\n            }\n\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_WRAP_R, this.gl.CLAMP_TO_EDGE);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR);\n            this.gl.texParameteri(this.gl.TEXTURE_CUBE_MAP, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubeVertexBuffer);\n            this.gl.enableVertexAttribArray(this.prefilterEnv.attributes.aPos);\n            this.gl.vertexAttribPointer(this.prefilterEnv.attributes.aPos, 3, this.gl.FLOAT, false, 0, 0);\n\n            this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);\n\n            this.gl.uniformMatrix4fv(this.prefilterEnv.uniforms.uPMatrix, false, pMatrix);\n            this.gl.activeTexture(this.gl.TEXTURE0);\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, this.rendererData.envTextures[path]);\n            this.gl.uniform1i(this.prefilterEnv.uniforms.uEnvironmentMap, 0);\n\n            for (let mip = 0; mip < MAX_ENV_MIP_LEVELS; ++mip) {\n                const mipWidth = ENV_PREFILTER_SIZE *.5 ** mip;\n                const mipHeight = ENV_PREFILTER_SIZE *.5 ** mip;\n                this.gl.viewport(0, 0, mipWidth, mipHeight);\n\n                const roughness = mip / (MAX_ENV_MIP_LEVELS - 1);\n\n                this.gl.uniform1f(this.prefilterEnv.uniforms.uRoughness, roughness);\n\n                for (let i = 0; i < 6; ++i) {\n                    this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilterCubemap, mip);\n                    this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n\n                    mat4.lookAt(mvMatrix, eye, center[i], up[i]);\n                    this.gl.uniformMatrix4fv(this.prefilterEnv.uniforms.uMVMatrix, false, mvMatrix);\n\n                    this.gl.drawArrays(this.gl.TRIANGLES, 0, 6 * 6);\n                }\n            }\n\n            // cleanup\n\n            this.gl.activeTexture(this.gl.TEXTURE1);\n            this.gl.bindTexture(this.gl.TEXTURE_CUBE_MAP, null);\n            this.gl.deleteFramebuffer(framebuffer);\n        }\n    }\n\n    private initShaderProgram<A extends string, U extends string>(\n        vertex: string,\n        fragment: string,\n        attributesDesc: Record<A, string>,\n        uniformsDesc: Record<U, string>\n    ): WebGLProgramObject<A, U> {\n        const vertexShader = getShader(this.gl, vertex, this.gl.VERTEX_SHADER);\n        const fragmentShader = getShader(this.gl, fragment, this.gl.FRAGMENT_SHADER);\n        const program = this.gl.createProgram();\n        this.gl.attachShader(program, vertexShader);\n        this.gl.attachShader(program, fragmentShader);\n        this.gl.linkProgram(program);\n\n        if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {\n            throw new Error('Could not initialise shaders');\n        }\n\n        const attributes = {} as Record<A, GLuint>;\n        for (const name in attributesDesc) {\n            attributes[name] = this.gl.getAttribLocation(program, name);\n            if (attributes[name] < 0) {\n                throw new Error('Missing shader attribute location: ' + name);\n            }\n        }\n\n        const uniforms = {} as Record<U, WebGLUniformLocation>;\n        for (const name in uniformsDesc) {\n            uniforms[name] = this.gl.getUniformLocation(program, name);\n            if (!uniforms[name]) {\n                throw new Error('Missing shader uniform location: ' + name);\n            }\n        }\n\n        return {\n            program,\n            vertexShader,\n            fragmentShader,\n            attributes,\n            uniforms\n        };\n    }\n\n    private destroyShaderProgramObject<A extends string, U extends string>(object: WebGLProgramObject<A, U>): void {\n        if (object.program) {\n            if (object.vertexShader) {\n                this.gl.detachShader(object.program, object.vertexShader);\n                this.gl.deleteShader(object.vertexShader);\n                object.vertexShader = null;\n            }\n            if (object.fragmentShader) {\n                this.gl.detachShader(object.program, object.fragmentShader);\n                this.gl.deleteShader(object.fragmentShader);\n                object.fragmentShader = null;\n            }\n            this.gl.deleteProgram(object.program);\n            object.program = null;\n        }\n    }\n\n    private initShaders (): void {\n        if (this.shaderProgram) {\n            return;\n        }\n\n        let vertexShaderSource;\n        if (this.isHD) {\n            vertexShaderSource = isWebGL2(this.gl) ? vertexShaderHDHardwareSkinningNew : vertexShaderHDHardwareSkinningOld;\n        } else if (this.softwareSkinning) {\n            vertexShaderSource = vertexShaderSoftwareSkinning;\n        } else {\n            vertexShaderSource = vertexShaderHardwareSkinning;\n        }\n\n        let fragmentShaderSource;\n        if (this.isHD) {\n            fragmentShaderSource = isWebGL2(this.gl) ? fragmentShaderHDNew : fragmentShaderHDOld;\n        } else {\n            fragmentShaderSource = fragmentShader;\n        }\n\n        const vertex = this.vertexShader = getShader(this.gl, vertexShaderSource, this.gl.VERTEX_SHADER);\n        const fragment = this.fragmentShader = getShader(this.gl, fragmentShaderSource, this.gl.FRAGMENT_SHADER);\n\n        const shaderProgram = this.shaderProgram = this.gl.createProgram();\n        this.gl.attachShader(shaderProgram, vertex);\n        this.gl.attachShader(shaderProgram, fragment);\n        this.gl.linkProgram(shaderProgram);\n\n        if (!this.gl.getProgramParameter(shaderProgram, this.gl.LINK_STATUS)) {\n            alert('Could not initialise shaders');\n        }\n\n        this.gl.useProgram(shaderProgram);\n\n        this.shaderProgramLocations.vertexPositionAttribute = this.gl.getAttribLocation(shaderProgram, 'aVertexPosition');\n        this.shaderProgramLocations.normalsAttribute = this.gl.getAttribLocation(shaderProgram, 'aNormal');\n        this.shaderProgramLocations.textureCoordAttribute = this.gl.getAttribLocation(shaderProgram, 'aTextureCoord');\n        if (this.isHD) {\n            this.shaderProgramLocations.skinAttribute = this.gl.getAttribLocation(shaderProgram, 'aSkin');\n            this.shaderProgramLocations.weightAttribute = this.gl.getAttribLocation(shaderProgram, 'aBoneWeight');\n            this.shaderProgramLocations.tangentAttribute = this.gl.getAttribLocation(shaderProgram, 'aTangent');\n        } else {\n            if (!this.softwareSkinning) {\n                this.shaderProgramLocations.groupAttribute = this.gl.getAttribLocation(shaderProgram, 'aGroup');\n            }\n        }\n\n        this.shaderProgramLocations.pMatrixUniform = this.gl.getUniformLocation(shaderProgram, 'uPMatrix');\n        this.shaderProgramLocations.mvMatrixUniform = this.gl.getUniformLocation(shaderProgram, 'uMVMatrix');\n        this.shaderProgramLocations.samplerUniform = this.gl.getUniformLocation(shaderProgram, 'uSampler');\n        this.shaderProgramLocations.replaceableColorUniform = this.gl.getUniformLocation(shaderProgram, 'uReplaceableColor');\n        if (this.isHD) {\n            this.shaderProgramLocations.normalSamplerUniform = this.gl.getUniformLocation(shaderProgram, 'uNormalSampler');\n            this.shaderProgramLocations.ormSamplerUniform = this.gl.getUniformLocation(shaderProgram, 'uOrmSampler');\n            this.shaderProgramLocations.lightPosUniform = this.gl.getUniformLocation(shaderProgram, 'uLightPos');\n            this.shaderProgramLocations.lightColorUniform = this.gl.getUniformLocation(shaderProgram, 'uLightColor');\n            this.shaderProgramLocations.cameraPosUniform = this.gl.getUniformLocation(shaderProgram, 'uCameraPos');\n\n            this.shaderProgramLocations.shadowParamsUniform = this.gl.getUniformLocation(shaderProgram, 'uShadowParams');\n            this.shaderProgramLocations.shadowMapSamplerUniform = this.gl.getUniformLocation(shaderProgram, 'uShadowMapSampler');\n            this.shaderProgramLocations.shadowMapLightMatrixUniform = this.gl.getUniformLocation(shaderProgram, 'uShadowMapLightMatrix');\n\n            this.shaderProgramLocations.hasEnvUniform = this.gl.getUniformLocation(shaderProgram, 'uHasEnv');\n            this.shaderProgramLocations.irradianceMapUniform = this.gl.getUniformLocation(shaderProgram, 'uIrradianceMap');\n            this.shaderProgramLocations.prefilteredEnvUniform = this.gl.getUniformLocation(shaderProgram, 'uPrefilteredEnv');\n            this.shaderProgramLocations.brdfLUTUniform = this.gl.getUniformLocation(shaderProgram, 'uBRDFLUT');\n        } else {\n            this.shaderProgramLocations.replaceableTypeUniform = this.gl.getUniformLocation(shaderProgram, 'uReplaceableType');\n        }\n        this.shaderProgramLocations.discardAlphaLevelUniform = this.gl.getUniformLocation(shaderProgram, 'uDiscardAlphaLevel');\n        this.shaderProgramLocations.tVertexAnimUniform = this.gl.getUniformLocation(shaderProgram, 'uTVertexAnim');\n        this.shaderProgramLocations.wireframeUniform = this.gl.getUniformLocation(shaderProgram, 'uWireframe');\n\n        if (!this.softwareSkinning) {\n            this.shaderProgramLocations.nodesMatricesAttributes = [];\n            for (let i = 0; i < MAX_NODES; ++i) {\n                this.shaderProgramLocations.nodesMatricesAttributes[i] =\n                    this.gl.getUniformLocation(shaderProgram, `uNodesMatrices[${i}]`);\n            }\n        }\n\n        if (this.isHD && isWebGL2(this.gl)) {\n            this.envToCubemap = this.initShaderProgram(envToCubemapVertexShader, envToCubemapFragmentShader, {\n                aPos: 'aPos'\n            }, {\n                uPMatrix: 'uPMatrix',\n                uMVMatrix: 'uMVMatrix',\n                uEquirectangularMap: 'uEquirectangularMap'\n            });\n\n            this.envSphere = this.initShaderProgram(envVertexShader, envFragmentShader, {\n                aPos: 'aPos'\n            }, {\n                uPMatrix: 'uPMatrix',\n                uMVMatrix: 'uMVMatrix',\n                uEnvironmentMap: 'uEnvironmentMap'\n            });\n\n            this.convoluteDiffuseEnv = this.initShaderProgram(convoluteEnvDiffuseVertexShader, convoluteEnvDiffuseFragmentShader, {\n                aPos: 'aPos'\n            }, {\n                uPMatrix: 'uPMatrix',\n                uMVMatrix: 'uMVMatrix',\n                uEnvironmentMap: 'uEnvironmentMap'\n            });\n\n            this.prefilterEnv = this.initShaderProgram(prefilterEnvVertexShader, prefilterEnvFragmentShader, {\n                aPos: 'aPos'\n            }, {\n                uPMatrix: 'uPMatrix',\n                uMVMatrix: 'uMVMatrix',\n                uEnvironmentMap: 'uEnvironmentMap',\n                uRoughness: 'uRoughness'\n            });\n\n            this.integrateBRDF = this.initShaderProgram(integrateBRDFVertexShader, integrateBRDFFragmentShader, {\n                aPos: 'aPos'\n            }, {});\n        }\n    }\n\n    private initGPUShaders (): void {\n        if (this.gpuShaderModule) {\n            return;\n        }\n\n        this.gpuShaderModule = this.device.createShaderModule({\n            label: 'main',\n            code: this.isHD ? hdShader : sdShader\n        });\n\n        this.gpuDepthShaderModule = this.device.createShaderModule({\n            label: 'depth',\n            code: depthShader\n        });\n\n        for (let i = 0; i < this.model.Textures.length; ++i) {\n            const texture = this.model.Textures[i];\n            const flags = texture.Flags;\n            const addressModeU: GPUAddressMode = flags & TextureFlags.WrapWidth ? 'repeat' : 'clamp-to-edge';\n            const addressModeV: GPUAddressMode = flags & TextureFlags.WrapHeight ? 'repeat' : 'clamp-to-edge';\n            this.rendererData.gpuSamplers[i] = this.device.createSampler({\n                label: `texture sampler ${i}`,\n                minFilter: 'linear',\n                magFilter: 'linear',\n                mipmapFilter: 'linear',\n                maxAnisotropy: 16,\n                addressModeU,\n                addressModeV\n            });\n        }\n\n        this.rendererData.gpuDepthSampler = this.device.createSampler({\n            label: 'texture depth sampler',\n            addressModeU: 'clamp-to-edge',\n            addressModeV: 'clamp-to-edge',\n            compare: 'less',\n            minFilter: 'nearest',\n            magFilter: 'nearest'\n        });\n\n        if (this.isHD) {\n            // Render env runtime\n            this.envShaderModeule = this.device.createShaderModule({\n                label: 'env',\n                code: envShader\n            });\n\n            this.envPiepeline = this.device.createRenderPipeline({\n                label: 'env',\n                layout: 'auto',\n                vertex: {\n                    module: this.envShaderModeule,\n                    buffers: [{\n                        arrayStride: 12,\n                        attributes: [{\n                            shaderLocation: 0,\n                            offset: 0,\n                            format: 'float32x3' as const\n                        }]\n                    }]\n                },\n                fragment: {\n                    module: this.envShaderModeule,\n                    targets: [{\n                        format: navigator.gpu.getPreferredCanvasFormat()\n                    }]\n                },\n                depthStencil: {\n                    depthWriteEnabled: false,\n                    depthCompare: 'always',\n                    format: 'depth24plus'\n                },\n                multisample: {\n                    count: MULTISAMPLE\n                }\n            });\n\n            this.envVSUniformsBuffer = this.device.createBuffer({\n                label: 'env vs uniforms',\n                size: 128,\n                usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n            });\n            this.envVSBindGroupLayout = this.envPiepeline.getBindGroupLayout(0);\n            this.envVSBindGroup = this.device.createBindGroup({\n                label: 'env vs bind group',\n                layout: this.envVSBindGroupLayout,\n                entries: [\n                    {\n                        binding: 0,\n                        resource: { buffer: this.envVSUniformsBuffer }\n                    }\n                ]\n            });\n\n            this.envSampler = this.device.createSampler({\n                label: 'env cube sampler',\n                addressModeU: 'clamp-to-edge',\n                addressModeV: 'clamp-to-edge',\n                addressModeW: 'clamp-to-edge',\n                minFilter: 'linear',\n                magFilter: 'linear'\n            });\n\n            this.envFSBindGroupLayout = this.envPiepeline.getBindGroupLayout(1);\n\n            // Convert env equirectangular map to the cube map\n            this.envToCubemapShaderModule = this.device.createShaderModule({\n                label: 'env to cubemap',\n                code: envToCubemapShader\n            });\n\n            this.envToCubemapPiepeline = this.device.createRenderPipeline({\n                label: 'env to cubemap',\n                layout: 'auto',\n                vertex: {\n                    module: this.envToCubemapShaderModule,\n                    buffers: [{\n                        arrayStride: 12,\n                        attributes: [{\n                            shaderLocation: 0,\n                            offset: 0,\n                            format: 'float32x3' as const\n                        }]\n                    }]\n                },\n                fragment: {\n                    module: this.envToCubemapShaderModule,\n                    targets: [{\n                        format: navigator.gpu.getPreferredCanvasFormat()\n                    }]\n                }\n            });\n\n            this.envToCubemapVSBindGroupLayout = this.envToCubemapPiepeline.getBindGroupLayout(0);\n\n            this.envToCubemapSampler = this.device.createSampler({\n                label: 'env to cubemap sampler',\n                addressModeU: 'clamp-to-edge',\n                addressModeV: 'clamp-to-edge',\n                minFilter: 'linear',\n                magFilter: 'linear'\n            });\n\n            this.envToCubemapFSBindGroupLayout = this.envToCubemapPiepeline.getBindGroupLayout(1);\n\n            this.convoluteDiffuseEnvShaderModule = this.device.createShaderModule({\n                label: 'convolute diffuse',\n                code: convoluteEnvDiffuseShader\n            });\n            this.convoluteDiffuseEnvPiepeline = this.device.createRenderPipeline({\n                label: 'convolute diffuse',\n                layout: 'auto',\n                vertex: {\n                    module: this.convoluteDiffuseEnvShaderModule,\n                    buffers: [{\n                        arrayStride: 12,\n                        attributes: [{\n                            shaderLocation: 0,\n                            offset: 0,\n                            format: 'float32x3' as const\n                        }]\n                    }]\n                },\n                fragment: {\n                    module: this.convoluteDiffuseEnvShaderModule,\n                    targets: [{\n                        format: navigator.gpu.getPreferredCanvasFormat()\n                    }]\n                }\n            });\n            this.convoluteDiffuseEnvVSBindGroupLayout = this.convoluteDiffuseEnvPiepeline.getBindGroupLayout(0);\n            this.convoluteDiffuseEnvFSBindGroupLayout = this.convoluteDiffuseEnvPiepeline.getBindGroupLayout(1);\n            this.convoluteDiffuseEnvSampler = this.device.createSampler({\n                label: 'convolute diffuse',\n                addressModeU: 'clamp-to-edge',\n                addressModeV: 'clamp-to-edge',\n                minFilter: 'linear',\n                magFilter: 'linear'\n            });\n\n\n            this.prefilterEnvShaderModule = this.device.createShaderModule({\n                label: 'prefilter env',\n                code: prefilterEnvShader\n            });\n            this.prefilterEnvPiepeline = this.device.createRenderPipeline({\n                label: 'prefilter env',\n                layout: 'auto',\n                vertex: {\n                    module: this.prefilterEnvShaderModule,\n                    buffers: [{\n                        arrayStride: 12,\n                        attributes: [{\n                            shaderLocation: 0,\n                            offset: 0,\n                            format: 'float32x3' as const\n                        }]\n                    }]\n                },\n                fragment: {\n                    module: this.prefilterEnvShaderModule,\n                    targets: [{\n                        format: navigator.gpu.getPreferredCanvasFormat()\n                    }]\n                }\n            });\n            this.prefilterEnvVSBindGroupLayout = this.prefilterEnvPiepeline.getBindGroupLayout(0);\n            this.prefilterEnvFSBindGroupLayout = this.prefilterEnvPiepeline.getBindGroupLayout(1);\n            this.prefilterEnvSampler = this.device.createSampler({\n                label: 'prefilter env',\n                addressModeU: 'clamp-to-edge',\n                addressModeV: 'clamp-to-edge',\n                addressModeW: 'clamp-to-edge',\n                minFilter: 'linear',\n                magFilter: 'linear'\n            });\n        }\n    }\n\n    private createWireframeBuffer (index: number): void {\n        const faces = this.model.Geosets[index].Faces;\n        const lines = new Uint16Array(faces.length * 2);\n\n        for (let i = 0; i < faces.length; i += 3) {\n            lines[i * 2]     = faces[i];\n            lines[i * 2 + 1] = faces[i + 1];\n            lines[i * 2 + 2] = faces[i + 1];\n            lines[i * 2 + 3] = faces[i + 2];\n            lines[i * 2 + 4] = faces[i + 2];\n            lines[i * 2 + 5] = faces[i];\n        }\n\n        this.wireframeIndexBuffer[index] = this.gl.createBuffer();\n        this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.wireframeIndexBuffer[index]);\n        this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, lines, this.gl.STATIC_DRAW);\n    }\n\n    private createWireframeGPUBuffer (index: number): void {\n        const faces = this.model.Geosets[index].Faces;\n        const lines = new Uint16Array(faces.length * 2);\n\n        for (let i = 0; i < faces.length; i += 3) {\n            lines[i * 2]     = faces[i];\n            lines[i * 2 + 1] = faces[i + 1];\n            lines[i * 2 + 2] = faces[i + 1];\n            lines[i * 2 + 3] = faces[i + 2];\n            lines[i * 2 + 4] = faces[i + 2];\n            lines[i * 2 + 5] = faces[i];\n        }\n\n        this.wireframeIndexGPUBuffer[index] = this.device.createBuffer({\n            label: `wireframe ${index}`,\n            size: lines.byteLength,\n            usage: GPUBufferUsage.INDEX,\n            mappedAtCreation: true\n        });\n        new Uint16Array(\n            this.wireframeIndexGPUBuffer[index].getMappedRange(0, this.wireframeIndexGPUBuffer[index].size)\n        ).set(lines);\n        this.wireframeIndexGPUBuffer[index].unmap();\n    }\n\n    private initBuffers (): void {\n        for (let i = 0; i < this.model.Geosets.length; ++i) {\n            const geoset = this.model.Geosets[i];\n\n            this.vertexBuffer[i] = this.gl.createBuffer();\n            if (this.softwareSkinning) {\n                this.vertices[i] = new Float32Array(geoset.Vertices.length);\n            } else {\n                this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer[i]);\n                this.gl.bufferData(this.gl.ARRAY_BUFFER, geoset.Vertices, this.gl.STATIC_DRAW);\n            }\n\n            this.normalBuffer[i] = this.gl.createBuffer();\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.normalBuffer[i]);\n            this.gl.bufferData(this.gl.ARRAY_BUFFER, geoset.Normals, this.gl.STATIC_DRAW);\n\n            this.texCoordBuffer[i] = this.gl.createBuffer();\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.texCoordBuffer[i]);\n            this.gl.bufferData(this.gl.ARRAY_BUFFER, geoset.TVertices[0], this.gl.STATIC_DRAW);\n\n            if (this.isHD) {\n                this.skinWeightBuffer[i] = this.gl.createBuffer();\n                this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.skinWeightBuffer[i]);\n                this.gl.bufferData(this.gl.ARRAY_BUFFER, geoset.SkinWeights, this.gl.STATIC_DRAW);\n\n                this.tangentBuffer[i] = this.gl.createBuffer();\n                this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.tangentBuffer[i]);\n                this.gl.bufferData(this.gl.ARRAY_BUFFER, geoset.Tangents, this.gl.STATIC_DRAW);\n            } else {\n                if (!this.softwareSkinning) {\n                    this.groupBuffer[i] = this.gl.createBuffer();\n                    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.groupBuffer[i]);\n                    const buffer = new Uint16Array(geoset.VertexGroup.length * 4);\n                    for (let j = 0; j < buffer.length; j += 4) {\n                        const index = j / 4;\n                        const group = geoset.Groups[geoset.VertexGroup[index]];\n                        buffer[j] = group[0];\n                        buffer[j + 1] = group.length > 1 ? group[1] : MAX_NODES;\n                        buffer[j + 2] = group.length > 2 ? group[2] : MAX_NODES;\n                        buffer[j + 3] = group.length > 3 ? group[3] : MAX_NODES;\n                    }\n                    this.gl.bufferData(this.gl.ARRAY_BUFFER, buffer, this.gl.STATIC_DRAW);\n                }\n            }\n\n            this.indexBuffer[i] = this.gl.createBuffer();\n            this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer[i]);\n            this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, geoset.Faces, this.gl.STATIC_DRAW);\n        }\n    }\n\n    private createGPUPipeline (\n        name: string,\n        blend: GPUBlendState | undefined,\n        depth: GPUDepthStencilState,\n        shaderModule: GPUShaderModule = this.gpuShaderModule,\n        extra: Partial<GPURenderPipelineDescriptor> = {}\n    ) : GPURenderPipeline {\n        return this.device.createRenderPipeline({\n            label: `pipeline ${name}`,\n            layout: this.gpuPipelineLayout,\n            vertex: {\n                module: shaderModule,\n                buffers: [{\n                    // vertices\n                    arrayStride: 12,\n                    attributes: [{\n                        shaderLocation: 0,\n                        offset: 0,\n                        format: 'float32x3' as const\n                    }]\n                }, {\n                    // normals\n                    arrayStride: 12,\n                    attributes: [{\n                        shaderLocation: 1,\n                        offset: 0,\n                        format: 'float32x3' as const\n                    }]\n                }, {\n                    // textureCoord\n                    arrayStride: 8,\n                    attributes: [{\n                        shaderLocation: 2,\n                        offset: 0,\n                        format: 'float32x2' as const\n                    }]\n                }, ...(this.isHD ? [{\n                    // tangents\n                    arrayStride: 16,\n                    attributes: [{\n                        shaderLocation: 3,\n                        offset: 0,\n                        format: 'float32x4' as const\n                    }]\n                }, {\n                    // skin\n                    arrayStride: 8,\n                    attributes: [{\n                        shaderLocation: 4,\n                        offset: 0,\n                        format: 'uint8x4' as const\n                    }]\n                }, {\n                    // boneWeight\n                    arrayStride: 8,\n                    attributes: [{\n                        shaderLocation: 5,\n                        offset: 4,\n                        format: 'unorm8x4' as const\n                    }]\n                }] : [{\n                    // group\n                    arrayStride: 4,\n                    attributes: [{\n                        shaderLocation: 3,\n                        offset: 0,\n                        format: 'uint8x4' as const\n                    }]\n                }])]\n            },\n            fragment: {\n                module: shaderModule,\n                targets: [{\n                    format: navigator.gpu.getPreferredCanvasFormat(),\n                    blend\n                }]\n            },\n            depthStencil: depth,\n            multisample: {\n                count: MULTISAMPLE\n            },\n            ...extra\n        });\n    }\n\n    private createGPUPipelineByLayer (filterMode: FilterMode, twoSided: boolean) : GPURenderPipeline {\n        return this.createGPUPipeline(...GPU_LAYER_PROPS[filterMode], undefined, {\n            primitive: {\n                cullMode: twoSided ? 'none' : 'back'\n            }\n        });\n    }\n\n    private getGPUPipeline (layer: Layer): GPURenderPipeline {\n        const filterMode = layer.FilterMode || 0;\n        const twoSided = Boolean((layer.Shading || 0) & LayerShading.TwoSided);\n\n        const key = `${filterMode}-${twoSided}`;\n\n        if (!this.gpuPipelines[key]) {\n            this.gpuPipelines[key] = this.createGPUPipelineByLayer(filterMode, twoSided);\n        }\n\n        return this.gpuPipelines[key];\n    }\n\n    private initGPUPipeline (): void {\n        this.vsBindGroupLayout = this.device.createBindGroupLayout({\n            label: 'vs bind group layout',\n            entries: [{\n                binding: 0,\n                visibility: GPUShaderStage.VERTEX,\n                buffer: {\n                    type: 'uniform',\n                    hasDynamicOffset: false,\n                    minBindingSize: 128 + 64 * MAX_NODES\n                }\n            }] as const\n        });\n        this.fsBindGroupLayout = this.device.createBindGroupLayout({\n            label: 'fs bind group layout2',\n            entries: this.isHD ? [\n                {\n                    binding: 0,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    buffer: {\n                        type: 'uniform',\n                        hasDynamicOffset: false,\n                        minBindingSize: 192\n                    }\n                },\n                {\n                    binding: 1,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    sampler: {\n                        type: 'filtering'\n                    }\n                },\n                {\n                    binding: 2,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    texture: {\n                        sampleType: 'float',\n                        viewDimension: '2d',\n                        multisampled: false\n                    }\n                },\n                {\n                    binding: 3,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    sampler: {\n                        type: 'filtering'\n                    }\n                },\n                {\n                    binding: 4,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    texture: {\n                        sampleType: 'float',\n                        viewDimension: '2d',\n                        multisampled: false\n                    }\n                },\n                {\n                    binding: 5,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    sampler: {\n                        type: 'filtering'\n                    }\n                },\n                {\n                    binding: 6,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    texture: {\n                        sampleType: 'float',\n                        viewDimension: '2d',\n                        multisampled: false\n                    }\n                },\n                {\n                    binding: 7,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    sampler: {\n                        type: 'comparison'\n                    }\n                },\n                {\n                    binding: 8,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    texture: {\n                        sampleType: 'depth',\n                        viewDimension: '2d',\n                        multisampled: false\n                    }\n                },\n                {\n                    binding: 9,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    sampler: {\n                        type: 'filtering'\n                    }\n                },\n                {\n                    binding: 10,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    texture: {\n                        sampleType: 'float',\n                        viewDimension: 'cube',\n                        multisampled: false\n                    }\n                },\n                {\n                    binding: 11,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    sampler: {\n                        type: 'filtering'\n                    }\n                },\n                {\n                    binding: 12,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    texture: {\n                        sampleType: 'float',\n                        viewDimension: 'cube',\n                        multisampled: false\n                    }\n                },\n                {\n                    binding: 13,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    sampler: {\n                        type: 'filtering'\n                    }\n                },\n                {\n                    binding: 14,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    texture: {\n                        sampleType: 'float',\n                        viewDimension: '2d',\n                        multisampled: false\n                    }\n                }\n            ] as const : [\n                {\n                    binding: 0,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    buffer: {\n                        type: 'uniform',\n                        hasDynamicOffset: false,\n                        minBindingSize: 80\n                    }\n                },\n                {\n                    binding: 1,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    sampler: {\n                        type: 'filtering'\n                    }\n                },\n                {\n                    binding: 2,\n                    visibility: GPUShaderStage.FRAGMENT,\n                    texture: {\n                        sampleType: 'float',\n                        viewDimension: '2d',\n                        multisampled: false\n                    }\n                }\n            ] as const\n        });\n\n        this.gpuPipelineLayout = this.device.createPipelineLayout({\n            label: 'pipeline layout',\n            bindGroupLayouts: [\n                this.vsBindGroupLayout,\n                this.fsBindGroupLayout\n            ]\n        });\n\n        this.gpuWireframePipeline = this.createGPUPipeline('wireframe', {\n            color: {\n                operation: 'add',\n                srcFactor: 'src-alpha',\n                dstFactor: 'one-minus-src-alpha'\n            },\n            alpha: {\n                operation: 'add',\n                srcFactor: 'one',\n                dstFactor: 'one-minus-src-alpha'\n            }\n        }, {\n            depthWriteEnabled: true,\n            depthCompare: 'less-equal',\n            format: 'depth24plus'\n        }, undefined, {\n            primitive: {\n                topology: 'line-list'\n            }\n        });\n\n        if (this.isHD) {\n            this.gpuShadowPipeline = this.createGPUPipeline('shadow', undefined, {\n                depthWriteEnabled: true,\n                depthCompare: 'less-equal',\n                format: 'depth32float'\n            }, this.gpuDepthShaderModule, {\n                fragment: {\n                    module: this.gpuDepthShaderModule,\n                    targets: []\n                },\n                multisample: {\n                    count: 1\n                }\n            });\n        }\n\n        this.gpuRenderPassDescriptor = {\n            label: 'basic renderPass',\n            colorAttachments: [\n                {\n                    view: null,\n                    clearValue: [0.15, 0.15, 0.15, 1],\n                    loadOp: 'clear' as const,\n                    storeOp: 'store' as const\n                }\n            ]\n        };\n    }\n\n    private initGPUBuffers (): void {\n        for (let i = 0; i < this.model.Geosets.length; ++i) {\n            const geoset = this.model.Geosets[i];\n\n            this.gpuVertexBuffer[i] = this.device.createBuffer({\n                label: `vertex ${i}`,\n                size: geoset.Vertices.byteLength,\n                usage: GPUBufferUsage.VERTEX,\n                mappedAtCreation: true\n            });\n            new Float32Array(\n                this.gpuVertexBuffer[i].getMappedRange(0, this.gpuVertexBuffer[i].size)\n            ).set(geoset.Vertices);\n            this.gpuVertexBuffer[i].unmap();\n\n            this.gpuNormalBuffer[i] = this.device.createBuffer({\n                label: `normal ${i}`,\n                size: geoset.Normals.byteLength,\n                usage: GPUBufferUsage.VERTEX,\n                mappedAtCreation: true\n            });\n            new Float32Array(\n                this.gpuNormalBuffer[i].getMappedRange(0, this.gpuNormalBuffer[i].size)\n            ).set(geoset.Normals);\n            this.gpuNormalBuffer[i].unmap();\n\n            this.gpuTexCoordBuffer[i] = this.device.createBuffer({\n                label: `texCoord ${i}`,\n                size: geoset.TVertices[0].byteLength,\n                usage: GPUBufferUsage.VERTEX,\n                mappedAtCreation: true\n            });\n            new Float32Array(\n                this.gpuTexCoordBuffer[i].getMappedRange(0, this.gpuTexCoordBuffer[i].size)\n            ).set(geoset.TVertices[0]);\n            this.gpuTexCoordBuffer[i].unmap();\n\n            if (this.isHD) {\n                this.gpuSkinWeightBuffer[i] = this.device.createBuffer({\n                    label: `SkinWeight ${i}`,\n                    size: geoset.SkinWeights.byteLength,\n                    usage: GPUBufferUsage.VERTEX,\n                    mappedAtCreation: true\n                });\n                new Uint8Array(\n                    this.gpuSkinWeightBuffer[i].getMappedRange(0, this.gpuSkinWeightBuffer[i].size)\n                ).set(geoset.SkinWeights);\n                this.gpuSkinWeightBuffer[i].unmap();\n\n                this.gpuTangentBuffer[i] = this.device.createBuffer({\n                    label: `Tangents ${i}`,\n                    size: geoset.Tangents.byteLength,\n                    usage: GPUBufferUsage.VERTEX,\n                    mappedAtCreation: true\n                });\n                new Float32Array(\n                    this.gpuTangentBuffer[i].getMappedRange(0, this.gpuTangentBuffer[i].size)\n                ).set(geoset.Tangents);\n                this.gpuTangentBuffer[i].unmap();\n            } else {\n                const buffer = new Uint8Array(geoset.VertexGroup.length * 4);\n                for (let j = 0; j < buffer.length; j += 4) {\n                    const index = j / 4;\n                    const group = geoset.Groups[geoset.VertexGroup[index]];\n                    buffer[j] = group[0];\n                    buffer[j + 1] = group.length > 1 ? group[1] : MAX_NODES;\n                    buffer[j + 2] = group.length > 2 ? group[2] : MAX_NODES;\n                    buffer[j + 3] = group.length > 3 ? group[3] : MAX_NODES;\n                }\n                this.gpuGroupBuffer[i] = this.device.createBuffer({\n                    label: `group ${i}`,\n                    size: 4 * geoset.VertexGroup.length,\n                    usage: GPUBufferUsage.VERTEX,\n                    mappedAtCreation: true\n                });\n                new Uint8Array(\n                    this.gpuGroupBuffer[i].getMappedRange(0, this.gpuGroupBuffer[i].size)\n                ).set(buffer);\n                this.gpuGroupBuffer[i].unmap();\n            }\n\n            const size = Math.ceil(geoset.Faces.byteLength / 4) * 4;\n            this.gpuIndexBuffer[i] = this.device.createBuffer({\n                label: `index ${i}`,\n                size: 2 * size,\n                usage: GPUBufferUsage.INDEX,\n                mappedAtCreation: true\n            });\n            new Uint16Array(\n                this.gpuIndexBuffer[i].getMappedRange(0, size)\n            ).set(geoset.Faces);\n            this.gpuIndexBuffer[i].unmap();\n        }\n    }\n\n    private initGPUUniformBuffers (): void {\n        this.gpuVSUniformsBuffer = this.device.createBuffer({\n            label: 'vs uniforms',\n            size: 128 + 64 * MAX_NODES,\n            usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n        });\n        this.gpuVSUniformsBindGroup = this.device.createBindGroup({\n            label: 'vs uniforms bind group',\n            layout: this.vsBindGroupLayout,\n            entries: [\n                {\n                    binding: 0,\n                    resource: { buffer: this.gpuVSUniformsBuffer }\n                }\n            ]\n        });\n    }\n\n    private initGPUMultisampleTexture (): void {\n        this.gpuMultisampleTexture = this.device.createTexture({\n            label: 'multisample texutre',\n            size: [this.canvas.width, this.canvas.height],\n            format: navigator.gpu.getPreferredCanvasFormat(),\n            usage: GPUTextureUsage.RENDER_ATTACHMENT,\n            sampleCount: MULTISAMPLE\n        });\n    }\n\n    private initGPUDepthTexture (): void {\n        this.gpuDepthTexture = this.device.createTexture({\n            label: 'depth texture',\n            size: [this.canvas.width, this.canvas.height],\n            format: 'depth24plus',\n            usage: GPUTextureUsage.RENDER_ATTACHMENT,\n            sampleCount: MULTISAMPLE\n        });\n    }\n\n    private initGPUEmptyTexture (): void {\n        const texture = this.rendererData.gpuEmptyTexture = this.device.createTexture({\n            label: 'empty texture',\n            size: [1, 1],\n            format: 'rgba8unorm',\n            usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n        });\n\n        this.device.queue.writeTexture(\n            { texture },\n            new Uint8Array([255, 255, 255, 255]),\n            { bytesPerRow: 1 * 4 },\n            { width: 1, height: 1 },\n        );\n\n        this.rendererData.gpuEmptyCubeTexture = this.device.createTexture({\n            label: 'empty cube texture',\n            size: [1, 1, 6],\n            format: 'rgba8unorm',\n            usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n        });\n\n        this.rendererData.gpuDepthEmptyTexture = this.device.createTexture({\n            label: 'empty depth texture',\n            size: [1, 1],\n            format: 'depth32float',\n            usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n        });\n    }\n\n    private initCube (): void {\n        const data = new Float32Array([\n            -0.5, -0.5,  -0.5,\n            -0.5,  0.5,  -0.5,\n            0.5, -0.5,  -0.5,\n            -0.5,  0.5,  -0.5,\n            0.5,  0.5,  -0.5,\n            0.5, -0.5,  -0.5,\n\n            -0.5, -0.5,   0.5,\n            0.5, -0.5,   0.5,\n            -0.5,  0.5,   0.5,\n            -0.5,  0.5,   0.5,\n            0.5, -0.5,   0.5,\n            0.5,  0.5,   0.5,\n\n            -0.5,   0.5, -0.5,\n            -0.5,   0.5,  0.5,\n            0.5,   0.5, -0.5,\n            -0.5,   0.5,  0.5,\n            0.5,   0.5,  0.5,\n            0.5,   0.5, -0.5,\n\n            -0.5,  -0.5, -0.5,\n            0.5,  -0.5, -0.5,\n            -0.5,  -0.5,  0.5,\n            -0.5,  -0.5,  0.5,\n            0.5,  -0.5, -0.5,\n            0.5,  -0.5,  0.5,\n\n            -0.5,  -0.5, -0.5,\n            -0.5,  -0.5,  0.5,\n            -0.5,   0.5, -0.5,\n            -0.5,  -0.5,  0.5,\n            -0.5,   0.5,  0.5,\n            -0.5,   0.5, -0.5,\n\n            0.5,  -0.5, -0.5,\n            0.5,   0.5, -0.5,\n            0.5,  -0.5,  0.5,\n            0.5,  -0.5,  0.5,\n            0.5,   0.5, -0.5,\n            0.5,   0.5,  0.5,\n        ]);\n\n        if (this.device) {\n            const vertex = this.cubeGPUVertexBuffer = this.device.createBuffer({\n                label: 'skeleton vertex',\n                size: data.byteLength,\n                usage: GPUBufferUsage.VERTEX,\n                mappedAtCreation: true\n            });\n            new Float32Array(\n                vertex.getMappedRange(0, vertex.size)\n            ).set(data);\n            vertex.unmap();\n        } else {\n            this.cubeVertexBuffer = this.gl.createBuffer();\n            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cubeVertexBuffer);\n            this.gl.bufferData(this.gl.ARRAY_BUFFER, data, this.gl.STATIC_DRAW);\n        }\n    }\n\n    private initSquare (): void {\n        this.squareVertexBuffer = this.gl.createBuffer();\n        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.squareVertexBuffer);\n        this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([\n            -1.0, -1.0,\n            1.0, -1.0,\n            -1.0, 1.0,\n            1.0, -1.0,\n            1.0, 1.0,\n            -1.0, 1.0,\n        ]), this.gl.STATIC_DRAW);\n    }\n\n    private initBRDFLUT (): void {\n        if (!isWebGL2(this.gl) || !this.isHD || !this.colorBufferFloatExt) {\n            return;\n        }\n\n        this.brdfLUT = this.gl.createTexture();\n        this.gl.activeTexture(this.gl.TEXTURE0);\n        this.gl.bindTexture(this.gl.TEXTURE_2D, this.brdfLUT);\n        this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RG16F, BRDF_LUT_SIZE, BRDF_LUT_SIZE, 0, this.gl.RG, this.gl.FLOAT, null);\n\n        this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n        this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n        this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n        this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n\n        const framebuffer = this.gl.createFramebuffer();\n        this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, framebuffer);\n        this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, this.gl.TEXTURE_2D, this.brdfLUT, 0);\n\n        this.gl.useProgram(this.integrateBRDF.program);\n\n        this.gl.viewport(0, 0, BRDF_LUT_SIZE, BRDF_LUT_SIZE);\n        this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n\n        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.squareVertexBuffer);\n        this.gl.enableVertexAttribArray(this.integrateBRDF.attributes.aPos);\n        this.gl.vertexAttribPointer(this.integrateBRDF.attributes.aPos, 2, this.gl.FLOAT, false, 0, 0);\n\n        this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);\n\n        this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n\n        this.gl.deleteFramebuffer(framebuffer);\n    }\n\n    private initGPUBRDFLUT (): void {\n        const shaderModule = this.device.createShaderModule({\n            label: 'integrate brdf',\n            code: integrateBRDFFShader\n        });\n\n        this.gpuBrdfLUT = this.device.createTexture({\n            label: 'brdf',\n            size: [BRDF_LUT_SIZE, BRDF_LUT_SIZE],\n            format: 'rg16float',\n            usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING\n        });\n\n        const square = new Float32Array([\n            -1.0, -1.0,\n            1.0, -1.0,\n            -1.0, 1.0,\n            1.0, -1.0,\n            1.0, 1.0,\n            -1.0, 1.0,\n        ]);\n        const buffer = this.device.createBuffer({\n            label: 'brdf square',\n            size:  square.byteLength,\n            usage: GPUBufferUsage.VERTEX,\n            mappedAtCreation: true\n        });\n        new Float32Array(\n            buffer.getMappedRange(0, buffer.size)\n        ).set(square);\n        buffer.unmap();\n\n        const encoder = this.device.createCommandEncoder({\n            label: 'integrate brdf'\n        });\n\n        const pass = encoder.beginRenderPass({\n            label: 'integrate brdf',\n            colorAttachments: [{\n                view: this.gpuBrdfLUT.createView(),\n                clearValue: [0, 0, 0, 1],\n                loadOp: 'clear',\n                storeOp: 'store'\n            }] as const\n        });\n\n        pass.setPipeline(this.device.createRenderPipeline({\n            label: 'integrate brdf',\n            layout: 'auto',\n            vertex: {\n                module: shaderModule,\n                buffers: [{\n                    arrayStride: 8,\n                    attributes: [{\n                        shaderLocation: 0,\n                        offset: 0,\n                        format: 'float32x2' as const\n                    }]\n                }]\n            },\n            fragment: {\n                module: shaderModule,\n                targets: [{\n                    format: 'rg16float'\n                }] as const\n            }\n        }));\n\n        pass.setVertexBuffer(0, buffer);\n        pass.draw(6);\n        pass.end();\n\n        const commandBuffer = encoder.finish();\n        this.device.queue.submit([commandBuffer]);\n        this.device.queue.onSubmittedWorkDone().finally(() => {\n            buffer.destroy();\n        });\n\n        this.gpuBrdfSampler = this.device.createSampler({\n            label: 'brdf lut',\n            addressModeU: 'clamp-to-edge',\n            addressModeV: 'clamp-to-edge',\n            minFilter: 'linear',\n            magFilter: 'linear'\n        });\n    }\n\n    /*private resetGlobalSequences (): void {\n        for (let i = 0; i < this.rendererData.globalSequencesFrames.length; ++i) {\n            this.rendererData.globalSequencesFrames[i] = 0;\n        }\n    }*/\n\n    private updateGlobalSequences (delta: number): void {\n        for (let i = 0; i < this.rendererData.globalSequencesFrames.length; ++i) {\n            this.rendererData.globalSequencesFrames[i] += delta;\n            if (this.rendererData.globalSequencesFrames[i] > this.model.GlobalSequences[i]) {\n                this.rendererData.globalSequencesFrames[i] = 0;\n            }\n        }\n    }\n\n    private updateNode (node: NodeWrapper): void {\n        const translationRes = this.interp.vec3(translation, node.node.Translation);\n        const rotationRes = this.interp.quat(rotation, node.node.Rotation);\n        const scalingRes = this.interp.vec3(scaling, node.node.Scaling);\n\n        if (!translationRes && !rotationRes && !scalingRes) {\n            mat4.identity(node.matrix);\n        } else if (translationRes && !rotationRes && !scalingRes) {\n            mat4.fromTranslation(node.matrix, translationRes);\n        } else if (!translationRes && rotationRes && !scalingRes) {\n            mat4fromRotationOrigin(node.matrix, rotationRes, node.node.PivotPoint as vec3);\n        } else {\n            mat4.fromRotationTranslationScaleOrigin(node.matrix,\n                rotationRes || defaultRotation,\n                translationRes || defaultTranslation,\n                scalingRes || defaultScaling,\n                node.node.PivotPoint as vec3\n            );\n        }\n\n        if (node.node.Parent || node.node.Parent === 0) {\n            mat4.mul(node.matrix, this.rendererData.nodes[node.node.Parent].matrix, node.matrix);\n        }\n\n        const billboardedLock = node.node.Flags & NodeFlags.BillboardedLockX ||\n            node.node.Flags & NodeFlags.BillboardedLockY ||\n            node.node.Flags & NodeFlags.BillboardedLockZ;\n\n        if (node.node.Flags & NodeFlags.Billboarded) {\n            vec3.transformMat4(tempTransformedPivotPoint, node.node.PivotPoint as vec3, node.matrix);\n\n            if (node.node.Parent || node.node.Parent === 0) {\n                // cancel parent rotation from PivotPoint\n                mat4.getRotation(tempParentRotationQuat, this.rendererData.nodes[node.node.Parent].matrix);\n                quat.invert(tempParentRotationQuat, tempParentRotationQuat);\n                mat4fromRotationOrigin(tempParentRotationMat, tempParentRotationQuat,\n                    tempTransformedPivotPoint);\n                mat4.mul(node.matrix, tempParentRotationMat, node.matrix);\n            }\n\n            // rotate to camera\n            mat4fromRotationOrigin(tempCameraMat, this.rendererData.cameraQuat,\n                tempTransformedPivotPoint);\n            mat4.mul(node.matrix, tempCameraMat, node.matrix);\n        } else if (billboardedLock) {\n            vec3.transformMat4(tempTransformedPivotPoint, node.node.PivotPoint as vec3, node.matrix);\n            vec3.copy(tempAxis, node.node.PivotPoint as vec3);\n\n            // todo BillboardedLockX ?\n            if (node.node.Flags & NodeFlags.BillboardedLockX) {\n                tempAxis[0] += 1;\n            } else if (node.node.Flags & NodeFlags.BillboardedLockY) {\n                tempAxis[1] += 1;\n            } else if (node.node.Flags & NodeFlags.BillboardedLockZ) {\n                tempAxis[2] += 1;\n            }\n\n            vec3.transformMat4(tempAxis, tempAxis, node.matrix);\n            vec3.sub(tempAxis, tempAxis, tempTransformedPivotPoint);\n\n            vec3.set(tempXAxis, 1, 0, 0);\n            vec3.add(tempXAxis, tempXAxis, node.node.PivotPoint as vec3);\n            vec3.transformMat4(tempXAxis, tempXAxis, node.matrix);\n            vec3.sub(tempXAxis, tempXAxis, tempTransformedPivotPoint);\n\n            vec3.set(tempCameraVec, -1, 0, 0);\n            vec3.transformQuat(tempCameraVec, tempCameraVec, this.rendererData.cameraQuat);\n\n            vec3.cross(tempCross0, tempAxis, tempCameraVec);\n            vec3.cross(tempCross1, tempAxis, tempCross0);\n\n            vec3.normalize(tempCross1, tempCross1);\n\n            quat.rotationTo(tempLockQuat, tempXAxis, tempCross1);\n            mat4fromRotationOrigin(tempLockMat, tempLockQuat, tempTransformedPivotPoint);\n            mat4.mul(node.matrix, tempLockMat, node.matrix);\n        }\n\n        for (const child of node.childs) {\n            this.updateNode(child);\n        }\n    }\n\n    private findAlpha (geosetId: number): number {\n        const geosetAnim = this.rendererData.geosetAnims[geosetId];\n\n        if (!geosetAnim || geosetAnim.Alpha === undefined) {\n            return 1;\n        }\n\n        if (typeof geosetAnim.Alpha === 'number') {\n            return geosetAnim.Alpha;\n        }\n\n        const interpRes = this.interp.num(geosetAnim.Alpha);\n\n        if (interpRes === null) {\n            return 1;\n        }\n        return interpRes;\n    }\n\n    private getTexCoordMatrix (layer: Layer): mat3 {\n        if (typeof layer.TVertexAnimId === 'number') {\n            const anim: TVertexAnim = this.rendererData.model.TextureAnims[layer.TVertexAnimId];\n            const translationRes = this.interp.vec3(translation, anim.Translation);\n            const rotationRes = this.interp.quat(rotation, anim.Rotation);\n            const scalingRes = this.interp.vec3(scaling, anim.Scaling);\n            mat4.fromRotationTranslationScale(\n                texCoordMat4,\n                rotationRes || defaultRotation,\n                translationRes || defaultTranslation,\n                scalingRes || defaultScaling\n            );\n            mat3.set(\n                texCoordMat3,\n                texCoordMat4[0], texCoordMat4[1], 0,\n                texCoordMat4[4], texCoordMat4[5], 0,\n                texCoordMat4[12], texCoordMat4[13], 0\n            );\n\n            return texCoordMat3;\n        } else {\n            return identifyMat3;\n        }\n    }\n\n    private setLayerProps (layer: Layer, textureID: number): void {\n        const texture = this.model.Textures[textureID];\n\n        if (layer.Shading & LayerShading.TwoSided) {\n            this.gl.disable(this.gl.CULL_FACE);\n        } else {\n            this.gl.enable(this.gl.CULL_FACE);\n        }\n\n        if (layer.FilterMode === FilterMode.Transparent) {\n            this.gl.uniform1f(this.shaderProgramLocations.discardAlphaLevelUniform, 0.75);\n        } else {\n            this.gl.uniform1f(this.shaderProgramLocations.discardAlphaLevelUniform, 0.);\n        }\n\n        if (layer.FilterMode === FilterMode.None) {\n            this.gl.disable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            // this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);\n            this.gl.depthMask(true);\n        } else if (layer.FilterMode === FilterMode.Transparent) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);\n            this.gl.depthMask(true);\n        } else if (layer.FilterMode === FilterMode.Blend) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);\n            this.gl.depthMask(false);\n        } else if (layer.FilterMode === FilterMode.Additive) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFunc(this.gl.SRC_COLOR, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (layer.FilterMode === FilterMode.AddAlpha) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (layer.FilterMode === FilterMode.Modulate) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.ZERO, this.gl.SRC_COLOR, this.gl.ZERO, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (layer.FilterMode === FilterMode.Modulate2x) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.DST_COLOR, this.gl.SRC_COLOR, this.gl.ZERO, this.gl.ONE);\n            this.gl.depthMask(false);\n        }\n\n        if (texture.Image) {\n            this.gl.activeTexture(this.gl.TEXTURE0);\n            this.gl.bindTexture(this.gl.TEXTURE_2D, this.rendererData.textures[texture.Image]);\n            this.gl.uniform1i(this.shaderProgramLocations.samplerUniform, 0);\n            this.gl.uniform1f(this.shaderProgramLocations.replaceableTypeUniform, 0);\n        } else if (texture.ReplaceableId === 1 || texture.ReplaceableId === 2) {\n            this.gl.uniform3fv(this.shaderProgramLocations.replaceableColorUniform, this.rendererData.teamColor);\n            this.gl.uniform1f(this.shaderProgramLocations.replaceableTypeUniform, texture.ReplaceableId);\n        }\n\n        if (layer.Shading & LayerShading.NoDepthTest) {\n            this.gl.disable(this.gl.DEPTH_TEST);\n        }\n        if (layer.Shading & LayerShading.NoDepthSet) {\n            this.gl.depthMask(false);\n        }\n\n        this.gl.uniformMatrix3fv(this.shaderProgramLocations.tVertexAnimUniform, false, this.getTexCoordMatrix(layer));\n    }\n\n    private setLayerPropsHD (materialID: number, layers: Layer[]): void {\n        const baseLayer = layers[0];\n        const textures = this.rendererData.materialLayerTextureID[materialID];\n        const normalTextres = this.rendererData.materialLayerNormalTextureID[materialID];\n        const ormTextres = this.rendererData.materialLayerOrmTextureID[materialID];\n        const diffuseTextureID = textures[0];\n        const diffuseTexture = this.model.Textures[diffuseTextureID];\n        const normalTextureID = baseLayer?.ShaderTypeId === 1 ? normalTextres[0] : textures[1];\n        const normalTexture = this.model.Textures[normalTextureID];\n        const ormTextureID = baseLayer?.ShaderTypeId === 1 ? ormTextres[0] : textures[2];\n        const ormTexture = this.model.Textures[ormTextureID];\n        // const emissiveTextureID = textures[3];\n        // const emissiveTexture = this.model.Textures[emissiveTextureID];\n        // const teamColorTextureID = textures[4];\n        // const teamColorTexture = this.model.Textures[teamColorTextureID];\n        // const envTextureID = textures[5];\n        // const envTexture = this.model.Textures[envTextureID];\n\n        if (baseLayer.Shading & LayerShading.TwoSided) {\n            this.gl.disable(this.gl.CULL_FACE);\n        } else {\n            this.gl.enable(this.gl.CULL_FACE);\n        }\n\n        if (baseLayer.FilterMode === FilterMode.Transparent) {\n            this.gl.uniform1f(this.shaderProgramLocations.discardAlphaLevelUniform, 0.75);\n        } else {\n            this.gl.uniform1f(this.shaderProgramLocations.discardAlphaLevelUniform, 0.);\n        }\n\n        if (baseLayer.FilterMode === FilterMode.None) {\n            this.gl.disable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            // this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);\n            this.gl.depthMask(true);\n        } else if (baseLayer.FilterMode === FilterMode.Transparent) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);\n            this.gl.depthMask(true);\n        } else if (baseLayer.FilterMode === FilterMode.Blend) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA, this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);\n            this.gl.depthMask(false);\n        } else if (baseLayer.FilterMode === FilterMode.Additive) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFunc(this.gl.SRC_COLOR, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (baseLayer.FilterMode === FilterMode.AddAlpha) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (baseLayer.FilterMode === FilterMode.Modulate) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.ZERO, this.gl.SRC_COLOR, this.gl.ZERO, this.gl.ONE);\n            this.gl.depthMask(false);\n        } else if (baseLayer.FilterMode === FilterMode.Modulate2x) {\n            this.gl.enable(this.gl.BLEND);\n            this.gl.enable(this.gl.DEPTH_TEST);\n            this.gl.blendFuncSeparate(this.gl.DST_COLOR, this.gl.SRC_COLOR, this.gl.ZERO, this.gl.ONE);\n            this.gl.depthMask(false);\n        }\n\n        this.gl.activeTexture(this.gl.TEXTURE0);\n        this.gl.bindTexture(this.gl.TEXTURE_2D, this.rendererData.textures[diffuseTexture.Image]);\n        this.gl.uniform1i(this.shaderProgramLocations.samplerUniform, 0);\n\n        if (baseLayer.Shading & LayerShading.NoDepthTest) {\n            this.gl.disable(this.gl.DEPTH_TEST);\n        }\n        if (baseLayer.Shading & LayerShading.NoDepthSet) {\n            this.gl.depthMask(false);\n        }\n\n        if (typeof baseLayer.TVertexAnimId === 'number') {\n            const anim: TVertexAnim = this.rendererData.model.TextureAnims[baseLayer.TVertexAnimId];\n            const translationRes = this.interp.vec3(translation, anim.Translation);\n            const rotationRes = this.interp.quat(rotation, anim.Rotation);\n            const scalingRes = this.interp.vec3(scaling, anim.Scaling);\n            mat4.fromRotationTranslationScale(\n                texCoordMat4,\n                rotationRes || defaultRotation,\n                translationRes || defaultTranslation,\n                scalingRes || defaultScaling\n            );\n            mat3.set(\n                texCoordMat3,\n                texCoordMat4[0], texCoordMat4[1], 0,\n                texCoordMat4[4], texCoordMat4[5], 0,\n                texCoordMat4[12], texCoordMat4[13], 0\n            );\n\n            this.gl.uniformMatrix3fv(this.shaderProgramLocations.tVertexAnimUniform, false, texCoordMat3);\n        } else {\n            this.gl.uniformMatrix3fv(this.shaderProgramLocations.tVertexAnimUniform, false, identifyMat3);\n        }\n\n        this.gl.activeTexture(this.gl.TEXTURE1);\n        this.gl.bindTexture(this.gl.TEXTURE_2D, this.rendererData.textures[normalTexture.Image]);\n        this.gl.uniform1i(this.shaderProgramLocations.normalSamplerUniform, 1);\n\n        this.gl.activeTexture(this.gl.TEXTURE2);\n        this.gl.bindTexture(this.gl.TEXTURE_2D, this.rendererData.textures[ormTexture.Image]);\n        this.gl.uniform1i(this.shaderProgramLocations.ormSamplerUniform, 2);\n\n        this.gl.uniform3fv(this.shaderProgramLocations.replaceableColorUniform, this.rendererData.teamColor);\n    }\n}\n"],"x_google_ignoreList":[9,10,11,12,13,14],"mappings":"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"}