MeshReceiver.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. onParseProgress: 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} onParseProgress
  43. * @param {Function} onMeshAlter
  44. * @private
  45. */
  46. _setCallbacks: function ( onParseProgress, onMeshAlter ) {
  47. if ( onParseProgress !== undefined && onParseProgress !== null ) {
  48. this.callbacks.onParseProgress = onParseProgress;
  49. }
  50. if ( onMeshAlter !== undefined && onMeshAlter !== null ) {
  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 callbackOnMeshAlter = this.callbacks.onMeshAlter;
  106. let callbackOnMeshAlterResult;
  107. let useOrgMesh = true;
  108. let geometryType = meshPayload.geometryType === null ? 0 : meshPayload.geometryType;
  109. if ( callbackOnMeshAlter ) {
  110. callbackOnMeshAlterResult = callbackOnMeshAlter(
  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 ( let 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. let meshNames = [];
  147. for ( let 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. let callbackOnParseProgress = this.callbacks.onParseProgress;
  158. if ( callbackOnParseProgress ) {
  159. callbackOnParseProgress( 'progress', progressMessage, meshPayload.progress.numericalValue );
  160. }
  161. return meshes;
  162. }
  163. };
  164. /**
  165. * Object to return by callback onMeshAlter. Used to disregard a certain mesh or to return one to many meshes.
  166. * @class
  167. *
  168. * @param {boolean} disregardMesh=false Tell implementation to completely disregard this mesh
  169. * @param {boolean} disregardMesh=false Tell implementation that mesh(es) have been altered or added
  170. */
  171. const LoadedMeshUserOverride = function( disregardMesh, alteredMesh ) {
  172. this.disregardMesh = disregardMesh === true;
  173. this.alteredMesh = alteredMesh === true;
  174. this.meshes = [];
  175. };
  176. LoadedMeshUserOverride.prototype = {
  177. constructor: LoadedMeshUserOverride,
  178. /**
  179. * Add a mesh created within callback.
  180. *
  181. * @param {Mesh} mesh
  182. */
  183. addMesh: function ( mesh ) {
  184. this.meshes.push( mesh );
  185. this.alteredMesh = true;
  186. },
  187. /**
  188. * Answers if mesh shall be disregarded completely.
  189. *
  190. * @returns {boolean}
  191. */
  192. isDisregardMesh: function () {
  193. return this.disregardMesh;
  194. },
  195. /**
  196. * Answers if new mesh(es) were created.
  197. *
  198. * @returns {boolean}
  199. */
  200. providesAlteredMeshes: function () {
  201. return this.alteredMesh;
  202. }
  203. };
  204. export {
  205. MeshReceiver,
  206. LoadedMeshUserOverride
  207. };