SkinnedMesh.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /**
  2. * @author mikael emtinger / http://gomo.se/
  3. * @author alteredq / http://alteredqualia.com/
  4. * @author ikerr / http://verold.com
  5. */
  6. THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) {
  7. THREE.Mesh.call( this, geometry, material );
  8. this.type = 'SkinnedMesh';
  9. this.bindMode = "attached";
  10. this.bindMatrix = new THREE.Matrix4();
  11. this.bindMatrixInverse = new THREE.Matrix4();
  12. // init bones
  13. // TODO: remove bone creation as there is no reason (other than
  14. // convenience) for THREE.SkinnedMesh to do this.
  15. var bones = [];
  16. if ( this.geometry && this.geometry.bones !== undefined ) {
  17. var bone, gbone, p, q, s;
  18. for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
  19. gbone = this.geometry.bones[ b ];
  20. p = gbone.pos;
  21. q = gbone.rotq;
  22. s = gbone.scl;
  23. bone = new THREE.Bone( this );
  24. bones.push( bone );
  25. bone.name = gbone.name;
  26. bone.position.set( p[ 0 ], p[ 1 ], p[ 2 ] );
  27. bone.quaternion.set( q[ 0 ], q[ 1 ], q[ 2 ], q[ 3 ] );
  28. if ( s !== undefined ) {
  29. bone.scale.set( s[ 0 ], s[ 1 ], s[ 2 ] );
  30. } else {
  31. bone.scale.set( 1, 1, 1 );
  32. }
  33. }
  34. for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
  35. gbone = this.geometry.bones[ b ];
  36. if ( gbone.parent !== - 1 ) {
  37. bones[ gbone.parent ].add( bones[ b ] );
  38. } else {
  39. this.add( bones[ b ] );
  40. }
  41. }
  42. }
  43. this.normalizeSkinWeights();
  44. this.updateMatrixWorld( true );
  45. this.bind( new THREE.Skeleton( bones, undefined, useVertexTexture ) );
  46. };
  47. THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype );
  48. THREE.SkinnedMesh.prototype.constructor = THREE.SkinnedMesh;
  49. THREE.SkinnedMesh.prototype.bind = function( skeleton, bindMatrix ) {
  50. this.skeleton = skeleton;
  51. if ( bindMatrix === undefined ) {
  52. this.updateMatrixWorld( true );
  53. bindMatrix = this.matrixWorld;
  54. }
  55. this.bindMatrix.copy( bindMatrix );
  56. this.bindMatrixInverse.getInverse( bindMatrix );
  57. };
  58. THREE.SkinnedMesh.prototype.pose = function () {
  59. this.skeleton.pose();
  60. };
  61. THREE.SkinnedMesh.prototype.normalizeSkinWeights = function () {
  62. if ( this.geometry instanceof THREE.Geometry ) {
  63. for ( var i = 0; i < this.geometry.skinIndices.length; i ++ ) {
  64. var sw = this.geometry.skinWeights[ i ];
  65. var scale = 1.0 / sw.lengthManhattan();
  66. if ( scale !== Infinity ) {
  67. sw.multiplyScalar( scale );
  68. } else {
  69. sw.set( 1 ); // this will be normalized by the shader anyway
  70. }
  71. }
  72. } else {
  73. // skinning weights assumed to be normalized for THREE.BufferGeometry
  74. }
  75. };
  76. THREE.SkinnedMesh.prototype.updateMatrixWorld = function( force ) {
  77. THREE.Mesh.prototype.updateMatrixWorld.call( this, true );
  78. if ( this.bindMode === "attached" ) {
  79. this.bindMatrixInverse.getInverse( this.matrixWorld );
  80. } else if ( this.bindMode === "detached" ) {
  81. this.bindMatrixInverse.getInverse( this.bindMatrix );
  82. } else {
  83. console.warn( 'THREE.SkinnedMesh unrecognized bindMode: ' + this.bindMode );
  84. }
  85. };
  86. THREE.SkinnedMesh.prototype.clone = function() {
  87. var skinMesh = new THREE.SkinnedMesh( this.geometry, this.material, this.useVertexTexture );
  88. return skinMesh.copy( this );
  89. };
  90. THREE.SkinnedMesh.prototype.copy = function( source ) {
  91. THREE.Mesh.prototype.copy.call( this, source );
  92. return this;
  93. };