WebGLObjects.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. */
  4. THREE.WebGLObjects = function ( gl, properties, info ) {
  5. var objects = {};
  6. var morphInfluences = new Float32Array( 8 );
  7. var geometries = new THREE.WebGLGeometries( gl, info );
  8. //
  9. function onObjectRemoved( event ) {
  10. var object = event.target;
  11. object.traverse( function ( child ) {
  12. child.removeEventListener( 'remove', onObjectRemoved );
  13. removeObject( child );
  14. } );
  15. }
  16. function removeObject( object ) {
  17. if ( object instanceof THREE.Mesh ||
  18. object instanceof THREE.PointCloud ||
  19. object instanceof THREE.Line ) {
  20. delete objects[ object.id ];
  21. }
  22. delete object._modelViewMatrix;
  23. delete object._normalMatrix;
  24. properties.delete( object );
  25. }
  26. function removeInstances( objlist, object ) {
  27. for ( var o = objlist.length - 1; o >= 0; o -- ) {
  28. if ( objlist[ o ].object === object ) {
  29. objlist.splice( o, 1 );
  30. }
  31. }
  32. }
  33. //
  34. this.objects = objects;
  35. this.geometries = geometries;
  36. this.init = function ( object ) {
  37. var objectProperties = properties.get( object );
  38. if ( objectProperties.__webglInit === undefined ) {
  39. objectProperties.__webglInit = true;
  40. object._modelViewMatrix = new THREE.Matrix4();
  41. object._normalMatrix = new THREE.Matrix3();
  42. object.addEventListener( 'removed', onObjectRemoved );
  43. }
  44. if ( objectProperties.__webglActive === undefined ) {
  45. objectProperties.__webglActive = true;
  46. if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.PointCloud ) {
  47. objects[ object.id ] = {
  48. id: object.id,
  49. object: object,
  50. z: 0
  51. };
  52. }
  53. }
  54. };
  55. function numericalSort ( a, b ) {
  56. return b[ 0 ] - a[ 0 ];
  57. }
  58. function updateObject( object ) {
  59. var geometry = geometries.get( object );
  60. if ( object.geometry.dynamic === true ) {
  61. geometry.updateFromObject( object );
  62. }
  63. // morph targets
  64. if ( object.morphTargetInfluences !== undefined ) {
  65. var activeInfluences = [];
  66. var morphTargetInfluences = object.morphTargetInfluences;
  67. for ( var i = 0, l = morphTargetInfluences.length; i < l; i ++ ) {
  68. var influence = morphTargetInfluences[ i ];
  69. activeInfluences.push( [ influence, i ] );
  70. }
  71. activeInfluences.sort( numericalSort );
  72. if ( activeInfluences.length > 8 ) {
  73. activeInfluences.length = 8;
  74. }
  75. for ( var i = 0, l = activeInfluences.length; i < l; i ++ ) {
  76. morphInfluences[ i ] = activeInfluences[ i ][ 0 ];
  77. var attribute = geometry.morphAttributes[ activeInfluences[ i ][ 1 ] ];
  78. geometry.addAttribute( 'morphTarget' + i, attribute );
  79. }
  80. var material = object.material;
  81. if ( material.program !== undefined ) {
  82. var uniforms = material.program.getUniforms();
  83. if ( uniforms.morphTargetInfluences !== null ) {
  84. gl.uniform1fv( uniforms.morphTargetInfluences, morphInfluences );
  85. }
  86. } else {
  87. console.warn( 'TOFIX: material.program is undefined' );
  88. }
  89. }
  90. //
  91. var attributes = geometry.attributes;
  92. for ( var name in attributes ) {
  93. updateAttribute( attributes[ name ], name );
  94. }
  95. }
  96. function updateAttribute ( attribute, name ) {
  97. var bufferType = ( name === 'index' ) ? gl.ELEMENT_ARRAY_BUFFER : gl.ARRAY_BUFFER;
  98. var data = ( attribute instanceof THREE.InterleavedBufferAttribute ) ? attribute.data : attribute;
  99. var attributeProperties = properties.get( data );
  100. if ( attributeProperties.__webglBuffer === undefined ) {
  101. createBuffer( attributeProperties, data, bufferType );
  102. } else if ( data.needsUpdate === true ) {
  103. updateBuffer( attributeProperties, data, bufferType );
  104. }
  105. }
  106. function createBuffer ( attributeProperties, data, bufferType ) {
  107. attributeProperties.__webglBuffer = gl.createBuffer();
  108. gl.bindBuffer( bufferType, attributeProperties.__webglBuffer );
  109. var usage = gl.STATIC_DRAW;
  110. if ( data instanceof THREE.DynamicBufferAttribute
  111. || ( data instanceof THREE.InstancedBufferAttribute && data.dynamic === true )
  112. || ( data instanceof THREE.InterleavedBuffer && data.dynamic === true ) ) {
  113. usage = gl.DYNAMIC_DRAW;
  114. }
  115. gl.bufferData( bufferType, data.array, usage );
  116. data.needsUpdate = false;
  117. }
  118. function updateBuffer( attributeProperties, data, bufferType ) {
  119. gl.bindBuffer( bufferType, attributeProperties.__webglBuffer );
  120. if ( data.updateRange === undefined || data.updateRange.count === -1 ) { // Not using update ranges
  121. gl.bufferSubData( bufferType, 0, data.array );
  122. } else if ( data.updateRange.count === 0 ) {
  123. console.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.' );
  124. } else {
  125. gl.bufferSubData( bufferType, data.updateRange.offset * data.array.BYTES_PER_ELEMENT,
  126. data.array.subarray( data.updateRange.offset, data.updateRange.offset + data.updateRange.count ) );
  127. data.updateRange.count = 0; // reset range
  128. }
  129. data.needsUpdate = false;
  130. }
  131. // returns the webgl buffer for a specified attribute
  132. this.getAttributeBuffer = function ( attribute ) {
  133. if ( attribute instanceof THREE.InterleavedBufferAttribute ) {
  134. return properties.get( attribute.data ).__webglBuffer;
  135. }
  136. return properties.get( attribute ).__webglBuffer;
  137. };
  138. this.update = function ( renderList ) {
  139. for ( var i = 0, ul = renderList.length; i < ul; i++ ) {
  140. var object = renderList[i].object;
  141. if ( object.material.visible !== false ) {
  142. updateObject( object );
  143. }
  144. }
  145. };
  146. this.clear = function () {
  147. objects = {};
  148. };
  149. };