Geometries.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import DataMap from './DataMap.js';
  2. import { AttributeType } from './Constants.js';
  3. import { Uint32BufferAttribute, Uint16BufferAttribute } from 'three';
  4. function arrayNeedsUint32( array ) {
  5. // assumes larger values usually on last
  6. for ( let i = array.length - 1; i >= 0; -- i ) {
  7. if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
  8. }
  9. return false;
  10. }
  11. function getWireframeVersion( geometry ) {
  12. return ( geometry.index !== null ) ? geometry.index.version : geometry.attributes.position.version;
  13. }
  14. function getWireframeIndex( geometry ) {
  15. const indices = [];
  16. const geometryIndex = geometry.index;
  17. const geometryPosition = geometry.attributes.position;
  18. if ( geometryIndex !== null ) {
  19. const array = geometryIndex.array;
  20. for ( let i = 0, l = array.length; i < l; i += 3 ) {
  21. const a = array[ i + 0 ];
  22. const b = array[ i + 1 ];
  23. const c = array[ i + 2 ];
  24. indices.push( a, b, b, c, c, a );
  25. }
  26. } else {
  27. const array = geometryPosition.array;
  28. for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
  29. const a = i + 0;
  30. const b = i + 1;
  31. const c = i + 2;
  32. indices.push( a, b, b, c, c, a );
  33. }
  34. }
  35. const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
  36. attribute.version = getWireframeVersion( geometry );
  37. return attribute;
  38. }
  39. class Geometries extends DataMap {
  40. constructor( attributes, info ) {
  41. super();
  42. this.attributes = attributes;
  43. this.info = info;
  44. this.wireframes = new WeakMap();
  45. this.attributeFrame = new WeakMap();
  46. }
  47. has( renderObject ) {
  48. const geometry = renderObject.geometry;
  49. return super.has( geometry ) && this.get( geometry ).initialized === true;
  50. }
  51. updateForRender( renderObject ) {
  52. if ( this.has( renderObject ) === false ) this.initGeometry( renderObject );
  53. this.updateAttributes( renderObject );
  54. }
  55. initGeometry( renderObject ) {
  56. const geometry = renderObject.geometry;
  57. const geometryData = this.get( geometry );
  58. geometryData.initialized = true;
  59. this.info.memory.geometries ++;
  60. const onDispose = () => {
  61. this.info.memory.geometries --;
  62. const index = geometry.index;
  63. const geometryAttributes = renderObject.getAttributes();
  64. if ( index !== null ) {
  65. this.attributes.delete( index );
  66. }
  67. for ( const geometryAttribute of geometryAttributes ) {
  68. this.attributes.delete( geometryAttribute );
  69. }
  70. const wireframeAttribute = this.wireframes.get( geometry );
  71. if ( wireframeAttribute !== undefined ) {
  72. this.attributes.delete( wireframeAttribute );
  73. }
  74. geometry.removeEventListener( 'dispose', onDispose );
  75. };
  76. geometry.addEventListener( 'dispose', onDispose );
  77. }
  78. updateAttributes( renderObject ) {
  79. const attributes = renderObject.getAttributes();
  80. for ( const attribute of attributes ) {
  81. this.updateAttribute( attribute, AttributeType.VERTEX );
  82. }
  83. const index = this.getIndex( renderObject );
  84. if ( index !== null ) {
  85. this.updateAttribute( index, AttributeType.INDEX );
  86. }
  87. }
  88. updateAttribute( attribute, type ) {
  89. const frame = this.info.render.frame;
  90. if ( this.attributeFrame.get( attribute ) !== frame ) {
  91. this.attributes.update( attribute, type );
  92. this.attributeFrame.set( attribute, frame );
  93. }
  94. }
  95. getIndex( renderObject ) {
  96. const { geometry, material } = renderObject;
  97. let index = geometry.index;
  98. if ( material.wireframe === true ) {
  99. const wireframes = this.wireframes;
  100. let wireframeAttribute = wireframes.get( geometry );
  101. if ( wireframeAttribute === undefined ) {
  102. wireframeAttribute = getWireframeIndex( geometry );
  103. wireframes.set( geometry, wireframeAttribute );
  104. } else if ( wireframeAttribute.version !== getWireframeVersion( geometry ) ) {
  105. this.attributes.delete( wireframeAttribute );
  106. wireframeAttribute = getWireframeIndex( geometry );
  107. wireframes.set( geometry, wireframeAttribute );
  108. }
  109. index = wireframeAttribute;
  110. }
  111. return index;
  112. }
  113. }
  114. export default Geometries;