SceneUtils.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import {
  2. Group,
  3. Mesh,
  4. BufferAttribute,
  5. BufferGeometry
  6. } from 'three';
  7. import { mergeGroups } from './BufferGeometryUtils.js';
  8. function createMeshesFromInstancedMesh( instancedMesh ) {
  9. const group = new Group();
  10. const count = instancedMesh.count;
  11. const geometry = instancedMesh.geometry;
  12. const material = instancedMesh.material;
  13. for ( let i = 0; i < count; i ++ ) {
  14. const mesh = new Mesh( geometry, material );
  15. instancedMesh.getMatrixAt( i, mesh.matrix );
  16. mesh.matrix.decompose( mesh.position, mesh.quaternion, mesh.scale );
  17. group.add( mesh );
  18. }
  19. group.copy( instancedMesh );
  20. group.updateMatrixWorld(); // ensure correct world matrices of meshes
  21. return group;
  22. }
  23. function createMeshesFromMultiMaterialMesh( mesh ) {
  24. if ( Array.isArray( mesh.material ) === false ) {
  25. console.warn( 'THREE.SceneUtils.createMeshesFromMultiMaterialMesh(): The given mesh has no multiple materials.' );
  26. return mesh;
  27. }
  28. const object = new Group();
  29. object.copy( mesh );
  30. // merge groups (which automatically sorts them)
  31. const geometry = mergeGroups( mesh.geometry );
  32. const index = geometry.index;
  33. const groups = geometry.groups;
  34. const attributeNames = Object.keys( geometry.attributes );
  35. // create a mesh for each group by extracting the buffer data into a new geometry
  36. for ( let i = 0; i < groups.length; i ++ ) {
  37. const group = groups[ i ];
  38. const start = group.start;
  39. const end = start + group.count;
  40. const newGeometry = new BufferGeometry();
  41. const newMaterial = mesh.material[ group.materialIndex ];
  42. // process all buffer attributes
  43. for ( let j = 0; j < attributeNames.length; j ++ ) {
  44. const name = attributeNames[ j ];
  45. const attribute = geometry.attributes[ name ];
  46. const itemSize = attribute.itemSize;
  47. const newLength = group.count * itemSize;
  48. const type = attribute.array.constructor;
  49. const newArray = new type( newLength );
  50. const newAttribute = new BufferAttribute( newArray, itemSize );
  51. for ( let k = start, n = 0; k < end; k ++, n ++ ) {
  52. const ind = index.getX( k );
  53. if ( itemSize >= 1 ) newAttribute.setX( n, attribute.getX( ind ) );
  54. if ( itemSize >= 2 ) newAttribute.setY( n, attribute.getY( ind ) );
  55. if ( itemSize >= 3 ) newAttribute.setZ( n, attribute.getZ( ind ) );
  56. if ( itemSize >= 4 ) newAttribute.setW( n, attribute.getW( ind ) );
  57. }
  58. newGeometry.setAttribute( name, newAttribute );
  59. }
  60. const newMesh = new Mesh( newGeometry, newMaterial );
  61. object.add( newMesh );
  62. }
  63. return object;
  64. }
  65. function createMultiMaterialObject( geometry, materials ) {
  66. const group = new Group();
  67. for ( let i = 0, l = materials.length; i < l; i ++ ) {
  68. group.add( new Mesh( geometry, materials[ i ] ) );
  69. }
  70. return group;
  71. }
  72. export {
  73. createMeshesFromInstancedMesh,
  74. createMeshesFromMultiMaterialMesh,
  75. createMultiMaterialObject
  76. };