WebGLObjects.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. */
  4. THREE.WebGLObjects = function ( gl, properties, info ) {
  5. var objects = {};
  6. var geometries = new THREE.WebGLGeometries( gl, properties, info );
  7. //
  8. function onObjectRemoved( event ) {
  9. var object = event.target;
  10. object.traverse( function ( child ) {
  11. child.removeEventListener( 'remove', onObjectRemoved );
  12. removeObject( child );
  13. } );
  14. }
  15. function removeObject( object ) {
  16. if ( object instanceof THREE.Mesh ||
  17. object instanceof THREE.PointCloud ||
  18. object instanceof THREE.Line ) {
  19. delete objects[ object.id ];
  20. }
  21. delete object._modelViewMatrix;
  22. delete object._normalMatrix;
  23. properties.delete( object );
  24. }
  25. //
  26. this.objects = objects;
  27. this.init = function ( object ) {
  28. var objectProperties = properties.get( object );
  29. if ( objectProperties.__webglInit === undefined ) {
  30. objectProperties.__webglInit = true;
  31. object._modelViewMatrix = new THREE.Matrix4();
  32. object._normalMatrix = new THREE.Matrix3();
  33. object.addEventListener( 'removed', onObjectRemoved );
  34. }
  35. if ( objectProperties.__webglActive === undefined ) {
  36. objectProperties.__webglActive = true;
  37. if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.PointCloud ) {
  38. objects[ object.id ] = {
  39. id: object.id,
  40. object: object,
  41. z: 0
  42. };
  43. }
  44. }
  45. };
  46. function update( object ) {
  47. // TODO: Avoid updating twice (when using shadowMap). Maybe add frame counter.
  48. var geometry = geometries.get( object );
  49. if ( object.geometry instanceof THREE.Geometry ) {
  50. geometry.updateFromObject( object );
  51. }
  52. var attributes = geometry.attributes;
  53. for ( var name in attributes ) {
  54. updateAttribute( attributes[ name ], name );
  55. }
  56. // morph targets
  57. var morphAttributes = geometry.morphAttributes;
  58. for ( var name in morphAttributes ) {
  59. var array = morphAttributes[ name ];
  60. for ( var i = 0, l = array.length; i < l; i ++ ) {
  61. updateAttribute( array[ i ], i );
  62. }
  63. }
  64. return geometry;
  65. }
  66. function updateAttribute( attribute, name ) {
  67. var bufferType;
  68. if ( name === 'index' || name === 'wireframe' ) {
  69. bufferType = gl.ELEMENT_ARRAY_BUFFER;
  70. } else {
  71. bufferType = gl.ARRAY_BUFFER;
  72. }
  73. var data = ( attribute instanceof THREE.InterleavedBufferAttribute ) ? attribute.data : attribute;
  74. var attributeProperties = properties.get( data );
  75. if ( attributeProperties.__webglBuffer === undefined ) {
  76. createBuffer( attributeProperties, data, bufferType );
  77. } else if ( attributeProperties.version !== data.version ) {
  78. updateBuffer( attributeProperties, data, bufferType );
  79. }
  80. }
  81. function createBuffer( attributeProperties, data, bufferType ) {
  82. attributeProperties.__webglBuffer = gl.createBuffer();
  83. gl.bindBuffer( bufferType, attributeProperties.__webglBuffer );
  84. var usage = gl.STATIC_DRAW;
  85. if ( data instanceof THREE.DynamicBufferAttribute
  86. || ( data instanceof THREE.InstancedBufferAttribute && data.dynamic === true )
  87. || ( data instanceof THREE.InterleavedBuffer && data.dynamic === true ) ) {
  88. usage = gl.DYNAMIC_DRAW;
  89. }
  90. gl.bufferData( bufferType, data.array, usage );
  91. attributeProperties.version = data.version;
  92. }
  93. function updateBuffer( attributeProperties, data, bufferType ) {
  94. gl.bindBuffer( bufferType, attributeProperties.__webglBuffer );
  95. if ( data.updateRange === undefined || data.updateRange.count === - 1 ) {
  96. // Not using update ranges
  97. gl.bufferSubData( bufferType, 0, data.array );
  98. } else if ( data.updateRange.count === 0 ) {
  99. console.error( 'THREE.WebGLObjects.updateBuffer: using updateRange for THREE.DynamicBufferAttribute and marked as needsUpdate but count is 0, ensure you are using set methods or updating manually.' );
  100. } else {
  101. gl.bufferSubData( bufferType, data.updateRange.offset * data.array.BYTES_PER_ELEMENT,
  102. data.array.subarray( data.updateRange.offset, data.updateRange.offset + data.updateRange.count ) );
  103. data.updateRange.count = 0; // reset range
  104. }
  105. attributeProperties.version = data.version;
  106. }
  107. // returns the webgl buffer for a specified attribute
  108. this.getAttributeBuffer = function ( attribute ) {
  109. if ( attribute instanceof THREE.InterleavedBufferAttribute ) {
  110. return properties.get( attribute.data ).__webglBuffer;
  111. }
  112. return properties.get( attribute ).__webglBuffer;
  113. };
  114. this.update = update;
  115. this.updateAttribute = updateAttribute;
  116. this.clear = function () {
  117. objects = {};
  118. };
  119. };