WebGPUGeometries.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import { Uint32BufferAttribute, Uint16BufferAttribute } from 'three';
  2. function arrayNeedsUint32( array ) {
  3. // assumes larger values usually on last
  4. for ( let i = array.length - 1; i >= 0; -- i ) {
  5. if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
  6. }
  7. return false;
  8. }
  9. class WebGPUGeometries {
  10. constructor( attributes, info ) {
  11. this.attributes = attributes;
  12. this.info = info;
  13. this.geometries = new WeakMap();
  14. this.wireframeGeometries = new WeakMap();
  15. }
  16. has( geometry ) {
  17. return this.geometries.has( geometry );
  18. }
  19. update( geometry, wireframe = false ) {
  20. const { geometries, attributes, info } = this;
  21. if ( geometries.has( geometry ) === false ) {
  22. const disposeCallback = onGeometryDispose.bind( this );
  23. geometries.set( geometry, disposeCallback );
  24. info.memory.geometries ++;
  25. geometry.addEventListener( 'dispose', disposeCallback );
  26. }
  27. const geometryAttributes = geometry.attributes;
  28. for ( const name in geometryAttributes ) {
  29. attributes.update( geometryAttributes[ name ] );
  30. }
  31. const index = this.getIndex( geometry, wireframe );
  32. if ( index !== null ) {
  33. attributes.update( index, true );
  34. }
  35. }
  36. getIndex( geometry, wireframe = false ) {
  37. let index = geometry.index;
  38. if ( wireframe ) {
  39. const wireframeGeometries = this.wireframeGeometries;
  40. let wireframeAttribute = wireframeGeometries.get( geometry );
  41. if ( wireframeAttribute === undefined ) {
  42. wireframeAttribute = this.getWireframeIndex( geometry );
  43. wireframeGeometries.set( geometry, wireframeAttribute );
  44. } else if ( wireframeAttribute.version !== this.getWireframeVersion( geometry ) ) {
  45. this.attributes.remove( wireframeAttribute );
  46. wireframeAttribute = this.getWireframeIndex( geometry );
  47. wireframeGeometries.set( geometry, wireframeAttribute );
  48. }
  49. index = wireframeAttribute;
  50. }
  51. return index;
  52. }
  53. getWireframeIndex( geometry ) {
  54. const indices = [];
  55. const geometryIndex = geometry.index;
  56. const geometryPosition = geometry.attributes.position;
  57. if ( geometryIndex !== null ) {
  58. const array = geometryIndex.array;
  59. for ( let i = 0, l = array.length; i < l; i += 3 ) {
  60. const a = array[ i + 0 ];
  61. const b = array[ i + 1 ];
  62. const c = array[ i + 2 ];
  63. indices.push( a, b, b, c, c, a );
  64. }
  65. } else {
  66. const array = geometryPosition.array;
  67. for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
  68. const a = i + 0;
  69. const b = i + 1;
  70. const c = i + 2;
  71. indices.push( a, b, b, c, c, a );
  72. }
  73. }
  74. const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
  75. attribute.version = this.getWireframeVersion( geometry );
  76. return attribute;
  77. }
  78. getWireframeVersion( geometry ) {
  79. return ( geometry.index !== null ) ? geometry.index.version : geometry.attributes.position.version;
  80. }
  81. }
  82. function onGeometryDispose( event ) {
  83. const geometry = event.target;
  84. const disposeCallback = this.geometries.get( geometry );
  85. this.geometries.delete( geometry );
  86. this.info.memory.geometries --;
  87. geometry.removeEventListener( 'dispose', disposeCallback );
  88. //
  89. const index = geometry.index;
  90. const geometryAttributes = geometry.attributes;
  91. if ( index !== null ) {
  92. this.attributes.remove( index );
  93. }
  94. for ( const name in geometryAttributes ) {
  95. this.attributes.remove( geometryAttributes[ name ] );
  96. }
  97. }
  98. export default WebGPUGeometries;