I3DMLoader.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { I3DMLoaderBase } from '../base/I3DMLoaderBase.js';
  2. import { DefaultLoadingManager, Matrix4, InstancedMesh, Vector3, Quaternion } from 'three';
  3. import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
  4. const tempPos = new Vector3();
  5. const tempQuat = new Quaternion();
  6. const tempSca = new Vector3();
  7. const tempMat = new Matrix4();
  8. export class I3DMLoader extends I3DMLoaderBase {
  9. constructor( manager = DefaultLoadingManager ) {
  10. super();
  11. this.manager = manager;
  12. }
  13. parse( buffer ) {
  14. return super
  15. .parse( buffer )
  16. .then( i3dm => {
  17. const { featureTable, batchTable } = i3dm;
  18. const gltfBuffer = i3dm.glbBytes.slice().buffer;
  19. return new Promise( ( resolve, reject ) => {
  20. const manager = this.manager;
  21. const loader = manager.getHandler( 'path.gltf' ) || new GLTFLoader( manager );
  22. loader.parse( gltfBuffer, null, model => {
  23. const INSTANCES_LENGTH = featureTable.getData( 'INSTANCES_LENGTH' );
  24. // RTC_CENTER
  25. // QUANTIZED_VOLUME_OFFSET
  26. // QUANTIZED_VOLUME_SCALE
  27. // EAST_NORTH_UP
  28. const POSITION = featureTable.getData( 'POSITION', INSTANCES_LENGTH, 'FLOAT', 'VEC3' );
  29. // POSITION_QUANTIZED
  30. // NORMAL_UP
  31. // NORMAL_RIGHT
  32. // NORMAL_UP_OCT32P
  33. // NORMAL_RIGHT_OCT32P
  34. // SCALE
  35. // SCALE_NON_UNIFORM
  36. // BATCH_ID
  37. const instanceMap = new Map();
  38. const instances = [];
  39. model.scene.traverse( child => {
  40. if ( child.isMesh ) {
  41. const { geometry, material } = child;
  42. const instancedMesh = new InstancedMesh( geometry, material, INSTANCES_LENGTH );
  43. instances.push( instancedMesh );
  44. instanceMap.set( child, instancedMesh );
  45. }
  46. } );
  47. // replace the meshes with instanced meshes
  48. instanceMap.forEach( ( instancedMesh, mesh ) => {
  49. const parent = mesh.parent;
  50. if ( parent ) {
  51. // Mesh have no children
  52. parent.remove( mesh );
  53. parent.add( instancedMesh );
  54. }
  55. } );
  56. for ( let i = 0; i < INSTANCES_LENGTH; i ++ ) {
  57. // TODO: handle quantized position
  58. tempPos.set(
  59. POSITION[ i * 3 + 0 ],
  60. POSITION[ i * 3 + 1 ],
  61. POSITION[ i * 3 + 2 ],
  62. );
  63. // TODO: handle normal orientation features
  64. tempQuat.set( 0, 0, 0, 1 );
  65. // TODO: handle scale features
  66. tempSca.set( 1, 1, 1 );
  67. tempMat.compose( tempPos, tempQuat, tempSca );
  68. for ( let j = 0, l = instances.length; j < l; j ++ ) {
  69. const instance = instances[ j ];
  70. instance.setMatrixAt( i, tempMat );
  71. }
  72. }
  73. model.batchTable = batchTable;
  74. model.featureTable = featureTable;
  75. resolve( model );
  76. }, reject );
  77. } );
  78. } );
  79. }
  80. }