MeshReceiver.js 7.0 KB

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