Pārlūkot izejas kodu

added options param to BoneIKController; poleTarget now defaults to parent bone; added option for poleTargetBone; added option for poleTargetLocalOffset; added option for bendAxis; fixed issue when mesh is scaled

Adam Bowman 8 gadi atpakaļ
vecāks
revīzija
92b17371d6
1 mainītis faili ar 87 papildinājumiem un 37 dzēšanām
  1. 87 37
      src/Bones/babylon.boneIKController.ts

+ 87 - 37
src/Bones/babylon.boneIKController.ts

@@ -1,9 +1,16 @@
 module BABYLON {
     export class BoneIKController {
 
-        public target: AbstractMesh;
-        public poleTarget: AbstractMesh;
+        public targetMesh: AbstractMesh;
+        public poleTargetMesh: AbstractMesh;
+        public poleTargetBone: Bone;
+
+        public targetPosition = Vector3.Zero();
+        public poleTargetPosition = Vector3.Zero();
+        
+        public poleTargetLocalOffset = Vector3.Zero();
         public poleAngle = 0;
+
         public mesh: AbstractMesh;
 
         private _bone1: Bone;
@@ -24,6 +31,8 @@ module BABYLON {
 
         private _rightHandedSystem = false;
 
+        private _bendAxis = Vector3.Right();
+
         get maxAngle(): number {
 
             return this._maxAngle;
@@ -36,21 +45,18 @@ module BABYLON {
 
         }
 
-        constructor(mesh: AbstractMesh, bone: Bone, target: AbstractMesh, poleTarget: AbstractMesh, poleAngle: number = 0){
-
-            target.computeWorldMatrix(true);
-            poleTarget.computeWorldMatrix(true);
+        constructor(mesh: AbstractMesh, bone: Bone, options?: { targetMesh?: AbstractMesh, poleTargetMesh?: AbstractMesh, poleTargetBone?: Bone, poleTargetLocalOffset?:Vector3, poleAngle?: number, bendAxis?: Vector3, maxAngle?:number }){
 
             this._bone2 = bone;
             this._bone1 = bone.getParent();
 
-            this.target = target;
-            this.poleTarget = poleTarget;
-            this.poleAngle = poleAngle;
             this.mesh = mesh;
 
-            if(bone.getAbsoluteTransform().determinant() > 0){
+             if(bone.getAbsoluteTransform().determinant() > 0){
                 this._rightHandedSystem = true;
+                this._bendAxis.x = 0;
+                this._bendAxis.y = 0;
+                this._bendAxis.z = 1;
             }
 
             if (this._bone1.length) {
@@ -58,8 +64,8 @@ module BABYLON {
                 var boneScale1 = this._bone1.getScale();
                 var boneScale2 = this._bone2.getScale();
                 
-                this._bone1Length = this._bone1.length * boneScale1.y;
-                this._bone2Length = this._bone2.length * boneScale2.y;
+                this._bone1Length = this._bone1.length * boneScale1.y * this.mesh.scaling.y;
+                this._bone2Length = this._bone2.length * boneScale2.y * this.mesh.scaling.y;
 
             } else if (this._bone1.children[0]) {
             
@@ -75,6 +81,46 @@ module BABYLON {
             }
 
             this.maxAngle = Math.PI;
+            
+            if(options){
+
+                if(options.targetMesh){
+                    this.targetMesh = options.targetMesh;
+                    this.targetMesh.computeWorldMatrix(true);
+                }
+
+                if(options.poleTargetMesh){
+
+                    this.poleTargetMesh = options.poleTargetMesh;
+                    this.poleTargetMesh.computeWorldMatrix(true);
+
+                }else if(options.poleTargetBone){
+
+                    this.poleTargetBone = options.poleTargetBone;
+
+                }else if(this._bone1.getParent()){
+
+                    this.poleTargetBone = this._bone1.getParent();
+
+                }
+
+                if(options.poleTargetLocalOffset){
+                    this.poleTargetLocalOffset.copyFrom(options.poleTargetLocalOffset);
+                }
+
+                if(options.poleAngle){
+                    this.poleAngle = options.poleAngle;
+                }
+
+                if(options.bendAxis){
+                    this._bendAxis.copyFrom(options.bendAxis);
+                }
+
+                if(options.maxAngle){
+                    this.maxAngle = options.maxAngle;
+                }
+
+            }
 
         }
 
@@ -100,17 +146,28 @@ module BABYLON {
         public update (): void {
 	
             var bone1 = this._bone1;
-            var target = this.target.getAbsolutePosition();
-            var poleTarget = this.poleTarget.getAbsolutePosition();
+            var target = this.targetPosition;
+            var poleTarget = this.poleTargetPosition;
+
+            var mat1 = this._tmpMat1;
+            var mat2 = this._tmpMat2;
+
+            if(this.targetMesh){
+                target.copyFrom(this.targetMesh.getAbsolutePosition());
+            }
+
+            if(this.poleTargetBone){
+                this.poleTargetBone.getAbsolutePositionFromLocalToRef(this.poleTargetLocalOffset, this.mesh, poleTarget);
+            }else if(this.poleTargetMesh){
+                Vector3.TransformCoordinatesToRef(this.poleTargetLocalOffset, this.poleTargetMesh.getWorldMatrix(), poleTarget);
+            }
 
             var bonePos = this._tmpVec1;
             var zaxis = this._tmpVec2;
             var xaxis = this._tmpVec3;
             var yaxis = this._tmpVec4;
             var upAxis = this._tmpVec5;
-            var mat1 = this._tmpMat1;
-            var mat2 = this._tmpMat2;
-
+            
             bone1.getAbsolutePositionToRef(this.mesh, bonePos);
 
             poleTarget.subtractToRef(bonePos, upAxis);
@@ -165,38 +222,31 @@ module BABYLON {
 
             var angC = -angA - angB;
 
-            
-            var bendAxis = this._tmpVec1;
-            bendAxis.x = 0;
-            bendAxis.y = 0;
-            bendAxis.z = 0;
-
             if (this._rightHandedSystem) {
 
-                bendAxis.z = 1;
+                Matrix.RotationYawPitchRollToRef(0, 0, Math.PI * .5, mat2);
+                mat2.multiplyToRef(mat1, mat1);
 
-                Matrix.RotationYawPitchRollToRef(0, 0, angB + Math.PI*.5, mat2);
+                Matrix.RotationAxisToRef(this._bendAxis, angB, mat2);
                 mat2.multiplyToRef(mat1, mat1);
-                
-                Matrix.RotationAxisToRef(yaxis, this.poleAngle + Math.PI, mat2);
-                mat1.multiplyToRef(mat2, mat1);
 
-            } else {
+            }else {
 
-                bendAxis.x = 1;
+                this._tmpVec1.copyFrom(this._bendAxis);
+                this._tmpVec1.x *= -1;
 
-                Matrix.RotationYawPitchRollToRef(0, angB, 0, mat2);
+                Matrix.RotationAxisToRef(this._tmpVec1, -angB, mat2);
                 mat2.multiplyToRef(mat1, mat1);
+                
+            }
 
-                if (this.poleAngle) {
-                    Matrix.RotationAxisToRef(yaxis, this.poleAngle, mat2);
-                    mat1.multiplyToRef(mat2, mat1);
-                }
-
+            if (this.poleAngle) {
+                Matrix.RotationAxisToRef(yaxis, this.poleAngle, mat2);
+                mat1.multiplyToRef(mat2, mat1);
             }
 
             this._bone1.setRotationMatrix(mat1, Space.WORLD, this.mesh);
-            this._bone2.setAxisAngle(bendAxis, angC, Space.LOCAL);
+            this._bone2.setAxisAngle(this._bendAxis, angC, Space.LOCAL);
 
         }