OptMeshLoader.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. THREE.OptMeshLoader = (function ()
  2. {
  3. function OptMeshLoader(manager)
  4. {
  5. this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
  6. this.materials = Promise.resolve(null);
  7. }
  8. OptMeshLoader.prototype =
  9. {
  10. constructor: OptMeshLoader,
  11. load: function (url, onLoad, onProgress, onError)
  12. {
  13. var scope = this;
  14. var loader = new THREE.FileLoader(scope.manager);
  15. loader.setResponseType('arraybuffer');
  16. loader.setPath(this.path);
  17. loader.load(url, function (data)
  18. {
  19. scope.decoder.ready.then(function ()
  20. {
  21. scope.materials.then(function (materials)
  22. {
  23. onLoad(scope.parse(data, materials));
  24. });
  25. });
  26. }, onProgress, onError);
  27. },
  28. setDecoder: function (value)
  29. {
  30. this.decoder = value;
  31. return this;
  32. },
  33. setPath: function (value)
  34. {
  35. this.path = value;
  36. return this;
  37. },
  38. setMaterials: function (materials)
  39. {
  40. this.materials = Promise.resolve(materials);
  41. return this;
  42. },
  43. setMaterialLib: function (lib)
  44. {
  45. var scope = this;
  46. this.materials = new Promise(function (resolve, reject)
  47. {
  48. var loader = new THREE.MTLLoader();
  49. loader.setPath(scope.path);
  50. loader.load(lib, function (materials) { materials.preload(); resolve(materials); }, null, reject);
  51. });
  52. return this;
  53. },
  54. parse: function (data, materials)
  55. {
  56. console.time('OptMeshLoader');
  57. var array = new Uint8Array(data);
  58. var view = new DataView(data);
  59. var endian = true;
  60. var magic = view.getUint32(0, endian);
  61. var objectCount = view.getUint32(4, endian);
  62. var vertexCount = view.getUint32(8, endian);
  63. var indexCount = view.getUint32(12, endian);
  64. var vertexDataSize = view.getUint32(16, endian);
  65. var indexDataSize = view.getUint32(20, endian);
  66. var posOffsetX = view.getFloat32(24, endian);
  67. var posOffsetY = view.getFloat32(28, endian);
  68. var posOffsetZ = view.getFloat32(32, endian);
  69. var posScale = view.getFloat32(36, endian);
  70. var uvOffsetX = view.getFloat32(40, endian);
  71. var uvOffsetY = view.getFloat32(44, endian);
  72. var uvScaleX = view.getFloat32(48, endian);
  73. var uvScaleY = view.getFloat32(52, endian);
  74. if (magic != 0x4D54504F)
  75. throw new Error("Malformed mesh file: unrecognized header");
  76. var objectOffset = 64;
  77. var objectDataOffset = objectOffset + 16 * objectCount;
  78. var objectDataSize = 0;
  79. for (var i = 0; i < objectCount; ++i)
  80. objectDataSize += view.getUint32(objectOffset + 16 * i + 8, endian);
  81. var vertexDataOffset = objectDataOffset + objectDataSize;
  82. var indexDataOffset = vertexDataOffset + vertexDataSize;
  83. var endOffset = indexDataOffset + indexDataSize;
  84. if (endOffset != data.byteLength)
  85. throw new Error("Malformed mesh file: unexpected input size");
  86. var vertexSize = 16;
  87. var indexSize = 4;
  88. var vertexBuffer = new ArrayBuffer(vertexCount * vertexSize);
  89. var vertexBufferU8 = new Uint8Array(vertexBuffer);
  90. this.decoder.decodeVertexBuffer(vertexBufferU8, vertexCount, vertexSize, array.subarray(vertexDataOffset, vertexDataOffset + vertexDataSize));
  91. var indexBuffer = new ArrayBuffer(indexCount * indexSize);
  92. var indexBufferU8 = new Uint8Array(indexBuffer);
  93. this.decoder.decodeIndexBuffer(indexBufferU8, indexCount, indexSize, array.subarray(indexDataOffset, indexDataOffset + indexDataSize));
  94. var geometry = new THREE.BufferGeometry();
  95. geometry.addAttribute('position', new THREE.InterleavedBufferAttribute(new THREE.InterleavedBuffer(new Uint16Array(vertexBuffer), 8), 3, 0, false));
  96. geometry.addAttribute('normal', new THREE.InterleavedBufferAttribute(new THREE.InterleavedBuffer(new Int8Array(vertexBuffer), 16), 3, 8, true));
  97. geometry.addAttribute('uv', new THREE.InterleavedBufferAttribute(new THREE.InterleavedBuffer(new Uint16Array(vertexBuffer), 8), 2, 6, false));
  98. geometry.setIndex(new THREE.BufferAttribute(new Uint32Array(indexBuffer), 1, false));
  99. var objectDataOffsetAcc = objectDataOffset;
  100. var objectMaterials = [];
  101. var objectMaterialsLookup = {};
  102. for (var i = 0; i < objectCount; i++)
  103. {
  104. var objectIndexOffset = view.getUint32(objectOffset + 16 * i + 0, endian);
  105. var objectIndexCount = view.getUint32(objectOffset + 16 * i + 4, endian);
  106. var objectMaterialLength = view.getUint32(objectOffset + 16 * i + 8, endian);
  107. var objectMaterialName = String.fromCharCode.apply(null, array.subarray(objectDataOffsetAcc, objectDataOffsetAcc + objectMaterialLength));
  108. var objectMaterialIndex = objectMaterialsLookup[objectMaterialName];
  109. if (objectMaterialIndex == undefined)
  110. {
  111. var objectMaterial = null;
  112. if (materials !== null)
  113. objectMaterial = materials.create(objectMaterialName);
  114. if (!objectMaterial)
  115. objectMaterial = new THREE.MeshPhongMaterial();
  116. if (objectMaterial.map)
  117. {
  118. objectMaterial.map.offset.set(uvOffsetX, uvOffsetY);
  119. objectMaterial.map.repeat.set(uvScaleX, uvScaleY);
  120. }
  121. objectMaterialIndex = objectMaterials.length;
  122. objectMaterialsLookup[objectMaterialName] = objectMaterialIndex;
  123. objectMaterials.push(objectMaterial);
  124. }
  125. geometry.addGroup(objectIndexOffset, objectIndexCount, objectMaterialIndex);
  126. objectDataOffsetAcc += objectMaterialLength;
  127. }
  128. var mesh = new THREE.Mesh(geometry, objectMaterials);
  129. mesh.position.set(posOffsetX, posOffsetY, posOffsetZ);
  130. mesh.scale.set(posScale, posScale, posScale);
  131. var container = new THREE.Group();
  132. container.add(mesh);
  133. console.timeEnd('OptMeshLoader');
  134. return container;
  135. }
  136. };
  137. return OptMeshLoader;
  138. })();