MeshReceiver.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /**
  2. * Development repository: https://github.com/kaisalmen/WWOBJLoader
  3. */
  4. import {
  5. BufferAttribute,
  6. BufferGeometry,
  7. LineSegments,
  8. Mesh,
  9. Points
  10. } from '../../../../../build/three.module.js';
  11. /**
  12. *
  13. * @param {MaterialHandler} materialHandler
  14. * @constructor
  15. */
  16. const MeshReceiver = function ( materialHandler ) {
  17. this.logging = {
  18. enabled: false,
  19. debug: false
  20. };
  21. this.callbacks = {
  22. onProgress: null,
  23. onMeshAlter: null
  24. };
  25. this.materialHandler = materialHandler;
  26. };
  27. MeshReceiver.prototype = {
  28. constructor: MeshReceiver,
  29. /**
  30. * Enable or disable logging in general (except warn and error), plus enable or disable debug logging.
  31. *
  32. * @param {boolean} enabled True or false.
  33. * @param {boolean} debug True or false.
  34. */
  35. setLogging: function ( enabled, debug ) {
  36. this.logging.enabled = enabled === true;
  37. this.logging.debug = debug === true;
  38. },
  39. /**
  40. *
  41. * @param {Function} onProgress
  42. * @param {Function} onMeshAlter
  43. * @private
  44. */
  45. _setCallbacks: function ( onProgress, onMeshAlter ) {
  46. if ( onProgress !== null && onProgress !== undefined && onProgress instanceof Function ) {
  47. this.callbacks.onProgress = onProgress;
  48. }
  49. if ( onMeshAlter !== null && onMeshAlter !== undefined && onMeshAlter instanceof Function ) {
  50. this.callbacks.onMeshAlter = onMeshAlter;
  51. }
  52. },
  53. /**
  54. * Builds one or multiple meshes from the data described in the payload (buffers, params, material info).
  55. *
  56. * @param {Object} meshPayload Raw mesh description (buffers, params, materials) used to build one to many meshes.
  57. * @returns {Mesh[]} mesh Array of {@link Mesh}
  58. */
  59. buildMeshes: function ( meshPayload ) {
  60. const meshName = meshPayload.params.meshName;
  61. const buffers = meshPayload.buffers;
  62. const bufferGeometry = new BufferGeometry();
  63. if ( buffers.vertices !== undefined && buffers.vertices !== null ) {
  64. bufferGeometry.setAttribute( 'position', new BufferAttribute( new Float32Array( buffers.vertices ), 3 ) );
  65. }
  66. if ( buffers.indices !== undefined && buffers.indices !== null ) {
  67. bufferGeometry.setIndex( new BufferAttribute( new Uint32Array( buffers.indices ), 1 ) );
  68. }
  69. if ( buffers.colors !== undefined && buffers.colors !== null ) {
  70. bufferGeometry.setAttribute( 'color', new BufferAttribute( new Float32Array( buffers.colors ), 3 ) );
  71. }
  72. if ( buffers.normals !== undefined && buffers.normals !== null ) {
  73. bufferGeometry.setAttribute( 'normal', new BufferAttribute( new Float32Array( buffers.normals ), 3 ) );
  74. } else {
  75. bufferGeometry.computeVertexNormals();
  76. }
  77. if ( buffers.uvs !== undefined && buffers.uvs !== null ) {
  78. bufferGeometry.setAttribute( 'uv', new BufferAttribute( new Float32Array( buffers.uvs ), 2 ) );
  79. }
  80. if ( buffers.skinIndex !== undefined && buffers.skinIndex !== null ) {
  81. bufferGeometry.setAttribute( 'skinIndex', new BufferAttribute( new Uint16Array( buffers.skinIndex ), 4 ) );
  82. }
  83. if ( buffers.skinWeight !== undefined && buffers.skinWeight !== null ) {
  84. bufferGeometry.setAttribute( 'skinWeight', new BufferAttribute( new Float32Array( buffers.skinWeight ), 4 ) );
  85. }
  86. let material, materialName, key;
  87. const materialNames = meshPayload.materials.materialNames;
  88. const createMultiMaterial = meshPayload.materials.multiMaterial;
  89. const multiMaterials = [];
  90. for ( key in materialNames ) {
  91. materialName = materialNames[ key ];
  92. material = this.materialHandler.getMaterial( materialName );
  93. if ( createMultiMaterial ) multiMaterials.push( material );
  94. }
  95. if ( createMultiMaterial ) {
  96. material = multiMaterials;
  97. const materialGroups = meshPayload.materials.materialGroups;
  98. let materialGroup;
  99. for ( key in materialGroups ) {
  100. materialGroup = materialGroups[ key ];
  101. bufferGeometry.addGroup( materialGroup.start, materialGroup.count, materialGroup.index );
  102. }
  103. }
  104. const meshes = [];
  105. let mesh;
  106. let callbackOnMeshAlterResult;
  107. let useOrgMesh = true;
  108. const geometryType = meshPayload.geometryType === null ? 0 : meshPayload.geometryType;
  109. if ( this.callbacks.onMeshAlter ) {
  110. callbackOnMeshAlterResult = this.callbacks.onMeshAlter(
  111. {
  112. detail: {
  113. meshName: meshName,
  114. bufferGeometry: bufferGeometry,
  115. material: material,
  116. geometryType: geometryType
  117. }
  118. }
  119. );
  120. }
  121. // here LoadedMeshUserOverride is required to be provided by the callback used to alter the results
  122. if ( callbackOnMeshAlterResult ) {
  123. if ( callbackOnMeshAlterResult.isDisregardMesh() ) {
  124. useOrgMesh = false;
  125. } else if ( callbackOnMeshAlterResult.providesAlteredMeshes() ) {
  126. for ( const i in callbackOnMeshAlterResult.meshes ) {
  127. meshes.push( callbackOnMeshAlterResult.meshes[ i ] );
  128. }
  129. useOrgMesh = false;
  130. }
  131. }
  132. if ( useOrgMesh ) {
  133. if ( meshPayload.computeBoundingSphere ) bufferGeometry.computeBoundingSphere();
  134. if ( geometryType === 0 ) {
  135. mesh = new Mesh( bufferGeometry, material );
  136. } else if ( geometryType === 1 ) {
  137. mesh = new LineSegments( bufferGeometry, material );
  138. } else {
  139. mesh = new Points( bufferGeometry, material );
  140. }
  141. mesh.name = meshName;
  142. meshes.push( mesh );
  143. }
  144. let progressMessage = meshPayload.params.meshName;
  145. if ( meshes.length > 0 ) {
  146. const meshNames = [];
  147. for ( const i in meshes ) {
  148. mesh = meshes[ i ];
  149. meshNames[ i ] = mesh.name;
  150. }
  151. progressMessage += ': Adding mesh(es) (' + meshNames.length + ': ' + meshNames + ') from input mesh: ' + meshName;
  152. progressMessage += ' (' + ( meshPayload.progress.numericalValue * 100 ).toFixed( 2 ) + '%)';
  153. } else {
  154. progressMessage += ': Not adding mesh: ' + meshName;
  155. progressMessage += ' (' + ( meshPayload.progress.numericalValue * 100 ).toFixed( 2 ) + '%)';
  156. }
  157. if ( this.callbacks.onProgress ) {
  158. this.callbacks.onProgress( 'progress', progressMessage, meshPayload.progress.numericalValue );
  159. }
  160. return meshes;
  161. }
  162. };
  163. /**
  164. * Object to return by callback onMeshAlter. Used to disregard a certain mesh or to return one to many meshes.
  165. * @class
  166. *
  167. * @param {boolean} disregardMesh=false Tell implementation to completely disregard this mesh
  168. * @param {boolean} disregardMesh=false Tell implementation that mesh(es) have been altered or added
  169. */
  170. const LoadedMeshUserOverride = function ( disregardMesh, alteredMesh ) {
  171. this.disregardMesh = disregardMesh === true;
  172. this.alteredMesh = alteredMesh === true;
  173. this.meshes = [];
  174. };
  175. LoadedMeshUserOverride.prototype = {
  176. constructor: LoadedMeshUserOverride,
  177. /**
  178. * Add a mesh created within callback.
  179. *
  180. * @param {Mesh} mesh
  181. */
  182. addMesh: function ( mesh ) {
  183. this.meshes.push( mesh );
  184. this.alteredMesh = true;
  185. },
  186. /**
  187. * Answers if mesh shall be disregarded completely.
  188. *
  189. * @returns {boolean}
  190. */
  191. isDisregardMesh: function () {
  192. return this.disregardMesh;
  193. },
  194. /**
  195. * Answers if new mesh(es) were created.
  196. *
  197. * @returns {boolean}
  198. */
  199. providesAlteredMeshes: function () {
  200. return this.alteredMesh;
  201. }
  202. };
  203. export {
  204. MeshReceiver,
  205. LoadedMeshUserOverride
  206. };