babylon.bone.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. module BABYLON {
  2. export class Bone extends Node {
  3. public children = new Array<Bone>();
  4. public animations = new Array<Animation>();
  5. public length: number;
  6. private _skeleton: Skeleton;
  7. public _matrix: Matrix;
  8. private _restPose: Matrix;
  9. private _baseMatrix: Matrix;
  10. private _worldTransform = new Matrix();
  11. private _absoluteTransform = new Matrix();
  12. private _invertedAbsoluteTransform = new Matrix();
  13. private _parent: Bone;
  14. constructor(public name: string, skeleton: Skeleton, parentBone: Bone, matrix: Matrix, restPose?: Matrix) {
  15. super(name, skeleton.getScene());
  16. this._skeleton = skeleton;
  17. this._matrix = matrix;
  18. this._baseMatrix = matrix;
  19. this._restPose = restPose ? restPose : matrix.clone();
  20. skeleton.bones.push(this);
  21. if (parentBone) {
  22. this._parent = parentBone;
  23. parentBone.children.push(this);
  24. } else {
  25. this._parent = null;
  26. }
  27. this._updateDifferenceMatrix();
  28. }
  29. // Members
  30. public getParent(): Bone {
  31. return this._parent;
  32. }
  33. public getLocalMatrix(): Matrix {
  34. return this._matrix;
  35. }
  36. public getBaseMatrix(): Matrix {
  37. return this._baseMatrix;
  38. }
  39. public getRestPose(): Matrix {
  40. return this._restPose;
  41. }
  42. public returnToRest(): void {
  43. this.updateMatrix(this._restPose.clone());
  44. }
  45. public getWorldMatrix(): Matrix {
  46. return this._worldTransform;
  47. }
  48. public getInvertedAbsoluteTransform(): Matrix {
  49. return this._invertedAbsoluteTransform;
  50. }
  51. public getAbsoluteTransform(): Matrix {
  52. return this._absoluteTransform;
  53. }
  54. // Methods
  55. public updateMatrix(matrix: Matrix): void {
  56. this._baseMatrix = matrix.clone();
  57. this._matrix = matrix.clone();
  58. this._skeleton._markAsDirty();
  59. this._updateDifferenceMatrix();
  60. }
  61. public _updateDifferenceMatrix(rootMatrix?: Matrix): void {
  62. if (!rootMatrix) {
  63. rootMatrix = this._baseMatrix;
  64. }
  65. if (this._parent) {
  66. rootMatrix.multiplyToRef(this._parent._absoluteTransform, this._absoluteTransform);
  67. } else {
  68. this._absoluteTransform.copyFrom(rootMatrix);
  69. }
  70. this._absoluteTransform.invertToRef(this._invertedAbsoluteTransform);
  71. for (var index = 0; index < this.children.length; index++) {
  72. this.children[index]._updateDifferenceMatrix();
  73. }
  74. }
  75. public markAsDirty(): void {
  76. this._currentRenderId++;
  77. this._skeleton._markAsDirty();
  78. }
  79. public copyAnimationRange(source: Bone, rangeName: string, frameOffset: number, rescaleAsRequired = false): boolean {
  80. // all animation may be coming from a library skeleton, so may need to create animation
  81. if (this.animations.length === 0) {
  82. this.animations.push(new Animation(this.name, "_matrix", source.animations[0].framePerSecond, Animation.ANIMATIONTYPE_MATRIX, 0));
  83. this.animations[0].setKeys([]);
  84. }
  85. // get animation info / verify there is such a range from the source bone
  86. var sourceRange = source.animations[0].getRange(rangeName);
  87. if (!sourceRange) {
  88. return false;
  89. }
  90. var from = sourceRange.from;
  91. var to = sourceRange.to;
  92. var sourceKeys = source.animations[0].getKeys();
  93. // rescaling prep
  94. var sourceBoneLength = source.length;
  95. var scalingReqd = rescaleAsRequired && sourceBoneLength && this.length && sourceBoneLength !== this.length;
  96. var ratio = scalingReqd ? this.length / sourceBoneLength : null;
  97. var destKeys = this.animations[0].getKeys();
  98. // loop vars declaration / initialization
  99. var orig: { frame: number, value: Matrix };
  100. var origScale = scalingReqd ? Vector3.Zero() : null;
  101. var origRotation = scalingReqd ? new Quaternion() : null;
  102. var origTranslation = scalingReqd ? Vector3.Zero() : null;
  103. var mat: Matrix;
  104. for (var key = 0, nKeys = sourceKeys.length; key < nKeys; key++) {
  105. orig = sourceKeys[key];
  106. if (orig.frame >= from && orig.frame <= to) {
  107. if (scalingReqd) {
  108. orig.value.decompose(origScale, origRotation, origTranslation);
  109. origTranslation.scaleInPlace(ratio);
  110. mat = Matrix.Compose(origScale, origRotation, origTranslation);
  111. } else {
  112. mat = orig.value;
  113. }
  114. destKeys.push({ frame: orig.frame + frameOffset, value: mat });
  115. }
  116. }
  117. this.animations[0].createRange(rangeName, from + frameOffset, to + frameOffset);
  118. return true;
  119. }
  120. }
  121. }