WebGLObjects.js 5.2 KB

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