MeshReceiver.js 7.0 KB

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