123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- import { Uint32BufferAttribute, Uint16BufferAttribute } from 'three';
- function arrayNeedsUint32( array ) {
- // assumes larger values usually on last
- for ( let i = array.length - 1; i >= 0; -- i ) {
- if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
- }
- return false;
- }
- class WebGPUGeometries {
- constructor( attributes, info ) {
- this.attributes = attributes;
- this.info = info;
- this.geometries = new WeakMap();
- this.wireframeGeometries = new WeakMap();
- }
- has( geometry ) {
- return this.geometries.has( geometry );
- }
- update( geometry, wireframe = false ) {
- const { geometries, attributes, info } = this;
- if ( geometries.has( geometry ) === false ) {
- const disposeCallback = onGeometryDispose.bind( this );
- geometries.set( geometry, disposeCallback );
- info.memory.geometries ++;
- geometry.addEventListener( 'dispose', disposeCallback );
- }
- const geometryAttributes = geometry.attributes;
- for ( const name in geometryAttributes ) {
- attributes.update( geometryAttributes[ name ] );
- }
- const index = this.getIndex( geometry, wireframe );
- if ( index !== null ) {
- attributes.update( index, true );
- }
- }
- getIndex( geometry, wireframe = false ) {
- let index = geometry.index;
- if ( wireframe ) {
- const wireframeGeometries = this.wireframeGeometries;
- let wireframeAttribute = wireframeGeometries.get( geometry );
- if ( wireframeAttribute === undefined ) {
- wireframeAttribute = this.getWireframeIndex( geometry );
- wireframeGeometries.set( geometry, wireframeAttribute );
- } else if ( wireframeAttribute.version !== this.getWireframeVersion( geometry ) ) {
- this.attributes.remove( wireframeAttribute );
- wireframeAttribute = this.getWireframeIndex( geometry );
- wireframeGeometries.set( geometry, wireframeAttribute );
- }
- index = wireframeAttribute;
- }
- return index;
- }
- getWireframeIndex( geometry ) {
- const indices = [];
- const geometryIndex = geometry.index;
- const geometryPosition = geometry.attributes.position;
- if ( geometryIndex !== null ) {
- const array = geometryIndex.array;
- for ( let i = 0, l = array.length; i < l; i += 3 ) {
- const a = array[ i + 0 ];
- const b = array[ i + 1 ];
- const c = array[ i + 2 ];
- indices.push( a, b, b, c, c, a );
- }
- } else {
- const array = geometryPosition.array;
- for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
- const a = i + 0;
- const b = i + 1;
- const c = i + 2;
- indices.push( a, b, b, c, c, a );
- }
- }
- const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
- attribute.version = this.getWireframeVersion( geometry );
- return attribute;
- }
- getWireframeVersion( geometry ) {
- return ( geometry.index !== null ) ? geometry.index.version : geometry.attributes.position.version;
- }
- }
- function onGeometryDispose( event ) {
- const geometry = event.target;
- const disposeCallback = this.geometries.get( geometry );
- this.geometries.delete( geometry );
- this.info.memory.geometries --;
- geometry.removeEventListener( 'dispose', disposeCallback );
- //
- const index = geometry.index;
- const geometryAttributes = geometry.attributes;
- if ( index !== null ) {
- this.attributes.remove( index );
- }
- for ( const name in geometryAttributes ) {
- this.attributes.remove( geometryAttributes[ name ] );
- }
- }
- export default WebGPUGeometries;
|