WebGLObjects.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. */
  4. THREE.WebGLObjects = function ( gl, info ) {
  5. var objects = {};
  6. var objectsImmediate = [];
  7. var geometries = {};
  8. var geometryGroups = {};
  9. var geometryGroupCounter = 0;
  10. //
  11. function onObjectRemoved( event ) {
  12. var object = event.target;
  13. object.traverse( function ( child ) {
  14. child.removeEventListener( 'remove', onObjectRemoved );
  15. removeObject( child );
  16. } );
  17. }
  18. function removeObject( object ) {
  19. if ( object instanceof THREE.Mesh ||
  20. object instanceof THREE.PointCloud ||
  21. object instanceof THREE.Line ) {
  22. delete objects[ object.id ];
  23. } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
  24. removeInstances( objectsImmediate, object );
  25. }
  26. delete object.__webglInit;
  27. delete object._modelViewMatrix;
  28. delete object._normalMatrix;
  29. delete object.__webglActive;
  30. }
  31. function removeInstances( objlist, object ) {
  32. for ( var o = objlist.length - 1; o >= 0; o -- ) {
  33. if ( objlist[ o ].object === object ) {
  34. objlist.splice( o, 1 );
  35. }
  36. }
  37. }
  38. //
  39. function onGeometryDispose( event ) {
  40. var geometry = event.target;
  41. geometry.removeEventListener( 'dispose', onGeometryDispose );
  42. deallocateGeometry( geometries[ geometry.id ] );
  43. }
  44. function deallocateGeometry( geometry ) {
  45. for ( var name in geometry.attributes ) {
  46. var attribute = geometry.attributes[ name ];
  47. if ( attribute.buffer !== undefined ) {
  48. gl.deleteBuffer( attribute.buffer );
  49. delete attribute.buffer;
  50. }
  51. }
  52. info.memory.geometries --;
  53. }
  54. //
  55. this.objects = objects;
  56. this.objectsImmediate = objectsImmediate;
  57. this.init = function ( object ) {
  58. if ( object.__webglInit === undefined ) {
  59. object.__webglInit = true;
  60. object._modelViewMatrix = new THREE.Matrix4();
  61. object._normalMatrix = new THREE.Matrix3();
  62. object.addEventListener( 'removed', onObjectRemoved );
  63. }
  64. var geometry = object.geometry;
  65. if ( geometry === undefined ) {
  66. // ImmediateRenderObject
  67. } else if ( geometries[ geometry.id ] === undefined ) {
  68. geometry.addEventListener( 'dispose', onGeometryDispose );
  69. if ( geometry instanceof THREE.BufferGeometry ) {
  70. geometries[ geometry.id ] = geometry;
  71. info.memory.geometries ++;
  72. } else {
  73. var bufferGeometry = new THREE.BufferGeometry().fromObject( object );
  74. geometries[ geometry.id ] = bufferGeometry;
  75. console.log( 'THREE.WebGLObjects: Converting...', object, bufferGeometry );
  76. info.memory.geometries ++;
  77. }
  78. }
  79. if ( object.__webglActive === undefined) {
  80. object.__webglActive = true;
  81. if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.PointCloud ) {
  82. objects[ object.id ] = {
  83. id: object.id,
  84. buffer: geometries[ geometry.id ],
  85. object: object,
  86. material: null,
  87. z: 0
  88. };
  89. } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
  90. objectsImmediate.push( {
  91. id: null,
  92. object: object,
  93. opaque: null,
  94. transparent: null,
  95. z: 0
  96. } );
  97. }
  98. }
  99. };
  100. this.update = function ( object ) {
  101. var geometry = object.geometry;
  102. if ( geometry instanceof THREE.Geometry ) {
  103. var bufferGeometry = geometries[ geometry.id ];
  104. if ( geometry.verticesNeedUpdate === true ) {
  105. var attribute = bufferGeometry.attributes.position;
  106. attribute.copyVector3sArray( geometry.vertices );
  107. attribute.needsUpdate = true;
  108. geometry.verticesNeedUpdate = false;
  109. }
  110. if ( geometry.colorsNeedUpdate === true ) {
  111. var attribute = bufferGeometry.attributes.color;
  112. attribute.copyColorsArray( geometry.colors );
  113. attribute.needsUpdate = true;
  114. geometry.colorsNeedUpdate = false;
  115. }
  116. geometry = bufferGeometry;
  117. }
  118. //
  119. if ( geometry instanceof THREE.BufferGeometry ) {
  120. var attributes = geometry.attributes;
  121. var attributesKeys = geometry.attributesKeys;
  122. for ( var i = 0, l = attributesKeys.length; i < l; i ++ ) {
  123. var key = attributesKeys[ i ];
  124. var attribute = attributes[ key ];
  125. var bufferType = ( key === 'index' ) ? gl.ELEMENT_ARRAY_BUFFER : gl.ARRAY_BUFFER;
  126. var data = ( attribute instanceof THREE.InterleavedBufferAttribute ) ? attribute.data : attribute;
  127. if ( data.buffer === undefined ) {
  128. data.buffer = gl.createBuffer();
  129. gl.bindBuffer( bufferType, data.buffer );
  130. var usage = gl.STATIC_DRAW;
  131. if ( data instanceof THREE.DynamicBufferAttribute
  132. || ( data instanceof THREE.InstancedBufferAttribute && data.dynamic === true )
  133. || ( data instanceof THREE.InterleavedBuffer && data.dynamic === true ) ) {
  134. usage = gl.DYNAMIC_DRAW;
  135. }
  136. gl.bufferData( bufferType, data.array, usage );
  137. data.needsUpdate = false;
  138. } else if ( data.needsUpdate === true ) {
  139. gl.bindBuffer( bufferType, data.buffer );
  140. if ( data.updateRange === undefined || data.updateRange.count === -1 ) { // Not using update ranges
  141. gl.bufferSubData( bufferType, 0, data.array );
  142. } else if ( data.updateRange.count === 0 ) {
  143. THREE.error( 'THREE.WebGLRenderer.updateObject: using updateRange for THREE.DynamicBufferAttribute and marked as needsUpdate but count is 0, ensure you are using set methods or updating manually.' );
  144. } else {
  145. gl.bufferSubData( bufferType, data.updateRange.offset * data.array.BYTES_PER_ELEMENT,
  146. data.array.subarray( data.updateRange.offset, data.updateRange.offset + data.updateRange.count ) );
  147. data.updateRange.count = 0; // reset range
  148. }
  149. data.needsUpdate = false;
  150. }
  151. }
  152. }
  153. };
  154. };