/** * @author mrdoob / http://mrdoob.com/ */ import { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute'; import { WebGLGeometries } from './WebGLGeometries'; function WebGLObjects( gl, properties, info ) { var geometries = new WebGLGeometries( gl, properties, info ); // function update( object ) { // TODO: Avoid updating twice (when using shadowMap). Maybe add frame counter. var geometry = geometries.get( object ); if ( object.geometry.isGeometry ) { geometry.updateFromObject( object ); } var index = geometry.index; var attributes = geometry.attributes; if ( index !== null ) { updateAttribute( index, gl.ELEMENT_ARRAY_BUFFER ); } for ( var name in attributes ) { updateAttribute( attributes[ 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 ++ ) { updateAttribute( array[ i ], gl.ARRAY_BUFFER ); } } return geometry; } function updateAttribute( attribute, bufferType ) { var data = ( attribute.isInterleavedBufferAttribute ) ? attribute.data : attribute; var attributeProperties = properties.get( data ); if ( attributeProperties.__webglBuffer === undefined ) { createBuffer( attributeProperties, data, bufferType ); } else if ( attributeProperties.version !== data.version ) { updateBuffer( attributeProperties, data, bufferType ); } } function createBuffer( attributeProperties, data, bufferType ) { attributeProperties.__webglBuffer = gl.createBuffer(); gl.bindBuffer( bufferType, attributeProperties.__webglBuffer ); var usage = data.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW; gl.bufferData( bufferType, data.array, usage ); var type = gl.FLOAT; var array = data.array; if ( array instanceof Float32Array ) { type = gl.FLOAT; } else if ( array instanceof Float64Array ) { console.warn( "Unsupported data buffer format: Float64Array" ); } else if ( array instanceof Uint16Array ) { type = gl.UNSIGNED_SHORT; } else if ( array instanceof Int16Array ) { type = gl.SHORT; } else if ( array instanceof Uint32Array ) { type = gl.UNSIGNED_INT; } else if ( array instanceof Int32Array ) { type = gl.INT; } else if ( array instanceof Int8Array ) { type = gl.BYTE; } else if ( array instanceof Uint8Array ) { type = gl.UNSIGNED_BYTE; } attributeProperties.bytesPerElement = array.BYTES_PER_ELEMENT; attributeProperties.type = type; attributeProperties.version = data.version; data.onUploadCallback(); } function updateBuffer( attributeProperties, data, bufferType ) { gl.bindBuffer( bufferType, attributeProperties.__webglBuffer ); if ( data.dynamic === false ) { gl.bufferData( bufferType, data.array, gl.STATIC_DRAW ); } else if ( data.updateRange.count === - 1 ) { // Not using update ranges gl.bufferSubData( bufferType, 0, data.array ); } else if ( data.updateRange.count === 0 ) { console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' ); } else { gl.bufferSubData( bufferType, data.updateRange.offset * data.array.BYTES_PER_ELEMENT, data.array.subarray( data.updateRange.offset, data.updateRange.offset + data.updateRange.count ) ); data.updateRange.count = 0; // reset range } attributeProperties.version = data.version; } function getAttributeBuffer( attribute ) { if ( attribute.isInterleavedBufferAttribute ) { return properties.get( attribute.data ).__webglBuffer; } return properties.get( attribute ).__webglBuffer; } function getAttributeProperties( attribute ) { if ( attribute.isInterleavedBufferAttribute ) { return properties.get( attribute.data ); } return properties.get( attribute ); } function getWireframeAttribute( geometry ) { var property = properties.get( geometry ); if ( property.wireframe !== undefined ) { return property.wireframe; } var indices = []; var index = geometry.index; var attributes = geometry.attributes; // console.time( 'wireframe' ); if ( index !== null ) { var array = index.array; 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 = attributes.position.array; 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 ); } } // console.timeEnd( 'wireframe' ); var attribute = new ( Math.max.apply( Math, indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); updateAttribute( attribute, gl.ELEMENT_ARRAY_BUFFER ); property.wireframe = attribute; return attribute; } return { getAttributeBuffer: getAttributeBuffer, getAttributeProperties: getAttributeProperties, getWireframeAttribute: getWireframeAttribute, update: update }; } export { WebGLObjects };