SkinnedMesh.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /**
  2. * @author mikael emtinger / http://gomo.se/
  3. * @author alteredq / http://alteredqualia.com/
  4. */
  5. THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) {
  6. THREE.Mesh.call( this, geometry, material );
  7. this.skeleton = new THREE.Skeleton( this.geometry && this.geometry.bones, useVertexTexture );
  8. // Add root level bones as children of the mesh
  9. for ( var b = 0; b < this.skeleton.bones.length; ++b ) {
  10. var bone = this.skeleton.bones[ b ];
  11. if ( bone.parent === undefined ) {
  12. this.add( bone );
  13. }
  14. }
  15. this.identityMatrix = new THREE.Matrix4();
  16. this.pose();
  17. };
  18. THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype );
  19. THREE.SkinnedMesh.prototype.updateMatrixWorld = function () {
  20. var offsetMatrix = new THREE.Matrix4();
  21. return function ( force ) {
  22. this.matrixAutoUpdate && this.updateMatrix();
  23. // update matrixWorld
  24. if ( this.matrixWorldNeedsUpdate || force ) {
  25. if ( this.parent ) {
  26. this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
  27. } else {
  28. this.matrixWorld.copy( this.matrix );
  29. }
  30. this.matrixWorldNeedsUpdate = false;
  31. force = true;
  32. }
  33. // update children
  34. for ( var i = 0, l = this.children.length; i < l; i ++ ) {
  35. var child = this.children[ i ];
  36. if ( child instanceof THREE.Bone ) {
  37. child.update( this.identityMatrix, false );
  38. } else {
  39. child.updateMatrixWorld( true );
  40. }
  41. }
  42. // make a snapshot of the bones' rest position
  43. if ( this.skeleton.boneInverses === undefined ) {
  44. this.skeleton.calculateInverses();
  45. }
  46. // flatten bone matrices to array
  47. for ( var b = 0, bl = this.skeleton.bones.length; b < bl; b ++ ) {
  48. // compute the offset between the current and the original transform;
  49. // TODO: we could get rid of this multiplication step if the skinMatrix
  50. // was already representing the offset; however, this requires some
  51. // major changes to the animation system
  52. offsetMatrix.multiplyMatrices( this.skeleton.bones[ b ].skinMatrix, this.skeleton.boneInverses[ b ] );
  53. offsetMatrix.flattenToArrayOffset( this.skeleton.boneMatrices, b * 16 );
  54. }
  55. if ( this.skeleton.useVertexTexture ) {
  56. this.skeleton.boneTexture.needsUpdate = true;
  57. }
  58. };
  59. }();
  60. THREE.SkinnedMesh.prototype.pose = function () {
  61. this.updateMatrixWorld( true );
  62. this.normalizeSkinWeights();
  63. };
  64. THREE.SkinnedMesh.prototype.normalizeSkinWeights = function () {
  65. if ( this.geometry instanceof THREE.Geometry ) {
  66. for ( var i = 0; i < this.geometry.skinIndices.length; i ++ ) {
  67. var sw = this.geometry.skinWeights[ i ];
  68. var scale = 1.0 / sw.lengthManhattan();
  69. if ( scale !== Infinity ) {
  70. sw.multiplyScalar( scale );
  71. } else {
  72. sw.set( 1 ); // this will be normalized by the shader anyway
  73. }
  74. }
  75. } else {
  76. // skinning weights assumed to be normalized for THREE.BufferGeometry
  77. }
  78. };
  79. THREE.SkinnedMesh.prototype.clone = function ( object ) {
  80. if ( object === undefined ) {
  81. object = new THREE.SkinnedMesh( this.geometry, this.material, this.useVertexTexture );
  82. }
  83. THREE.Mesh.prototype.clone.call( this, object );
  84. return object;
  85. };