UNPKG

three-stdlib

Version:

stand-alone library of threejs examples

1,436 lines • 50.1 kB
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
class AssimpLoader extends THREE.Loader {
  load(url, onLoad, onProgress, onError) {
    var scope = this;
    var path = scope.path === "" ? THREE.LoaderUtils.extractUrlBase(url) : scope.path;
    var loader = new THREE.FileLoader(scope.manager);
    loader.setPath(scope.path);
    loader.setResponseType("arraybuffer");
    loader.setRequestHeader(scope.requestHeader);
    loader.setWithCredentials(scope.withCredentials);
    loader.load(
      url,
      function(buffer) {
        try {
          onLoad(scope.parse(buffer, path));
        } catch (e) {
          if (onError) {
            onError(e);
          } else {
            console.error(e);
          }
          scope.manager.itemError(url);
        }
      },
      onProgress,
      onError
    );
  }
  parse(buffer, path) {
    var textureLoader = new THREE.TextureLoader(this.manager);
    textureLoader.setPath(this.resourcePath || path).setCrossOrigin(this.crossOrigin);
    var Virtulous = {};
    Virtulous.KeyFrame = class {
      constructor(time, matrix) {
        this.time = time;
        this.matrix = matrix.clone();
        this.position = new THREE.Vector3();
        this.quaternion = new THREE.Quaternion();
        this.scale = new THREE.Vector3(1, 1, 1);
        this.matrix.decompose(this.position, this.quaternion, this.scale);
        this.clone = function() {
          var n = new Virtulous.KeyFrame(this.time, this.matrix);
          return n;
        };
        this.lerp = function(nextKey, time2) {
          time2 -= this.time;
          var dist = nextKey.time - this.time;
          var l = time2 / dist;
          var l2 = 1 - l;
          var keypos = this.position;
          var keyrot = this.quaternion;
          var key2pos = nextKey.position;
          var key2rot = nextKey.quaternion;
          Virtulous.KeyFrame.tempAniPos.x = keypos.x * l2 + key2pos.x * l;
          Virtulous.KeyFrame.tempAniPos.y = keypos.y * l2 + key2pos.y * l;
          Virtulous.KeyFrame.tempAniPos.z = keypos.z * l2 + key2pos.z * l;
          Virtulous.KeyFrame.tempAniQuat.set(keyrot.x, keyrot.y, keyrot.z, keyrot.w);
          Virtulous.KeyFrame.tempAniQuat.slerp(key2rot, l);
          return Virtulous.KeyFrame.tempAniMatrix.compose(
            Virtulous.KeyFrame.tempAniPos,
            Virtulous.KeyFrame.tempAniQuat,
            Virtulous.KeyFrame.tempAniScale
          );
        };
      }
    };
    Virtulous.KeyFrame.tempAniPos = new THREE.Vector3();
    Virtulous.KeyFrame.tempAniQuat = new THREE.Quaternion();
    Virtulous.KeyFrame.tempAniScale = new THREE.Vector3(1, 1, 1);
    Virtulous.KeyFrame.tempAniMatrix = new THREE.Matrix4();
    Virtulous.KeyFrameTrack = function() {
      this.keys = [];
      this.target = null;
      this.time = 0;
      this.length = 0;
      this._accelTable = {};
      this.fps = 20;
      this.addKey = function(key) {
        this.keys.push(key);
      };
      this.init = function() {
        this.sortKeys();
        if (this.keys.length > 0)
          this.length = this.keys[this.keys.length - 1].time;
        else
          this.length = 0;
        if (!this.fps)
          return;
        for (let j = 0; j < this.length * this.fps; j++) {
          for (let i = 0; i < this.keys.length; i++) {
            if (this.keys[i].time == j) {
              this._accelTable[j] = i;
              break;
            } else if (this.keys[i].time < j / this.fps && this.keys[i + 1] && this.keys[i + 1].time >= j / this.fps) {
              this._accelTable[j] = i;
              break;
            }
          }
        }
      };
      this.parseFromThree = function(data) {
        var fps = data.fps;
        this.target = data.node;
        var track = data.hierarchy[0].keys;
        for (let i = 0; i < track.length; i++) {
          this.addKey(new Virtulous.KeyFrame(i / fps || track[i].time, track[i].targets[0].data));
        }
        this.init();
      };
      this.parseFromCollada = function(data) {
        var track = data.keys;
        var fps = this.fps;
        for (let i = 0; i < track.length; i++) {
          this.addKey(new Virtulous.KeyFrame(i / fps || track[i].time, track[i].matrix));
        }
        this.init();
      };
      this.sortKeys = function() {
        this.keys.sort(this.keySortFunc);
      };
      this.keySortFunc = function(a, b) {
        return a.time - b.time;
      };
      this.clone = function() {
        var t = new Virtulous.KeyFrameTrack();
        t.target = this.target;
        t.time = this.time;
        t.length = this.length;
        for (let i = 0; i < this.keys.length; i++) {
          t.addKey(this.keys[i].clone());
        }
        t.init();
        return t;
      };
      this.reTarget = function(root, compareitor) {
        if (!compareitor)
          compareitor = Virtulous.TrackTargetNodeNameCompare;
        this.target = compareitor(root, this.target);
      };
      this.keySearchAccel = function(time) {
        time *= this.fps;
        time = Math.floor(time);
        return this._accelTable[time] || 0;
      };
      this.setTime = function(time) {
        time = Math.abs(time);
        if (this.length)
          time = time % this.length + 0.05;
        var key0 = null;
        var key1 = null;
        for (let i = this.keySearchAccel(time); i < this.keys.length; i++) {
          if (this.keys[i].time == time) {
            key0 = this.keys[i];
            key1 = this.keys[i];
            break;
          } else if (this.keys[i].time < time && this.keys[i + 1] && this.keys[i + 1].time > time) {
            key0 = this.keys[i];
            key1 = this.keys[i + 1];
            break;
          } else if (this.keys[i].time < time && i == this.keys.length - 1) {
            key0 = this.keys[i];
            key1 = this.keys[0].clone();
            key1.time += this.length + 0.05;
            break;
          }
        }
        if (key0 && key1 && key0 !== key1) {
          this.target.matrixAutoUpdate = false;
          this.target.matrix.copy(key0.lerp(key1, time));
          this.target.matrixWorldNeedsUpdate = true;
          return;
        }
        if (key0 && key1 && key0 == key1) {
          this.target.matrixAutoUpdate = false;
          this.target.matrix.copy(key0.matrix);
          this.target.matrixWorldNeedsUpdate = true;
          return;
        }
      };
    };
    Virtulous.TrackTargetNodeNameCompare = function(root, target) {
      function find(node, name) {
        if (node.name == name)
          return node;
        for (let i = 0; i < node.children.length; i++) {
          var r = find(node.children[i], name);
          if (r)
            return r;
        }
        return null;
      }
      return find(root, target.name);
    };
    Virtulous.Animation = function() {
      this.tracks = [];
      this.length = 0;
      this.addTrack = function(track) {
        this.tracks.push(track);
        this.length = Math.max(track.length, this.length);
      };
      this.setTime = function(time) {
        this.time = time;
        for (let i = 0; i < this.tracks.length; i++)
          this.tracks[i].setTime(time);
      };
      this.clone = function(target, compareitor) {
        if (!compareitor)
          compareitor = Virtulous.TrackTargetNodeNameCompare;
        var n = new Virtulous.Animation();
        n.target = target;
        for (let i = 0; i < this.tracks.length; i++) {
          var track = this.tracks[i].clone();
          track.reTarget(target, compareitor);
          n.addTrack(track);
        }
        return n;
      };
    };
    var ASSBIN_CHUNK_AICAMERA = 4660;
    var ASSBIN_CHUNK_AILIGHT = 4661;
    var ASSBIN_CHUNK_AITEXTURE = 4662;
    var ASSBIN_CHUNK_AIMESH = 4663;
    var ASSBIN_CHUNK_AINODEANIM = 4664;
    var ASSBIN_CHUNK_AISCENE = 4665;
    var ASSBIN_CHUNK_AIBONE = 4666;
    var ASSBIN_CHUNK_AIANIMATION = 4667;
    var ASSBIN_CHUNK_AINODE = 4668;
    var ASSBIN_CHUNK_AIMATERIAL = 4669;
    var ASSBIN_CHUNK_AIMATERIALPROPERTY = 4670;
    var ASSBIN_MESH_HAS_POSITIONS = 1;
    var ASSBIN_MESH_HAS_NORMALS = 2;
    var ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS = 4;
    var ASSBIN_MESH_HAS_TEXCOORD_BASE = 256;
    var ASSBIN_MESH_HAS_COLOR_BASE = 65536;
    var AI_MAX_NUMBER_OF_COLOR_SETS = 1;
    var AI_MAX_NUMBER_OF_TEXTURECOORDS = 4;
    //! A directional light source has a well-defined direction
    //! but is infinitely far away. That's quite a good
    //! approximation for sun light.
    var aiLightSource_DIRECTIONAL = 1;
    //! A point light source has a well-defined position
    //! in space but no direction - it emits light in all
    //! directions. A normal bulb is a point light.
    //! A spot light source emits light in a specific
    //! angle. It has a position and a direction it is pointing to.
    //! A good example for a spot light is a light spot in
    //! sport arenas.
    var aiLightSource_SPOT = 3;
    //! The generic light level of the world, including the bounces
    //! of all other lightsources.
    //! Typically, there's at most one ambient light in a scene.
    //! This light type doesn't have a valid position, direction, or
    //! other properties, just a color.
    var aiTextureType_DIFFUSE = 1;
    var aiTextureType_NORMALS = 6;
    var aiTextureType_OPACITY = 8;
    var aiTextureType_LIGHTMAP = 10;
    var BONESPERVERT = 4;
    function ASSBIN_MESH_HAS_TEXCOORD(n) {
      return ASSBIN_MESH_HAS_TEXCOORD_BASE << n;
    }
    function ASSBIN_MESH_HAS_COLOR(n) {
      return ASSBIN_MESH_HAS_COLOR_BASE << n;
    }
    function markBones(scene) {
      for (let i in scene.mMeshes) {
        var mesh = scene.mMeshes[i];
        for (let k in mesh.mBones) {
          var boneNode = scene.findNode(mesh.mBones[k].mName);
          if (boneNode)
            boneNode.isBone = true;
        }
      }
    }
    function cloneTreeToBones(root, scene) {
      var rootBone = new THREE.Bone();
      rootBone.matrix.copy(root.matrix);
      rootBone.matrixWorld.copy(root.matrixWorld);
      rootBone.position.copy(root.position);
      rootBone.quaternion.copy(root.quaternion);
      rootBone.scale.copy(root.scale);
      scene.nodeCount++;
      rootBone.name = "bone_" + root.name + scene.nodeCount.toString();
      if (!scene.nodeToBoneMap[root.name])
        scene.nodeToBoneMap[root.name] = [];
      scene.nodeToBoneMap[root.name].push(rootBone);
      for (let i in root.children) {
        var child = cloneTreeToBones(root.children[i], scene);
        rootBone.add(child);
      }
      return rootBone;
    }
    function sortWeights(indexes, weights) {
      var pairs = [];
      for (let i = 0; i < indexes.length; i++) {
        pairs.push({
          i: indexes[i],
          w: weights[i]
        });
      }
      pairs.sort(function(a, b) {
        return b.w - a.w;
      });
      while (pairs.length < 4) {
        pairs.push({
          i: 0,
          w: 0
        });
      }
      if (pairs.length > 4)
        pairs.length = 4;
      var sum = 0;
      for (let i = 0; i < 4; i++) {
        sum += pairs[i].w * pairs[i].w;
      }
      sum = Math.sqrt(sum);
      for (let i = 0; i < 4; i++) {
        pairs[i].w = pairs[i].w / sum;
        indexes[i] = pairs[i].i;
        weights[i] = pairs[i].w;
      }
    }
    function findMatchingBone(root, name) {
      if (root.name.indexOf("bone_" + name) == 0)
        return root;
      for (let i in root.children) {
        var ret = findMatchingBone(root.children[i], name);
        if (ret)
          return ret;
      }
      return void 0;
    }
    class aiMesh {
      constructor() {
        this.mPrimitiveTypes = 0;
        this.mNumVertices = 0;
        this.mNumFaces = 0;
        this.mNumBones = 0;
        this.mMaterialIndex = 0;
        this.mVertices = [];
        this.mNormals = [];
        this.mTangents = [];
        this.mBitangents = [];
        this.mColors = [[]];
        this.mTextureCoords = [[]];
        this.mFaces = [];
        this.mBones = [];
        this.hookupSkeletons = function(scene) {
          if (this.mBones.length == 0)
            return;
          var allBones = [];
          var offsetMatrix = [];
          var skeletonRoot = scene.findNode(this.mBones[0].mName);
          while (skeletonRoot.mParent && skeletonRoot.mParent.isBone) {
            skeletonRoot = skeletonRoot.mParent;
          }
          var threeSkeletonRoot = skeletonRoot.toTHREE(scene);
          var threeSkeletonRootBone = cloneTreeToBones(threeSkeletonRoot, scene);
          this.threeNode.add(threeSkeletonRootBone);
          for (let i = 0; i < this.mBones.length; i++) {
            var bone = findMatchingBone(threeSkeletonRootBone, this.mBones[i].mName);
            if (bone) {
              var tbone = bone;
              allBones.push(tbone);
              offsetMatrix.push(this.mBones[i].mOffsetMatrix.toTHREE());
            } else {
              var skeletonRoot = scene.findNode(this.mBones[i].mName);
              if (!skeletonRoot)
                return;
              var threeSkeletonRoot = skeletonRoot.toTHREE(scene);
              var threeSkeletonRootBone = cloneTreeToBones(threeSkeletonRoot, scene);
              this.threeNode.add(threeSkeletonRootBone);
              var bone = findMatchingBone(threeSkeletonRootBone, this.mBones[i].mName);
              var tbone = bone;
              allBones.push(tbone);
              offsetMatrix.push(this.mBones[i].mOffsetMatrix.toTHREE());
            }
          }
          var skeleton = new THREE.Skeleton(allBones, offsetMatrix);
          this.threeNode.bind(skeleton, new THREE.Matrix4());
          this.threeNode.material.skinning = true;
        };
        this.toTHREE = function(scene) {
          if (this.threeNode)
            return this.threeNode;
          var geometry = new THREE.BufferGeometry();
          var mat;
          if (scene.mMaterials[this.mMaterialIndex])
            mat = scene.mMaterials[this.mMaterialIndex].toTHREE(scene);
          else
            mat = new THREE.MeshLambertMaterial();
          geometry.setIndex(new THREE.BufferAttribute(new Uint32Array(this.mIndexArray), 1));
          geometry.setAttribute("position", new THREE.BufferAttribute(this.mVertexBuffer, 3));
          if (this.mNormalBuffer && this.mNormalBuffer.length > 0) {
            geometry.setAttribute("normal", new THREE.BufferAttribute(this.mNormalBuffer, 3));
          }
          if (this.mColorBuffer && this.mColorBuffer.length > 0) {
            geometry.setAttribute("color", new THREE.BufferAttribute(this.mColorBuffer, 4));
          }
          if (this.mTexCoordsBuffers[0] && this.mTexCoordsBuffers[0].length > 0) {
            geometry.setAttribute("uv", new THREE.BufferAttribute(new Float32Array(this.mTexCoordsBuffers[0]), 2));
          }
          if (this.mTexCoordsBuffers[1] && this.mTexCoordsBuffers[1].length > 0) {
            geometry.setAttribute("uv1", new THREE.BufferAttribute(new Float32Array(this.mTexCoordsBuffers[1]), 2));
          }
          if (this.mTangentBuffer && this.mTangentBuffer.length > 0) {
            geometry.setAttribute("tangents", new THREE.BufferAttribute(this.mTangentBuffer, 3));
          }
          if (this.mBitangentBuffer && this.mBitangentBuffer.length > 0) {
            geometry.setAttribute("bitangents", new THREE.BufferAttribute(this.mBitangentBuffer, 3));
          }
          if (this.mBones.length > 0) {
            var weights = [];
            var bones = [];
            for (let i = 0; i < this.mBones.length; i++) {
              for (let j = 0; j < this.mBones[i].mWeights.length; j++) {
                var weight = this.mBones[i].mWeights[j];
                if (weight) {
                  if (!weights[weight.mVertexId])
                    weights[weight.mVertexId] = [];
                  if (!bones[weight.mVertexId])
                    bones[weight.mVertexId] = [];
                  weights[weight.mVertexId].push(weight.mWeight);
                  bones[weight.mVertexId].push(parseInt(i));
                }
              }
            }
            for (let i in bones) {
              sortWeights(bones[i], weights[i]);
            }
            var _weights = [];
            var _bones = [];
            for (let i = 0; i < weights.length; i++) {
              for (let j = 0; j < 4; j++) {
                if (weights[i] && bones[i]) {
                  _weights.push(weights[i][j]);
                  _bones.push(bones[i][j]);
                } else {
                  _weights.push(0);
                  _bones.push(0);
                }
              }
            }
            geometry.setAttribute("skinWeight", new THREE.BufferAttribute(new Float32Array(_weights), BONESPERVERT));
            geometry.setAttribute("skinIndex", new THREE.BufferAttribute(new Float32Array(_bones), BONESPERVERT));
          }
          var mesh;
          if (this.mBones.length == 0)
            mesh = new THREE.Mesh(geometry, mat);
          if (this.mBones.length > 0) {
            mesh = new THREE.SkinnedMesh(geometry, mat);
            mesh.normalizeSkinWeights();
          }
          this.threeNode = mesh;
          return mesh;
        };
      }
    }
    class aiFace {
      constructor() {
        this.mNumIndices = 0;
        this.mIndices = [];
      }
    }
    class aiVector3D {
      constructor() {
        this.x = 0;
        this.y = 0;
        this.z = 0;
        this.toTHREE = function() {
          return new THREE.Vector3(this.x, this.y, this.z);
        };
      }
    }
    class aiColor3D {
      constructor() {
        this.r = 0;
        this.g = 0;
        this.b = 0;
        this.a = 0;
        this.toTHREE = function() {
          return new THREE.Color(this.r, this.g, this.b);
        };
      }
    }
    class aiQuaternion {
      constructor() {
        this.x = 0;
        this.y = 0;
        this.z = 0;
        this.w = 0;
        this.toTHREE = function() {
          return new THREE.Quaternion(this.x, this.y, this.z, this.w);
        };
      }
    }
    class aiVertexWeight {
      constructor() {
        this.mVertexId = 0;
        this.mWeight = 0;
      }
    }
    class aiString {
      constructor() {
        this.data = [];
        this.toString = function() {
          var str = "";
          this.data.forEach(function(i) {
            str += String.fromCharCode(i);
          });
          return str.replace(/[^\x20-\x7E]+/g, "");
        };
      }
    }
    class aiVectorKey {
      constructor() {
        this.mTime = 0;
        this.mValue = null;
      }
    }
    class aiQuatKey {
      constructor() {
        this.mTime = 0;
        this.mValue = null;
      }
    }
    class aiNode {
      constructor() {
        this.mName = "";
        this.mTransformation = [];
        this.mNumChildren = 0;
        this.mNumMeshes = 0;
        this.mMeshes = [];
        this.mChildren = [];
        this.toTHREE = function(scene) {
          if (this.threeNode)
            return this.threeNode;
          var o = new THREE.Object3D();
          o.name = this.mName;
          o.matrix = this.mTransformation.toTHREE();
          for (let i = 0; i < this.mChildren.length; i++) {
            o.add(this.mChildren[i].toTHREE(scene));
          }
          for (let i = 0; i < this.mMeshes.length; i++) {
            o.add(scene.mMeshes[this.mMeshes[i]].toTHREE(scene));
          }
          this.threeNode = o;
          o.matrix.decompose(o.position, o.quaternion, o.scale);
          return o;
        };
      }
    }
    class aiBone {
      constructor() {
        this.mName = "";
        this.mNumWeights = 0;
        this.mOffsetMatrix = 0;
      }
    }
    class aiMaterialProperty {
      constructor() {
        this.mKey = "";
        this.mSemantic = 0;
        this.mIndex = 0;
        this.mData = [];
        this.mDataLength = 0;
        this.mType = 0;
        this.dataAsColor = function() {
          var array = new Uint8Array(this.mData).buffer;
          var reader = new DataView(array);
          var r = reader.getFloat32(0, true);
          var g = reader.getFloat32(4, true);
          var b = reader.getFloat32(8, true);
          return new THREE.Color(r, g, b);
        };
        this.dataAsFloat = function() {
          var array = new Uint8Array(this.mData).buffer;
          var reader = new DataView(array);
          var r = reader.getFloat32(0, true);
          return r;
        };
        this.dataAsBool = function() {
          var array = new Uint8Array(this.mData).buffer;
          var reader = new DataView(array);
          var r = reader.getFloat32(0, true);
          return !!r;
        };
        this.dataAsString = function() {
          var s = new aiString();
          s.data = this.mData;
          return s.toString();
        };
        this.dataAsMap = function() {
          var s = new aiString();
          s.data = this.mData;
          var path2 = s.toString();
          path2 = path2.replace(/\\/g, "/");
          if (path2.indexOf("/") != -1) {
            path2 = path2.substr(path2.lastIndexOf("/") + 1);
          }
          return textureLoader.load(path2);
        };
      }
    }
    var namePropMapping = {
      "?mat.name": "name",
      "$mat.shadingm": "shading",
      "$mat.twosided": "twoSided",
      "$mat.wireframe": "wireframe",
      "$clr.ambient": "ambient",
      "$clr.diffuse": "color",
      "$clr.specular": "specular",
      "$clr.emissive": "emissive",
      "$clr.transparent": "transparent",
      "$clr.reflective": "reflect",
      "$mat.shininess": "shininess",
      "$mat.reflectivity": "reflectivity",
      "$mat.refracti": "refraction",
      "$tex.file": "map"
    };
    var nameTypeMapping = {
      "?mat.name": "string",
      "$mat.shadingm": "bool",
      "$mat.twosided": "bool",
      "$mat.wireframe": "bool",
      "$clr.ambient": "color",
      "$clr.diffuse": "color",
      "$clr.specular": "color",
      "$clr.emissive": "color",
      "$clr.transparent": "color",
      "$clr.reflective": "color",
      "$mat.shininess": "float",
      "$mat.reflectivity": "float",
      "$mat.refracti": "float",
      "$tex.file": "map"
    };
    class aiMaterial {
      constructor() {
        this.mNumAllocated = 0;
        this.mNumProperties = 0;
        this.mProperties = [];
        this.toTHREE = function() {
          var mat = new THREE.MeshPhongMaterial();
          for (let i = 0; i < this.mProperties.length; i++) {
            if (nameTypeMapping[this.mProperties[i].mKey] == "float") {
              mat[namePropMapping[this.mProperties[i].mKey]] = this.mProperties[i].dataAsFloat();
            }
            if (nameTypeMapping[this.mProperties[i].mKey] == "color") {
              mat[namePropMapping[this.mProperties[i].mKey]] = this.mProperties[i].dataAsColor();
            }
            if (nameTypeMapping[this.mProperties[i].mKey] == "bool") {
              mat[namePropMapping[this.mProperties[i].mKey]] = this.mProperties[i].dataAsBool();
            }
            if (nameTypeMapping[this.mProperties[i].mKey] == "string") {
              mat[namePropMapping[this.mProperties[i].mKey]] = this.mProperties[i].dataAsString();
            }
            if (nameTypeMapping[this.mProperties[i].mKey] == "map") {
              var prop = this.mProperties[i];
              if (prop.mSemantic == aiTextureType_DIFFUSE)
                mat.map = this.mProperties[i].dataAsMap();
              if (prop.mSemantic == aiTextureType_NORMALS)
                mat.normalMap = this.mProperties[i].dataAsMap();
              if (prop.mSemantic == aiTextureType_LIGHTMAP)
                mat.lightMap = this.mProperties[i].dataAsMap();
              if (prop.mSemantic == aiTextureType_OPACITY)
                mat.alphaMap = this.mProperties[i].dataAsMap();
            }
          }
          mat.ambient.r = 0.53;
          mat.ambient.g = 0.53;
          mat.ambient.b = 0.53;
          mat.color.r = 1;
          mat.color.g = 1;
          mat.color.b = 1;
          return mat;
        };
      }
    }
    function veclerp(v1, v2, l) {
      var v = new THREE.Vector3();
      var lm1 = 1 - l;
      v.x = v1.x * l + v2.x * lm1;
      v.y = v1.y * l + v2.y * lm1;
      v.z = v1.z * l + v2.z * lm1;
      return v;
    }
    function quatlerp(q1, q2, l) {
      return q1.clone().slerp(q2, 1 - l);
    }
    function sampleTrack(keys, time, lne, lerp) {
      if (keys.length == 1)
        return keys[0].mValue.toTHREE();
      var dist = Infinity;
      var key = null;
      var nextKey = null;
      for (let i = 0; i < keys.length; i++) {
        var timeDist = Math.abs(keys[i].mTime - time);
        if (timeDist < dist && keys[i].mTime <= time) {
          dist = timeDist;
          key = keys[i];
          nextKey = keys[i + 1];
        }
      }
      if (!key) {
        return null;
      } else if (nextKey) {
        var dT = nextKey.mTime - key.mTime;
        var T = key.mTime - time;
        var l = T / dT;
        return lerp(key.mValue.toTHREE(), nextKey.mValue.toTHREE(), l);
      } else {
        nextKey = keys[0].clone();
        nextKey.mTime += lne;
        var dT = nextKey.mTime - key.mTime;
        var T = key.mTime - time;
        var l = T / dT;
        return lerp(key.mValue.toTHREE(), nextKey.mValue.toTHREE(), l);
      }
    }
    class aiNodeAnim {
      constructor() {
        this.mNodeName = "";
        this.mNumPositionKeys = 0;
        this.mNumRotationKeys = 0;
        this.mNumScalingKeys = 0;
        this.mPositionKeys = [];
        this.mRotationKeys = [];
        this.mScalingKeys = [];
        this.mPreState = "";
        this.mPostState = "";
        this.init = function(tps) {
          if (!tps)
            tps = 1;
          function t(t2) {
            t2.mTime /= tps;
          }
          this.mPositionKeys.forEach(t);
          this.mRotationKeys.forEach(t);
          this.mScalingKeys.forEach(t);
        };
        this.sortKeys = function() {
          function comp(a, b) {
            return a.mTime - b.mTime;
          }
          this.mPositionKeys.sort(comp);
          this.mRotationKeys.sort(comp);
          this.mScalingKeys.sort(comp);
        };
        this.getLength = function() {
          return Math.max(
            Math.max.apply(
              null,
              this.mPositionKeys.map(function(a) {
                return a.mTime;
              })
            ),
            Math.max.apply(
              null,
              this.mRotationKeys.map(function(a) {
                return a.mTime;
              })
            ),
            Math.max.apply(
              null,
              this.mScalingKeys.map(function(a) {
                return a.mTime;
              })
            )
          );
        };
        this.toTHREE = function(o) {
          this.sortKeys();
          var length = this.getLength();
          var track = new Virtulous.KeyFrameTrack();
          for (let i = 0; i < length; i += 0.05) {
            var matrix = new THREE.Matrix4();
            var time = i;
            var pos = sampleTrack(this.mPositionKeys, time, length, veclerp);
            var scale = sampleTrack(this.mScalingKeys, time, length, veclerp);
            var rotation = sampleTrack(this.mRotationKeys, time, length, quatlerp);
            matrix.compose(pos, rotation, scale);
            var key = new Virtulous.KeyFrame(time, matrix);
            track.addKey(key);
          }
          track.target = o.findNode(this.mNodeName).toTHREE();
          var tracks = [track];
          if (o.nodeToBoneMap[this.mNodeName]) {
            for (let i = 0; i < o.nodeToBoneMap[this.mNodeName].length; i++) {
              var t2 = track.clone();
              t2.target = o.nodeToBoneMap[this.mNodeName][i];
              tracks.push(t2);
            }
          }
          return tracks;
        };
      }
    }
    class aiAnimation {
      constructor() {
        this.mName = "";
        this.mDuration = 0;
        this.mTicksPerSecond = 0;
        this.mNumChannels = 0;
        this.mChannels = [];
        this.toTHREE = function(root) {
          var animationHandle = new Virtulous.Animation();
          for (let i in this.mChannels) {
            this.mChannels[i].init(this.mTicksPerSecond);
            var tracks = this.mChannels[i].toTHREE(root);
            for (let j in tracks) {
              tracks[j].init();
              animationHandle.addTrack(tracks[j]);
            }
          }
          animationHandle.length = Math.max.apply(
            null,
            animationHandle.tracks.map(function(e) {
              return e.length;
            })
          );
          return animationHandle;
        };
      }
    }
    class aiTexture {
      constructor() {
        this.mWidth = 0;
        this.mHeight = 0;
        this.texAchFormatHint = [];
        this.pcData = [];
      }
    }
    class aiLight {
      constructor() {
        this.mName = "";
        this.mType = 0;
        this.mAttenuationConstant = 0;
        this.mAttenuationLinear = 0;
        this.mAttenuationQuadratic = 0;
        this.mAngleInnerCone = 0;
        this.mAngleOuterCone = 0;
        this.mColorDiffuse = null;
        this.mColorSpecular = null;
        this.mColorAmbient = null;
      }
    }
    class aiCamera {
      constructor() {
        this.mName = "";
        this.mPosition = null;
        this.mLookAt = null;
        this.mUp = null;
        this.mHorizontalFOV = 0;
        this.mClipPlaneNear = 0;
        this.mClipPlaneFar = 0;
        this.mAspect = 0;
      }
    }
    class aiScene {
      constructor() {
        this.versionMajor = 0;
        this.versionMinor = 0;
        this.versionRevision = 0;
        this.compileFlags = 0;
        this.mFlags = 0;
        this.mNumMeshes = 0;
        this.mNumMaterials = 0;
        this.mNumAnimations = 0;
        this.mNumTextures = 0;
        this.mNumLights = 0;
        this.mNumCameras = 0;
        this.mRootNode = null;
        this.mMeshes = [];
        this.mMaterials = [];
        this.mAnimations = [];
        this.mLights = [];
        this.mCameras = [];
        this.nodeToBoneMap = {};
        this.findNode = function(name, root) {
          if (!root) {
            root = this.mRootNode;
          }
          if (root.mName == name) {
            return root;
          }
          for (let i = 0; i < root.mChildren.length; i++) {
            var ret = this.findNode(name, root.mChildren[i]);
            if (ret)
              return ret;
          }
          return null;
        };
        this.toTHREE = function() {
          this.nodeCount = 0;
          markBones(this);
          var o = this.mRootNode.toTHREE(this);
          for (let i in this.mMeshes)
            this.mMeshes[i].hookupSkeletons(this);
          if (this.mAnimations.length > 0) {
            var a = this.mAnimations[0].toTHREE(this);
          }
          return { object: o, animation: a };
        };
      }
    }
    class aiMatrix4 {
      constructor() {
        this.elements = [[], [], [], []];
        this.toTHREE = function() {
          var m = new THREE.Matrix4();
          for (let i = 0; i < 4; ++i) {
            for (let i2 = 0; i2 < 4; ++i2) {
              m.elements[i * 4 + i2] = this.elements[i2][i];
            }
          }
          return m;
        };
      }
    }
    var littleEndian = true;
    function readFloat(dataview) {
      var val = dataview.getFloat32(dataview.readOffset, littleEndian);
      dataview.readOffset += 4;
      return val;
    }
    function Read_double(dataview) {
      var val = dataview.getFloat64(dataview.readOffset, littleEndian);
      dataview.readOffset += 8;
      return val;
    }
    function Read_uint8_t(dataview) {
      var val = dataview.getUint8(dataview.readOffset);
      dataview.readOffset += 1;
      return val;
    }
    function Read_uint16_t(dataview) {
      var val = dataview.getUint16(dataview.readOffset, littleEndian);
      dataview.readOffset += 2;
      return val;
    }
    function Read_unsigned_int(dataview) {
      var val = dataview.getUint32(dataview.readOffset, littleEndian);
      dataview.readOffset += 4;
      return val;
    }
    function Read_uint32_t(dataview) {
      var val = dataview.getUint32(dataview.readOffset, littleEndian);
      dataview.readOffset += 4;
      return val;
    }
    function Read_aiVector3D(stream) {
      var v = new aiVector3D();
      v.x = readFloat(stream);
      v.y = readFloat(stream);
      v.z = readFloat(stream);
      return v;
    }
    function Read_aiColor3D(stream) {
      var c = new aiColor3D();
      c.r = readFloat(stream);
      c.g = readFloat(stream);
      c.b = readFloat(stream);
      return c;
    }
    function Read_aiQuaternion(stream) {
      var v = new aiQuaternion();
      v.w = readFloat(stream);
      v.x = readFloat(stream);
      v.y = readFloat(stream);
      v.z = readFloat(stream);
      return v;
    }
    function Read_aiString(stream) {
      var s = new aiString();
      var stringlengthbytes = Read_unsigned_int(stream);
      stream.ReadBytes(s.data, 1, stringlengthbytes);
      return s.toString();
    }
    function Read_aiVertexWeight(stream) {
      var w = new aiVertexWeight();
      w.mVertexId = Read_unsigned_int(stream);
      w.mWeight = readFloat(stream);
      return w;
    }
    function Read_aiMatrix4x4(stream) {
      var m = new aiMatrix4();
      for (let i = 0; i < 4; ++i) {
        for (let i2 = 0; i2 < 4; ++i2) {
          m.elements[i][i2] = readFloat(stream);
        }
      }
      return m;
    }
    function Read_aiVectorKey(stream) {
      var v = new aiVectorKey();
      v.mTime = Read_double(stream);
      v.mValue = Read_aiVector3D(stream);
      return v;
    }
    function Read_aiQuatKey(stream) {
      var v = new aiQuatKey();
      v.mTime = Read_double(stream);
      v.mValue = Read_aiQuaternion(stream);
      return v;
    }
    function ReadArray_aiVertexWeight(stream, data, size) {
      for (let i = 0; i < size; i++)
        data[i] = Read_aiVertexWeight(stream);
    }
    function ReadArray_aiVectorKey(stream, data, size) {
      for (let i = 0; i < size; i++)
        data[i] = Read_aiVectorKey(stream);
    }
    function ReadArray_aiQuatKey(stream, data, size) {
      for (let i = 0; i < size; i++)
        data[i] = Read_aiQuatKey(stream);
    }
    function ReadBounds(stream, T, n) {
      return stream.Seek(sizeof(T) * n, aiOrigin_CUR);
    }
    function ai_assert(bool) {
      if (!bool)
        throw "asset failed";
    }
    function ReadBinaryNode(stream, parent, depth) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AINODE);
      Read_uint32_t(stream);
      var node = new aiNode();
      node.mParent = parent;
      node.mDepth = depth;
      node.mName = Read_aiString(stream);
      node.mTransformation = Read_aiMatrix4x4(stream);
      node.mNumChildren = Read_unsigned_int(stream);
      node.mNumMeshes = Read_unsigned_int(stream);
      if (node.mNumMeshes) {
        node.mMeshes = [];
        for (let i = 0; i < node.mNumMeshes; ++i) {
          node.mMeshes[i] = Read_unsigned_int(stream);
        }
      }
      if (node.mNumChildren) {
        node.mChildren = [];
        for (let i = 0; i < node.mNumChildren; ++i) {
          var node2 = ReadBinaryNode(stream, node, depth++);
          node.mChildren[i] = node2;
        }
      }
      return node;
    }
    function ReadBinaryBone(stream, b) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AIBONE);
      Read_uint32_t(stream);
      b.mName = Read_aiString(stream);
      b.mNumWeights = Read_unsigned_int(stream);
      b.mOffsetMatrix = Read_aiMatrix4x4(stream);
      if (shortened) {
        ReadBounds(stream, b.mWeights, b.mNumWeights);
      } else {
        b.mWeights = [];
        ReadArray_aiVertexWeight(stream, b.mWeights, b.mNumWeights);
      }
      return b;
    }
    function ReadBinaryMesh(stream, mesh) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AIMESH);
      Read_uint32_t(stream);
      mesh.mPrimitiveTypes = Read_unsigned_int(stream);
      mesh.mNumVertices = Read_unsigned_int(stream);
      mesh.mNumFaces = Read_unsigned_int(stream);
      mesh.mNumBones = Read_unsigned_int(stream);
      mesh.mMaterialIndex = Read_unsigned_int(stream);
      mesh.mNumUVComponents = [];
      var c = Read_unsigned_int(stream);
      if (c & ASSBIN_MESH_HAS_POSITIONS) {
        if (shortened) {
          ReadBounds(stream, mesh.mVertices, mesh.mNumVertices);
        } else {
          mesh.mVertices = [];
          mesh.mVertexBuffer = stream.subArray32(stream.readOffset, stream.readOffset + mesh.mNumVertices * 3 * 4);
          stream.Seek(mesh.mNumVertices * 3 * 4, aiOrigin_CUR);
        }
      }
      if (c & ASSBIN_MESH_HAS_NORMALS) {
        if (shortened) {
          ReadBounds(stream, mesh.mNormals, mesh.mNumVertices);
        } else {
          mesh.mNormals = [];
          mesh.mNormalBuffer = stream.subArray32(stream.readOffset, stream.readOffset + mesh.mNumVertices * 3 * 4);
          stream.Seek(mesh.mNumVertices * 3 * 4, aiOrigin_CUR);
        }
      }
      if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS) {
        if (shortened) {
          ReadBounds(stream, mesh.mTangents, mesh.mNumVertices);
          ReadBounds(stream, mesh.mBitangents, mesh.mNumVertices);
        } else {
          mesh.mTangents = [];
          mesh.mTangentBuffer = stream.subArray32(stream.readOffset, stream.readOffset + mesh.mNumVertices * 3 * 4);
          stream.Seek(mesh.mNumVertices * 3 * 4, aiOrigin_CUR);
          mesh.mBitangents = [];
          mesh.mBitangentBuffer = stream.subArray32(stream.readOffset, stream.readOffset + mesh.mNumVertices * 3 * 4);
          stream.Seek(mesh.mNumVertices * 3 * 4, aiOrigin_CUR);
        }
      }
      for (let n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS; ++n) {
        if (!(c & ASSBIN_MESH_HAS_COLOR(n)))
          break;
        if (shortened) {
          ReadBounds(stream, mesh.mColors[n], mesh.mNumVertices);
        } else {
          mesh.mColors[n] = [];
          mesh.mColorBuffer = stream.subArray32(stream.readOffset, stream.readOffset + mesh.mNumVertices * 4 * 4);
          stream.Seek(mesh.mNumVertices * 4 * 4, aiOrigin_CUR);
        }
      }
      mesh.mTexCoordsBuffers = [];
      for (let n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++n) {
        if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n)))
          break;
        mesh.mNumUVComponents[n] = Read_unsigned_int(stream);
        if (shortened) {
          ReadBounds(stream, mesh.mTextureCoords[n], mesh.mNumVertices);
        } else {
          mesh.mTextureCoords[n] = [];
          mesh.mTexCoordsBuffers[n] = [];
          for (let uv = 0; uv < mesh.mNumVertices; uv++) {
            mesh.mTexCoordsBuffers[n].push(readFloat(stream));
            mesh.mTexCoordsBuffers[n].push(readFloat(stream));
            readFloat(stream);
          }
        }
      }
      if (shortened) {
        Read_unsigned_int(stream);
      } else {
        mesh.mFaces = [];
        mesh.mIndexArray = [];
        for (let i = 0; i < mesh.mNumFaces; ++i) {
          var f = mesh.mFaces[i] = new aiFace();
          f.mNumIndices = Read_uint16_t(stream);
          f.mIndices = [];
          for (let a = 0; a < f.mNumIndices; ++a) {
            if (mesh.mNumVertices < 1 << 16) {
              f.mIndices[a] = Read_uint16_t(stream);
            } else {
              f.mIndices[a] = Read_unsigned_int(stream);
            }
          }
          if (f.mNumIndices === 3) {
            mesh.mIndexArray.push(f.mIndices[0]);
            mesh.mIndexArray.push(f.mIndices[1]);
            mesh.mIndexArray.push(f.mIndices[2]);
          } else if (f.mNumIndices === 4) {
            mesh.mIndexArray.push(f.mIndices[0]);
            mesh.mIndexArray.push(f.mIndices[1]);
            mesh.mIndexArray.push(f.mIndices[2]);
            mesh.mIndexArray.push(f.mIndices[2]);
            mesh.mIndexArray.push(f.mIndices[3]);
            mesh.mIndexArray.push(f.mIndices[0]);
          } else {
            throw new Error("Sorry, can't currently triangulate polys. Use the triangulate preprocessor in Assimp.");
          }
        }
      }
      if (mesh.mNumBones) {
        mesh.mBones = [];
        for (let a = 0; a < mesh.mNumBones; ++a) {
          mesh.mBones[a] = new aiBone();
          ReadBinaryBone(stream, mesh.mBones[a]);
        }
      }
    }
    function ReadBinaryMaterialProperty(stream, prop) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY);
      Read_uint32_t(stream);
      prop.mKey = Read_aiString(stream);
      prop.mSemantic = Read_unsigned_int(stream);
      prop.mIndex = Read_unsigned_int(stream);
      prop.mDataLength = Read_unsigned_int(stream);
      prop.mType = Read_unsigned_int(stream);
      prop.mData = [];
      stream.ReadBytes(prop.mData, 1, prop.mDataLength);
    }
    function ReadBinaryMaterial(stream, mat) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL);
      Read_uint32_t(stream);
      mat.mNumAllocated = mat.mNumProperties = Read_unsigned_int(stream);
      if (mat.mNumProperties) {
        if (mat.mProperties) {
          delete mat.mProperties;
        }
        mat.mProperties = [];
        for (let i = 0; i < mat.mNumProperties; ++i) {
          mat.mProperties[i] = new aiMaterialProperty();
          ReadBinaryMaterialProperty(stream, mat.mProperties[i]);
        }
      }
    }
    function ReadBinaryNodeAnim(stream, nd) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM);
      Read_uint32_t(stream);
      nd.mNodeName = Read_aiString(stream);
      nd.mNumPositionKeys = Read_unsigned_int(stream);
      nd.mNumRotationKeys = Read_unsigned_int(stream);
      nd.mNumScalingKeys = Read_unsigned_int(stream);
      nd.mPreState = Read_unsigned_int(stream);
      nd.mPostState = Read_unsigned_int(stream);
      if (nd.mNumPositionKeys) {
        if (shortened) {
          ReadBounds(stream, nd.mPositionKeys, nd.mNumPositionKeys);
        } else {
          nd.mPositionKeys = [];
          ReadArray_aiVectorKey(stream, nd.mPositionKeys, nd.mNumPositionKeys);
        }
      }
      if (nd.mNumRotationKeys) {
        if (shortened) {
          ReadBounds(stream, nd.mRotationKeys, nd.mNumRotationKeys);
        } else {
          nd.mRotationKeys = [];
          ReadArray_aiQuatKey(stream, nd.mRotationKeys, nd.mNumRotationKeys);
        }
      }
      if (nd.mNumScalingKeys) {
        if (shortened) {
          ReadBounds(stream, nd.mScalingKeys, nd.mNumScalingKeys);
        } else {
          nd.mScalingKeys = [];
          ReadArray_aiVectorKey(stream, nd.mScalingKeys, nd.mNumScalingKeys);
        }
      }
    }
    function ReadBinaryAnim(stream, anim) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION);
      Read_uint32_t(stream);
      anim.mName = Read_aiString(stream);
      anim.mDuration = Read_double(stream);
      anim.mTicksPerSecond = Read_double(stream);
      anim.mNumChannels = Read_unsigned_int(stream);
      if (anim.mNumChannels) {
        anim.mChannels = [];
        for (let a = 0; a < anim.mNumChannels; ++a) {
          anim.mChannels[a] = new aiNodeAnim();
          ReadBinaryNodeAnim(stream, anim.mChannels[a]);
        }
      }
    }
    function ReadBinaryTexture(stream, tex) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE);
      Read_uint32_t(stream);
      tex.mWidth = Read_unsigned_int(stream);
      tex.mHeight = Read_unsigned_int(stream);
      stream.ReadBytes(tex.achFormatHint, 1, 4);
      if (!shortened) {
        if (!tex.mHeight) {
          tex.pcData = [];
          stream.ReadBytes(tex.pcData, 1, tex.mWidth);
        } else {
          tex.pcData = [];
          stream.ReadBytes(tex.pcData, 1, tex.mWidth * tex.mHeight * 4);
        }
      }
    }
    function ReadBinaryLight(stream, l) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT);
      Read_uint32_t(stream);
      l.mName = Read_aiString(stream);
      l.mType = Read_unsigned_int(stream);
      if (l.mType != aiLightSource_DIRECTIONAL) {
        l.mAttenuationConstant = readFloat(stream);
        l.mAttenuationLinear = readFloat(stream);
        l.mAttenuationQuadratic = readFloat(stream);
      }
      l.mColorDiffuse = Read_aiColor3D(stream);
      l.mColorSpecular = Read_aiColor3D(stream);
      l.mColorAmbient = Read_aiColor3D(stream);
      if (l.mType == aiLightSource_SPOT) {
        l.mAngleInnerCone = readFloat(stream);
        l.mAngleOuterCone = readFloat(stream);
      }
    }
    function ReadBinaryCamera(stream, cam) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA);
      Read_uint32_t(stream);
      cam.mName = Read_aiString(stream);
      cam.mPosition = Read_aiVector3D(stream);
      cam.mLookAt = Read_aiVector3D(stream);
      cam.mUp = Read_aiVector3D(stream);
      cam.mHorizontalFOV = readFloat(stream);
      cam.mClipPlaneNear = readFloat(stream);
      cam.mClipPlaneFar = readFloat(stream);
      cam.mAspect = readFloat(stream);
    }
    function ReadBinaryScene(stream, scene) {
      var chunkID = Read_uint32_t(stream);
      ai_assert(chunkID == ASSBIN_CHUNK_AISCENE);
      Read_uint32_t(stream);
      scene.mFlags = Read_unsigned_int(stream);
      scene.mNumMeshes = Read_unsigned_int(stream);
      scene.mNumMaterials = Read_unsigned_int(stream);
      scene.mNumAnimations = Read_unsigned_int(stream);
      scene.mNumTextures = Read_unsigned_int(stream);
      scene.mNumLights = Read_unsigned_int(stream);
      scene.mNumCameras = Read_unsigned_int(stream);
      scene.mRootNode = new aiNode();
      scene.mRootNode = ReadBinaryNode(stream, null, 0);
      if (scene.mNumMeshes) {
        scene.mMeshes = [];
        for (let i = 0; i < scene.mNumMeshes; ++i) {
          scene.mMeshes[i] = new aiMesh();
          ReadBinaryMesh(stream, scene.mMeshes[i]);
        }
      }
      if (scene.mNumMaterials) {
        scene.mMaterials = [];
        for (let i = 0; i < scene.mNumMaterials; ++i) {
          scene.mMaterials[i] = new aiMaterial();
          ReadBinaryMaterial(stream, scene.mMaterials[i]);
        }
      }
      if (scene.mNumAnimations) {
        scene.mAnimations = [];
        for (let i = 0; i < scene.mNumAnimations; ++i) {
          scene.mAnimations[i] = new aiAnimation();
          ReadBinaryAnim(stream, scene.mAnimations[i]);
        }
      }
      if (scene.mNumTextures) {
        scene.mTextures = [];
        for (let i = 0; i < scene.mNumTextures; ++i) {
          scene.mTextures[i] = new aiTexture();
          ReadBinaryTexture(stream, scene.mTextures[i]);
        }
      }
      if (scene.mNumLights) {
        scene.mLights = [];
        for (let i = 0; i < scene.mNumLights; ++i) {
          scene.mLights[i] = new aiLight();
          ReadBinaryLight(stream, scene.mLights[i]);
        }
      }
      if (scene.mNumCameras) {
        scene.mCameras = [];
        for (let i = 0; i < scene.mNumCameras; ++i) {
          scene.mCameras[i] = new aiCamera();
          ReadBinaryCamera(stream, scene.mCameras[i]);
        }
      }
    }
    var aiOrigin_CUR = 0;
    var aiOrigin_BEG = 1;
    function extendStream(stream) {
      stream.readOffset = 0;
      stream.Seek = function(off, ori) {
        if (ori == aiOrigin_CUR) {
          stream.readOffset += off;
        }
        if (ori == aiOrigin_BEG) {
          stream.readOffset = off;
        }
      };
      stream.ReadBytes = function(buff, size, n) {
        var bytes = size * n;
        for (let i = 0; i < bytes; i++)
          buff[i] = Read_uint8_t(this);
      };
      stream.subArray32 = function(start, end) {
        var buff = this.buffer;
        var newbuff = buff.slice(start, end);
        return new Float32Array(newbuff);
      };
      stream.subArrayUint16 = function(start, end) {
        var buff = this.buffer;
        var newbuff = buff.slice(start, end);
        return new Uint16Array(newbuff);
      };
      stream.subArrayUint8 = function(start, end) {
        var buff = this.buffer;
        var newbuff = buff.slice(start, end);
        return new Uint8Array(newbuff);
      };
      stream.subArrayUint32 = function(start, end) {
        var buff = this.buffer;
        var newbuff = buff.slice(start, end);
        return new Uint32Array(newbuff);
      };
    }
    var shortened, compressed;
    function InternReadFile(pFiledata) {
      var pScene = new aiScene();
      var stream = new DataView(pFiledata);
      extendStream(stream);
      stream.Seek(44, aiOrigin_CUR);
      pScene.versionMajor = Read_unsigned_int(stream);
      pScene.versionMinor = Read_unsigned_int(stream);
      pScene.versionRevision = Read_unsigned_int(stream);
      pScene.compileFlags = Read_unsigned_int(stream);
      shortened = Read_uint16_t(stream) > 0;
      compressed = Read_uint16_t(stream) > 0;
      if (shortened)
        throw "Shortened binaries are not supported!";
      stream.Seek(256, aiOrigin_CUR);
      stream.Seek(128, aiOrigin_CUR);
      stream.Seek(64, aiOrigin_CUR);
      if (compressed) {
        var uncompressedSize = Read_uint32_t(stream);
        var compressedSize = stream.FileSize() - stream.Tell();
        var compressedData = [];
        stream.Read(compressedData, 1, compressedSize);
        var uncompressedData = [];
        uncompress(uncompressedData, uncompressedSize, compressedData, compressedSize);
        var buff = new ArrayBuffer(uncompressedData);
        ReadBinaryScene(buff, pScene);
      } else {
        ReadBinaryScene(stream, pScene);
      }
      return pScene.toTHREE();
    }
    return InternReadFile(buffer);
  }
}
exports.AssimpLoader = AssimpLoader;
//# sourceMappingURL=AssimpLoader.cjs.map