| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- THREE.OptMeshLoader = (function ()
- {
- function OptMeshLoader(manager)
- {
- this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
- this.materials = Promise.resolve(null);
- }
- OptMeshLoader.prototype =
- {
- constructor: OptMeshLoader,
- load: function (url, onLoad, onProgress, onError)
- {
- var scope = this;
- var loader = new THREE.FileLoader(scope.manager);
- loader.setResponseType('arraybuffer');
- loader.setPath(this.path);
- loader.load(url, function (data)
- {
- scope.decoder.ready.then(function ()
- {
- scope.materials.then(function (materials)
- {
- onLoad(scope.parse(data, materials));
- });
- });
- }, onProgress, onError);
- },
- setDecoder: function (value)
- {
- this.decoder = value;
- return this;
- },
- setPath: function (value)
- {
- this.path = value;
- return this;
- },
- setMaterials: function (materials)
- {
- this.materials = Promise.resolve(materials);
- return this;
- },
- setMaterialLib: function (lib)
- {
- var scope = this;
- this.materials = new Promise(function (resolve, reject)
- {
- var loader = new THREE.MTLLoader();
- loader.setPath(scope.path);
- loader.load(lib, function (materials) { materials.preload(); resolve(materials); }, null, reject);
- });
- return this;
- },
- parse: function (data, materials)
- {
- console.time('OptMeshLoader');
- var array = new Uint8Array(data);
- var view = new DataView(data);
- var endian = true;
- var magic = view.getUint32(0, endian);
- var objectCount = view.getUint32(4, endian);
- var vertexCount = view.getUint32(8, endian);
- var indexCount = view.getUint32(12, endian);
- var vertexDataSize = view.getUint32(16, endian);
- var indexDataSize = view.getUint32(20, endian);
- var posOffsetX = view.getFloat32(24, endian);
- var posOffsetY = view.getFloat32(28, endian);
- var posOffsetZ = view.getFloat32(32, endian);
- var posScale = view.getFloat32(36, endian);
- var uvOffsetX = view.getFloat32(40, endian);
- var uvOffsetY = view.getFloat32(44, endian);
- var uvScaleX = view.getFloat32(48, endian);
- var uvScaleY = view.getFloat32(52, endian);
- if (magic != 0x4D54504F)
- throw new Error("Malformed mesh file: unrecognized header");
- var objectOffset = 64;
- var objectDataOffset = objectOffset + 16 * objectCount;
- var objectDataSize = 0;
- for (var i = 0; i < objectCount; ++i)
- objectDataSize += view.getUint32(objectOffset + 16 * i + 8, endian);
- var vertexDataOffset = objectDataOffset + objectDataSize;
- var indexDataOffset = vertexDataOffset + vertexDataSize;
- var endOffset = indexDataOffset + indexDataSize;
- if (endOffset != data.byteLength)
- throw new Error("Malformed mesh file: unexpected input size");
- var vertexSize = 16;
- var indexSize = 4;
- var vertexBuffer = new ArrayBuffer(vertexCount * vertexSize);
- var vertexBufferU8 = new Uint8Array(vertexBuffer);
- this.decoder.decodeVertexBuffer(vertexBufferU8, vertexCount, vertexSize, array.subarray(vertexDataOffset, vertexDataOffset + vertexDataSize));
- var indexBuffer = new ArrayBuffer(indexCount * indexSize);
- var indexBufferU8 = new Uint8Array(indexBuffer);
- this.decoder.decodeIndexBuffer(indexBufferU8, indexCount, indexSize, array.subarray(indexDataOffset, indexDataOffset + indexDataSize));
- var geometry = new THREE.BufferGeometry();
- geometry.addAttribute('position', new THREE.InterleavedBufferAttribute(new THREE.InterleavedBuffer(new Uint16Array(vertexBuffer), 8), 3, 0, false));
- geometry.addAttribute('normal', new THREE.InterleavedBufferAttribute(new THREE.InterleavedBuffer(new Int8Array(vertexBuffer), 16), 3, 8, true));
- geometry.addAttribute('uv', new THREE.InterleavedBufferAttribute(new THREE.InterleavedBuffer(new Uint16Array(vertexBuffer), 8), 2, 6, false));
- geometry.setIndex(new THREE.BufferAttribute(new Uint32Array(indexBuffer), 1, false));
- var objectDataOffsetAcc = objectDataOffset;
- var objectMaterials = [];
- var objectMaterialsLookup = {};
- for (var i = 0; i < objectCount; i++)
- {
- var objectIndexOffset = view.getUint32(objectOffset + 16 * i + 0, endian);
- var objectIndexCount = view.getUint32(objectOffset + 16 * i + 4, endian);
- var objectMaterialLength = view.getUint32(objectOffset + 16 * i + 8, endian);
- var objectMaterialName = String.fromCharCode.apply(null, array.subarray(objectDataOffsetAcc, objectDataOffsetAcc + objectMaterialLength));
- var objectMaterialIndex = objectMaterialsLookup[objectMaterialName];
- if (objectMaterialIndex == undefined)
- {
- var objectMaterial = null;
- if (materials !== null)
- objectMaterial = materials.create(objectMaterialName);
- if (!objectMaterial)
- objectMaterial = new THREE.MeshPhongMaterial();
- if (objectMaterial.map)
- {
- objectMaterial.map.offset.set(uvOffsetX, uvOffsetY);
- objectMaterial.map.repeat.set(uvScaleX, uvScaleY);
- }
- objectMaterialIndex = objectMaterials.length;
- objectMaterialsLookup[objectMaterialName] = objectMaterialIndex;
- objectMaterials.push(objectMaterial);
- }
- geometry.addGroup(objectIndexOffset, objectIndexCount, objectMaterialIndex);
- objectDataOffsetAcc += objectMaterialLength;
- }
- var mesh = new THREE.Mesh(geometry, objectMaterials);
- mesh.position.set(posOffsetX, posOffsetY, posOffsetZ);
- mesh.scale.set(posScale, posScale, posScale);
- var container = new THREE.Group();
- container.add(mesh);
- console.timeEnd('OptMeshLoader');
- return container;
- }
- };
- return OptMeshLoader;
- })();
|