LoaderBuilder.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /**
  2. * Builds one or many THREE.Mesh from one raw set of Arraybuffers, materialGroup descriptions and further parameters.
  3. * Supports vertex, vertexColor, normal, uv and index buffers.
  4. * @class
  5. */
  6. THREE.LoaderSupport.MeshBuilder = (function () {
  7. var LOADER_MESH_BUILDER_VERSION = '1.2.0';
  8. var Validator = THREE.LoaderSupport.Validator;
  9. function MeshBuilder() {
  10. console.info( 'Using THREE.LoaderSupport.MeshBuilder version: ' + LOADER_MESH_BUILDER_VERSION );
  11. this.logging = {
  12. enabled: true,
  13. debug: false
  14. };
  15. this.callbacks = new THREE.LoaderSupport.Callbacks();
  16. this.materials = [];
  17. }
  18. /**
  19. * Enable or disable logging in general (except warn and error), plus enable or disable debug logging.
  20. * @memberOf THREE.LoaderSupport.MeshBuilder
  21. *
  22. * @param {boolean} enabled True or false.
  23. * @param {boolean} debug True or false.
  24. */
  25. MeshBuilder.prototype.setLogging = function ( enabled, debug ) {
  26. this.logging.enabled = enabled === true;
  27. this.logging.debug = debug === true;
  28. };
  29. /**
  30. * Initializes the MeshBuilder (currently only default material initialisation).
  31. * @memberOf THREE.LoaderSupport.MeshBuilder
  32. *
  33. */
  34. MeshBuilder.prototype.init = function () {
  35. var defaultMaterial = new THREE.MeshStandardMaterial( { color: 0xDCF1FF } );
  36. defaultMaterial.name = 'defaultMaterial';
  37. var defaultVertexColorMaterial = new THREE.MeshStandardMaterial( { color: 0xDCF1FF } );
  38. defaultVertexColorMaterial.name = 'defaultVertexColorMaterial';
  39. defaultVertexColorMaterial.vertexColors = THREE.VertexColors;
  40. var defaultLineMaterial = new THREE.LineBasicMaterial();
  41. defaultLineMaterial.name = 'defaultLineMaterial';
  42. var defaultPointMaterial = new THREE.PointsMaterial( { size: 1 } );
  43. defaultPointMaterial.name = 'defaultPointMaterial';
  44. var runtimeMaterials = {};
  45. runtimeMaterials[ defaultMaterial.name ] = defaultMaterial;
  46. runtimeMaterials[ defaultVertexColorMaterial.name ] = defaultVertexColorMaterial;
  47. runtimeMaterials[ defaultLineMaterial.name ] = defaultLineMaterial;
  48. runtimeMaterials[ defaultPointMaterial.name ] = defaultPointMaterial;
  49. this.updateMaterials(
  50. {
  51. cmd: 'materialData',
  52. materials: {
  53. materialCloneInstructions: null,
  54. serializedMaterials: null,
  55. runtimeMaterials: runtimeMaterials
  56. }
  57. }
  58. );
  59. };
  60. /**
  61. * Set materials loaded by any supplier of an Array of {@link THREE.Material}.
  62. * @memberOf THREE.LoaderSupport.MeshBuilder
  63. *
  64. * @param {THREE.Material[]} materials Array of {@link THREE.Material}
  65. */
  66. MeshBuilder.prototype.setMaterials = function ( materials ) {
  67. var payload = {
  68. cmd: 'materialData',
  69. materials: {
  70. materialCloneInstructions: null,
  71. serializedMaterials: null,
  72. runtimeMaterials: Validator.isValid( this.callbacks.onLoadMaterials ) ? this.callbacks.onLoadMaterials( materials ) : materials
  73. }
  74. };
  75. this.updateMaterials( payload );
  76. };
  77. MeshBuilder.prototype._setCallbacks = function ( callbacks ) {
  78. if ( Validator.isValid( callbacks.onProgress ) ) this.callbacks.setCallbackOnProgress( callbacks.onProgress );
  79. if ( Validator.isValid( callbacks.onMeshAlter ) ) this.callbacks.setCallbackOnMeshAlter( callbacks.onMeshAlter );
  80. if ( Validator.isValid( callbacks.onLoad ) ) this.callbacks.setCallbackOnLoad( callbacks.onLoad );
  81. if ( Validator.isValid( callbacks.onLoadMaterials ) ) this.callbacks.setCallbackOnLoadMaterials( callbacks.onLoadMaterials );
  82. };
  83. /**
  84. * Delegates processing of the payload (mesh building or material update) to the corresponding functions (BW-compatibility).
  85. * @memberOf THREE.LoaderSupport.MeshBuilder
  86. *
  87. * @param {Object} payload Raw Mesh or Material descriptions.
  88. * @returns {THREE.Mesh[]} mesh Array of {@link THREE.Mesh} or null in case of material update
  89. */
  90. MeshBuilder.prototype.processPayload = function ( payload ) {
  91. if ( payload.cmd === 'meshData' ) {
  92. return this.buildMeshes( payload );
  93. } else if ( payload.cmd === 'materialData' ) {
  94. this.updateMaterials( payload );
  95. return null;
  96. }
  97. };
  98. /**
  99. * Builds one or multiple meshes from the data described in the payload (buffers, params, material info).
  100. * @memberOf THREE.LoaderSupport.MeshBuilder
  101. *
  102. * @param {Object} meshPayload Raw mesh description (buffers, params, materials) used to build one to many meshes.
  103. * @returns {THREE.Mesh[]} mesh Array of {@link THREE.Mesh}
  104. */
  105. MeshBuilder.prototype.buildMeshes = function ( meshPayload ) {
  106. var meshName = meshPayload.params.meshName;
  107. var bufferGeometry = new THREE.BufferGeometry();
  108. bufferGeometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( meshPayload.buffers.vertices ), 3 ) );
  109. if ( Validator.isValid( meshPayload.buffers.indices ) ) {
  110. bufferGeometry.setIndex( new THREE.BufferAttribute( new Uint32Array( meshPayload.buffers.indices ), 1 ));
  111. }
  112. var haveVertexColors = Validator.isValid( meshPayload.buffers.colors );
  113. if ( haveVertexColors ) {
  114. bufferGeometry.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( meshPayload.buffers.colors ), 3 ) );
  115. }
  116. if ( Validator.isValid( meshPayload.buffers.normals ) ) {
  117. bufferGeometry.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( meshPayload.buffers.normals ), 3 ) );
  118. } else {
  119. bufferGeometry.computeVertexNormals();
  120. }
  121. if ( Validator.isValid( meshPayload.buffers.uvs ) ) {
  122. bufferGeometry.addAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( meshPayload.buffers.uvs ), 2 ) );
  123. }
  124. var material, materialName, key;
  125. var materialNames = meshPayload.materials.materialNames;
  126. var createMultiMaterial = meshPayload.materials.multiMaterial;
  127. var multiMaterials = [];
  128. for ( key in materialNames ) {
  129. materialName = materialNames[ key ];
  130. material = this.materials[ materialName ];
  131. if ( createMultiMaterial ) multiMaterials.push( material );
  132. }
  133. if ( createMultiMaterial ) {
  134. material = multiMaterials;
  135. var materialGroups = meshPayload.materials.materialGroups;
  136. var materialGroup;
  137. for ( key in materialGroups ) {
  138. materialGroup = materialGroups[ key ];
  139. bufferGeometry.addGroup( materialGroup.start, materialGroup.count, materialGroup.index );
  140. }
  141. }
  142. var meshes = [];
  143. var mesh;
  144. var callbackOnMeshAlter = this.callbacks.onMeshAlter;
  145. var callbackOnMeshAlterResult;
  146. var useOrgMesh = true;
  147. var geometryType = Validator.verifyInput( meshPayload.geometryType, 0 );
  148. if ( Validator.isValid( callbackOnMeshAlter ) ) {
  149. callbackOnMeshAlterResult = callbackOnMeshAlter(
  150. {
  151. detail: {
  152. meshName: meshName,
  153. bufferGeometry: bufferGeometry,
  154. material: material,
  155. geometryType: geometryType
  156. }
  157. }
  158. );
  159. if ( Validator.isValid( callbackOnMeshAlterResult ) ) {
  160. if ( ! callbackOnMeshAlterResult.isDisregardMesh() && callbackOnMeshAlterResult.providesAlteredMeshes() ) {
  161. for ( var i in callbackOnMeshAlterResult.meshes ) {
  162. meshes.push( callbackOnMeshAlterResult.meshes[ i ] );
  163. }
  164. }
  165. useOrgMesh = false;
  166. }
  167. }
  168. if ( useOrgMesh ) {
  169. if ( meshPayload.computeBoundingSphere ) bufferGeometry.computeBoundingSphere();
  170. if ( geometryType === 0 ) {
  171. mesh = new THREE.Mesh( bufferGeometry, material );
  172. } else if ( geometryType === 1) {
  173. mesh = new THREE.LineSegments( bufferGeometry, material );
  174. } else {
  175. mesh = new THREE.Points( bufferGeometry, material );
  176. }
  177. mesh.name = meshName;
  178. meshes.push( mesh );
  179. }
  180. var progressMessage;
  181. if ( Validator.isValid( meshes ) && meshes.length > 0 ) {
  182. var meshNames = [];
  183. for ( var i in meshes ) {
  184. mesh = meshes[ i ];
  185. meshNames[ i ] = mesh.name;
  186. }
  187. progressMessage = 'Adding mesh(es) (' + meshNames.length + ': ' + meshNames + ') from input mesh: ' + meshName;
  188. progressMessage += ' (' + ( meshPayload.progress.numericalValue * 100 ).toFixed( 2 ) + '%)';
  189. } else {
  190. progressMessage = 'Not adding mesh: ' + meshName;
  191. progressMessage += ' (' + ( meshPayload.progress.numericalValue * 100 ).toFixed( 2 ) + '%)';
  192. }
  193. var callbackOnProgress = this.callbacks.onProgress;
  194. if ( Validator.isValid( callbackOnProgress ) ) {
  195. var event = new CustomEvent( 'MeshBuilderEvent', {
  196. detail: {
  197. type: 'progress',
  198. modelName: meshPayload.params.meshName,
  199. text: progressMessage,
  200. numericalValue: meshPayload.progress.numericalValue
  201. }
  202. } );
  203. callbackOnProgress( event );
  204. }
  205. return meshes;
  206. };
  207. /**
  208. * Updates the materials with contained material objects (sync) or from alteration instructions (async).
  209. * @memberOf THREE.LoaderSupport.MeshBuilder
  210. *
  211. * @param {Object} materialPayload Material update instructions
  212. */
  213. MeshBuilder.prototype.updateMaterials = function ( materialPayload ) {
  214. var material, materialName;
  215. var materialCloneInstructions = materialPayload.materials.materialCloneInstructions;
  216. if ( Validator.isValid( materialCloneInstructions ) ) {
  217. var materialNameOrg = materialCloneInstructions.materialNameOrg;
  218. var materialOrg = this.materials[ materialNameOrg ];
  219. if ( Validator.isValid( materialNameOrg ) ) {
  220. material = materialOrg.clone();
  221. materialName = materialCloneInstructions.materialName;
  222. material.name = materialName;
  223. var materialProperties = materialCloneInstructions.materialProperties;
  224. for ( var key in materialProperties ) {
  225. if ( material.hasOwnProperty( key ) && materialProperties.hasOwnProperty( key ) ) material[ key ] = materialProperties[ key ];
  226. }
  227. this.materials[ materialName ] = material;
  228. } else {
  229. console.warn( 'Requested material "' + materialNameOrg + '" is not available!' );
  230. }
  231. }
  232. var materials = materialPayload.materials.serializedMaterials;
  233. if ( Validator.isValid( materials ) && Object.keys( materials ).length > 0 ) {
  234. var loader = new THREE.MaterialLoader();
  235. var materialJson;
  236. for ( materialName in materials ) {
  237. materialJson = materials[ materialName ];
  238. if ( Validator.isValid( materialJson ) ) {
  239. material = loader.parse( materialJson );
  240. if ( this.logging.enabled ) console.info( 'De-serialized material with name "' + materialName + '" will be added.' );
  241. this.materials[ materialName ] = material;
  242. }
  243. }
  244. }
  245. materials = materialPayload.materials.runtimeMaterials;
  246. if ( Validator.isValid( materials ) && Object.keys( materials ).length > 0 ) {
  247. for ( materialName in materials ) {
  248. material = materials[ materialName ];
  249. if ( this.logging.enabled ) console.info( 'Material with name "' + materialName + '" will be added.' );
  250. this.materials[ materialName ] = material;
  251. }
  252. }
  253. };
  254. /**
  255. * Returns the mapping object of material name and corresponding jsonified material.
  256. *
  257. * @returns {Object} Map of Materials in JSON representation
  258. */
  259. MeshBuilder.prototype.getMaterialsJSON = function () {
  260. var materialsJSON = {};
  261. var material;
  262. for ( var materialName in this.materials ) {
  263. material = this.materials[ materialName ];
  264. materialsJSON[ materialName ] = material.toJSON();
  265. }
  266. return materialsJSON;
  267. };
  268. /**
  269. * Returns the mapping object of material name and corresponding material.
  270. *
  271. * @returns {Object} Map of {@link THREE.Material}
  272. */
  273. MeshBuilder.prototype.getMaterials = function () {
  274. return this.materials;
  275. };
  276. return MeshBuilder;
  277. })();