/** * @author mrdoob / http://mrdoob.com/ */ import { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute.js'; import { BufferGeometry } from '../../core/BufferGeometry.js'; import { arrayMax } from '../../utils.js'; function WebGLGeometries( gl, attributes, info ) { var geometries = new WeakMap(); var wireframeAttributes = new WeakMap(); function onGeometryDispose( event ) { var geometry = event.target; var buffergeometry = geometries.get( geometry ); if ( buffergeometry.index !== null ) { attributes.remove( buffergeometry.index ); } for ( var name in buffergeometry.attributes ) { attributes.remove( buffergeometry.attributes[ name ] ); } geometry.removeEventListener( 'dispose', onGeometryDispose ); geometries.delete( geometry ); var attribute = wireframeAttributes.get( buffergeometry ); if ( attribute ) { attributes.remove( attribute ); wireframeAttributes.delete( buffergeometry ); } // info.memory.geometries --; } function get( object, geometry ) { var buffergeometry = geometries.get( geometry ); if ( buffergeometry ) return buffergeometry; geometry.addEventListener( 'dispose', onGeometryDispose ); if ( geometry.isBufferGeometry ) { buffergeometry = geometry; } else if ( geometry.isGeometry ) { if ( geometry._bufferGeometry === undefined ) { geometry._bufferGeometry = new BufferGeometry().setFromObject( object ); } buffergeometry = geometry._bufferGeometry; } geometries.set( geometry, buffergeometry ); info.memory.geometries ++; return buffergeometry; } function update( geometry ) { var index = geometry.index; var geometryAttributes = geometry.attributes; if ( index !== null ) { attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); } for ( var name in geometryAttributes ) { attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); } // morph targets var morphAttributes = geometry.morphAttributes; for ( var name in morphAttributes ) { var array = morphAttributes[ name ]; for ( var i = 0, l = array.length; i < l; i ++ ) { attributes.update( array[ i ], gl.ARRAY_BUFFER ); } } } function updateWireframeAttribute( geometry ) { var indices = []; var geometryIndex = geometry.index; var geometryPosition = geometry.attributes.position; var version = 0; if ( geometryIndex !== null ) { var array = geometryIndex.array; version = geometryIndex.version; for ( var i = 0, l = array.length; i < l; i += 3 ) { var a = array[ i + 0 ]; var b = array[ i + 1 ]; var c = array[ i + 2 ]; indices.push( a, b, b, c, c, a ); } } else { var array = geometryPosition.array; version = geometryPosition.version; for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { var a = i + 0; var b = i + 1; var c = i + 2; indices.push( a, b, b, c, c, a ); } } var attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); attribute.version = version; attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER ); // var previousAttribute = wireframeAttributes.get( geometry ); if ( previousAttribute ) attributes.remove( previousAttribute ); // wireframeAttributes.set( geometry, attribute ); } function getWireframeAttribute( geometry ) { var currentAttribute = wireframeAttributes.get( geometry ); if ( currentAttribute ) { var 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 ); } return { get: get, update: update, getWireframeAttribute: getWireframeAttribute }; } export { WebGLGeometries };