three
Version:
JavaScript 3D library
215 lines (117 loc) • 4.26 kB
JavaScript
import { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute.js';
function WebGLGeometries( gl, attributes, info, bindingStates ) {
const geometries = {};
const wireframeAttributes = new WeakMap();
const registry = new FinalizationRegistry( ( id ) => delete geometries[ id ] );
function onGeometryDispose( event ) {
destroyGeometry( event.target );
}
function destroyGeometry( geometry ) {
if ( geometry.index !== null ) {
attributes.remove( geometry.index );
}
for ( const name in geometry.attributes ) {
attributes.remove( geometry.attributes[ name ] );
}
geometry.removeEventListener( 'dispose', onGeometryDispose );
delete geometries[ geometry.id ];
registry.unregister( geometry );
const attribute = wireframeAttributes.get( geometry );
if ( attribute ) {
attributes.remove( attribute );
wireframeAttributes.delete( geometry );
}
bindingStates.releaseStatesOfGeometry( geometry );
if ( geometry.isInstancedBufferGeometry === true ) {
delete geometry._maxInstanceCount;
}
//
info.memory.geometries --;
}
function get( object, geometry ) {
if ( geometries[ geometry.id ] !== undefined ) return geometry;
geometry.addEventListener( 'dispose', onGeometryDispose );
geometries[ geometry.id ] = new WeakRef( geometry );
registry.register( geometry, geometry.id, geometry );
info.memory.geometries ++;
return geometry;
}
function update( geometry ) {
const geometryAttributes = geometry.attributes;
// Updating index buffer in VAO now. See WebGLBindingStates.
for ( const name in geometryAttributes ) {
attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
}
}
function updateWireframeAttribute( geometry ) {
const geometryIndex = geometry.index;
const geometryPosition = geometry.attributes.position;
let version = 0;
if ( geometryPosition === undefined ) {
return;
}
const count = geometryIndex !== null ? geometryIndex.array.length : ( geometryPosition.array.length / 3 ) - 1;
// check whether a 32 bit or 16 bit buffer is required to store the indices
// account for PRIMITIVE_RESTART_FIXED_INDEX, #24565
const IndexBufferAttribute = geometryPosition.count >= 65535 ? Uint32BufferAttribute : Uint16BufferAttribute;
const attribute = new IndexBufferAttribute( Math.ceil( count / 3 ) * 6, 1 );
const indices = attribute.array;
if ( geometryIndex !== null ) {
const array = geometryIndex.array;
version = geometryIndex.version;
for ( let i = 0, j = 0; i < count; i += 3 ) {
const a = array[ i + 0 ];
const b = array[ i + 1 ];
const c = array[ i + 2 ];
indices[ j ++ ] = a; indices[ j ++ ] = b;
indices[ j ++ ] = b; indices[ j ++ ] = c;
indices[ j ++ ] = c; indices[ j ++ ] = a;
}
} else {
version = geometryPosition.version;
for ( let i = 0, j = 0; i < count; i += 3 ) {
const a = i + 0;
const b = i + 1;
const c = i + 2;
indices[ j ++ ] = a; indices[ j ++ ] = b;
indices[ j ++ ] = b; indices[ j ++ ] = c;
indices[ j ++ ] = c; indices[ j ++ ] = a;
}
}
attribute.version = version;
// Updating index buffer in VAO now. See WebGLBindingStates
//
const previousAttribute = wireframeAttributes.get( geometry );
if ( previousAttribute ) attributes.remove( previousAttribute );
//
wireframeAttributes.set( geometry, attribute );
}
function getWireframeAttribute( geometry ) {
const currentAttribute = wireframeAttributes.get( geometry );
if ( currentAttribute ) {
const geometryIndex = geometry.index;
if ( geometryIndex !== null ) {
// if the attribute is obsolete, create a new one
if ( currentAttribute.version < geometryIndex.version ) {
updateWireframeAttribute( geometry );
}
}
} else {
updateWireframeAttribute( geometry );
}
return wireframeAttributes.get( geometry );
}
function dispose() {
for ( const id in geometries ) {
const geometry = geometries[ id ].deref();
if ( geometry !== undefined ) destroyGeometry( geometry );
}
}
return {
get: get,
update: update,
getWireframeAttribute: getWireframeAttribute,
dispose: dispose
};
}
export { WebGLGeometries };