216 lines
4.0 KiB
JavaScript
216 lines
4.0 KiB
JavaScript
|
import DataMap from './DataMap.js';
|
||
|
import { AttributeType } from './Constants.js';
|
||
|
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;
|
||
|
|
||
|
}
|
||
|
|
||
|
function getWireframeVersion( geometry ) {
|
||
|
|
||
|
return ( geometry.index !== null ) ? geometry.index.version : geometry.attributes.position.version;
|
||
|
|
||
|
}
|
||
|
|
||
|
function 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 = getWireframeVersion( geometry );
|
||
|
|
||
|
return attribute;
|
||
|
|
||
|
}
|
||
|
|
||
|
class Geometries extends DataMap {
|
||
|
|
||
|
constructor( attributes, info ) {
|
||
|
|
||
|
super();
|
||
|
|
||
|
this.attributes = attributes;
|
||
|
this.info = info;
|
||
|
|
||
|
this.wireframes = new WeakMap();
|
||
|
this.attributeCall = new WeakMap();
|
||
|
|
||
|
}
|
||
|
|
||
|
has( renderObject ) {
|
||
|
|
||
|
const geometry = renderObject.geometry;
|
||
|
|
||
|
return super.has( geometry ) && this.get( geometry ).initialized === true;
|
||
|
|
||
|
}
|
||
|
|
||
|
updateForRender( renderObject ) {
|
||
|
|
||
|
if ( this.has( renderObject ) === false ) this.initGeometry( renderObject );
|
||
|
|
||
|
this.updateAttributes( renderObject );
|
||
|
|
||
|
}
|
||
|
|
||
|
initGeometry( renderObject ) {
|
||
|
|
||
|
const geometry = renderObject.geometry;
|
||
|
const geometryData = this.get( geometry );
|
||
|
|
||
|
geometryData.initialized = true;
|
||
|
|
||
|
this.info.memory.geometries ++;
|
||
|
|
||
|
const onDispose = () => {
|
||
|
|
||
|
this.info.memory.geometries --;
|
||
|
|
||
|
const index = geometry.index;
|
||
|
const geometryAttributes = renderObject.getAttributes();
|
||
|
|
||
|
if ( index !== null ) {
|
||
|
|
||
|
this.attributes.delete( index );
|
||
|
|
||
|
}
|
||
|
|
||
|
for ( const geometryAttribute of geometryAttributes ) {
|
||
|
|
||
|
this.attributes.delete( geometryAttribute );
|
||
|
|
||
|
}
|
||
|
|
||
|
const wireframeAttribute = this.wireframes.get( geometry );
|
||
|
|
||
|
if ( wireframeAttribute !== undefined ) {
|
||
|
|
||
|
this.attributes.delete( wireframeAttribute );
|
||
|
|
||
|
}
|
||
|
|
||
|
geometry.removeEventListener( 'dispose', onDispose );
|
||
|
|
||
|
};
|
||
|
|
||
|
geometry.addEventListener( 'dispose', onDispose );
|
||
|
|
||
|
}
|
||
|
|
||
|
updateAttributes( renderObject ) {
|
||
|
|
||
|
const attributes = renderObject.getAttributes();
|
||
|
|
||
|
for ( const attribute of attributes ) {
|
||
|
|
||
|
this.updateAttribute( attribute, AttributeType.VERTEX );
|
||
|
|
||
|
}
|
||
|
|
||
|
const index = this.getIndex( renderObject );
|
||
|
|
||
|
if ( index !== null ) {
|
||
|
|
||
|
this.updateAttribute( index, AttributeType.INDEX );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
updateAttribute( attribute, type ) {
|
||
|
|
||
|
const callId = this.info.render.calls;
|
||
|
|
||
|
if ( this.attributeCall.get( attribute ) !== callId ) {
|
||
|
|
||
|
this.attributes.update( attribute, type );
|
||
|
|
||
|
this.attributeCall.set( attribute, callId );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
getIndex( renderObject ) {
|
||
|
|
||
|
const { geometry, material } = renderObject;
|
||
|
|
||
|
let index = geometry.index;
|
||
|
|
||
|
if ( material.wireframe === true ) {
|
||
|
|
||
|
const wireframes = this.wireframes;
|
||
|
|
||
|
let wireframeAttribute = wireframes.get( geometry );
|
||
|
|
||
|
if ( wireframeAttribute === undefined ) {
|
||
|
|
||
|
wireframeAttribute = getWireframeIndex( geometry );
|
||
|
|
||
|
wireframes.set( geometry, wireframeAttribute );
|
||
|
|
||
|
} else if ( wireframeAttribute.version !== getWireframeVersion( geometry ) ) {
|
||
|
|
||
|
this.attributes.delete( wireframeAttribute );
|
||
|
|
||
|
wireframeAttribute = getWireframeIndex( geometry );
|
||
|
|
||
|
wireframes.set( geometry, wireframeAttribute );
|
||
|
|
||
|
}
|
||
|
|
||
|
index = wireframeAttribute;
|
||
|
|
||
|
}
|
||
|
|
||
|
return index;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
export default Geometries;
|