MeshReceiver.js 6.8 KB

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