Browse Source

DynamicBones: backend v0.1 ok

lviguier 7 months ago
parent
commit
a19841c8f8
5 changed files with 158 additions and 121 deletions
  1. 93 88
      h3d/anim/BufferAnimation.hx
  2. 7 3
      h3d/anim/Skin.hx
  3. 48 25
      h3d/scene/Skin.hx
  4. 9 4
      hxd/fmt/fbx/HMDOut.hx
  5. 1 1
      hxd/fmt/hmd/Library.hx

+ 93 - 88
h3d/anim/BufferAnimation.hx

@@ -165,46 +165,98 @@ class BufferAnimation extends Animation {
 
 			var m = o.matrix;
 			if( m != null ) {
+				var dynJoint = Std.downcast(o.targetSkin.getSkinData().allJoints[o.targetJoint], h3d.anim.Skin.DynamicJoint);
+				if (dynJoint == null) {
+					if( layout.has(Position) ) {
+						m._41 = lerpValue();
+						m._42 = lerpValue();
+						m._43 = lerpValue();
+					} else {
+						m._41 = m._14;
+						m._42 = m._24;
+						m._43 = m._34;
+					}
 
-				if( layout.has(Position) ) {
-					m._41 = lerpValue();
-					m._42 = lerpValue();
-					m._43 = lerpValue();
-				} else {
-					m._41 = m._14;
-					m._42 = m._24;
-					m._43 = m._34;
-				}
+					if( layout.has(Rotation) ) {
+						var q1x : Float32 = data[offset1++];
+						var q1y : Float32 = data[offset1++];
+						var q1z : Float32 = data[offset1++];
+						var q1w : Float32 = Math.sqrt(hxd.Math.abs(1 - (q1x*q1x+q1y*q1y+q1z*q1z)));
+						var q2x : Float32 = data[offset2++];
+						var q2y : Float32 = data[offset2++];
+						var q2z : Float32 = data[offset2++];
+						var q2w : Float32 = Math.sqrt(hxd.Math.abs(1 - (q2x*q2x+q2y*q2y+q2z*q2z)));
+
+						// qlerp nearest
+						var dot = q1x * q2x + q1y * q2y + q1z * q2z + q1w * q2w;
+						var q2 = dot < 0 ? -k2 : k2;
+						var qx = q1x * k1 + q2x * q2;
+						var qy = q1y * k1 + q2y * q2;
+						var qz = q1z * k1 + q2z * q2;
+						var qw = q1w * k1 + q2w * q2;
+						// make sure the resulting quaternion is normalized
+						var ql = 1 / Math.sqrt(qx * qx + qy * qy + qz * qz + qw * qw);
+						qx *= ql;
+						qy *= ql;
+						qz *= ql;
+						qw *= ql;
+
+						if( decompose ) {
+							m._12 = qx;
+							m._13 = qy;
+							m._21 = qz;
+							m._23 = qw;
+							if( layout.has(Scale) ) {
+								m._11 = lerpValue();
+								m._22 = lerpValue();
+								m._33 = lerpValue();
+							} else {
+								m._11 = 1;
+								m._22 = 1;
+								m._33 = 1;
+							}
+						} else {
+							// quaternion to matrix
+							var xx = qx * qx;
+							var xy = qx * qy;
+							var xz = qx * qz;
+							var xw = qx * qw;
+							var yy = qy * qy;
+							var yz = qy * qz;
+							var yw = qy * qw;
+							var zz = qz * qz;
+							var zw = qz * qw;
+							m._11 = 1 - 2 * ( yy + zz );
+							m._12 = 2 * ( xy + zw );
+							m._13 = 2 * ( xz - yw );
+							m._21 = 2 * ( xy - zw );
+							m._22 = 1 - 2 * ( xx + zz );
+							m._23 = 2 * ( yz + xw );
+							m._31 = 2 * ( xz + yw );
+							m._32 = 2 * ( yz - xw );
+							m._33 = 1 - 2 * ( xx + yy );
+							if( layout.has(Scale) ) {
+								var sx = lerpValue();
+								var sy = lerpValue();
+								var sz = lerpValue();
+								m._11 *= sx;
+								m._12 *= sx;
+								m._13 *= sx;
+								m._21 *= sy;
+								m._22 *= sy;
+								m._23 *= sy;
+								m._31 *= sz;
+								m._32 *= sz;
+								m._33 *= sz;
+							}
+						}
+
+					} else {
+						m._12 = 0;
+						m._13 = 0;
+						m._21 = 0;
+						m._23 = decompose ? 1 : 0;
 
-				if( layout.has(Rotation) ) {
-					var q1x : Float32 = data[offset1++];
-					var q1y : Float32 = data[offset1++];
-					var q1z : Float32 = data[offset1++];
-					var q1w : Float32 = Math.sqrt(hxd.Math.abs(1 - (q1x*q1x+q1y*q1y+q1z*q1z)));
-					var q2x : Float32 = data[offset2++];
-					var q2y : Float32 = data[offset2++];
-					var q2z : Float32 = data[offset2++];
-					var q2w : Float32 = Math.sqrt(hxd.Math.abs(1 - (q2x*q2x+q2y*q2y+q2z*q2z)));
-
-					// qlerp nearest
-					var dot = q1x * q2x + q1y * q2y + q1z * q2z + q1w * q2w;
-					var q2 = dot < 0 ? -k2 : k2;
-					var qx = q1x * k1 + q2x * q2;
-					var qy = q1y * k1 + q2y * q2;
-					var qz = q1z * k1 + q2z * q2;
-					var qw = q1w * k1 + q2w * q2;
-					// make sure the resulting quaternion is normalized
-					var ql = 1 / Math.sqrt(qx * qx + qy * qy + qz * qz + qw * qw);
-					qx *= ql;
-					qy *= ql;
-					qz *= ql;
-					qw *= ql;
-
-					if( decompose ) {
-						m._12 = qx;
-						m._13 = qy;
-						m._21 = qz;
-						m._23 = qw;
 						if( layout.has(Scale) ) {
 							m._11 = lerpValue();
 							m._22 = lerpValue();
@@ -214,58 +266,11 @@ class BufferAnimation extends Animation {
 							m._22 = 1;
 							m._33 = 1;
 						}
-					} else {
-						// quaternion to matrix
-						var xx = qx * qx;
-						var xy = qx * qy;
-						var xz = qx * qz;
-						var xw = qx * qw;
-						var yy = qy * qy;
-						var yz = qy * qz;
-						var yw = qy * qw;
-						var zz = qz * qz;
-						var zw = qz * qw;
-						m._11 = 1 - 2 * ( yy + zz );
-						m._12 = 2 * ( xy + zw );
-						m._13 = 2 * ( xz - yw );
-						m._21 = 2 * ( xy - zw );
-						m._22 = 1 - 2 * ( xx + zz );
-						m._23 = 2 * ( yz + xw );
-						m._31 = 2 * ( xz + yw );
-						m._32 = 2 * ( yz - xw );
-						m._33 = 1 - 2 * ( xx + yy );
-						if( layout.has(Scale) ) {
-							var sx = lerpValue();
-							var sy = lerpValue();
-							var sz = lerpValue();
-							m._11 *= sx;
-							m._12 *= sx;
-							m._13 *= sx;
-							m._21 *= sy;
-							m._22 *= sy;
-							m._23 *= sy;
-							m._31 *= sz;
-							m._32 *= sz;
-							m._33 *= sz;
-						}
-					}
-
-				} else {
-					m._12 = 0;
-					m._13 = 0;
-					m._21 = 0;
-					m._23 = decompose ? 1 : 0;
-
-					if( layout.has(Scale) ) {
-						m._11 = lerpValue();
-						m._22 = lerpValue();
-						m._33 = lerpValue();
-					} else {
-						m._11 = 1;
-						m._22 = 1;
-						m._33 = 1;
 					}
 				}
+				else {
+					m = dynJoint.relPos;
+				}
 
 				if( o.targetSkin != null ) {
 					o.targetSkin.currentRelPose[o.targetJoint] = m;

+ 7 - 3
h3d/anim/Skin.hx

@@ -35,16 +35,16 @@ class DynamicJoint extends Joint {
 	public static var STAMP : Float = 0.0;
 	public static var SLEEP_THRESHOLD : Float = 0.0;
 
-	public var relPos : h3d.Matrix; // Initial relative pos before joint get moved by animation / dynamic system
+	public var relPos(default, set) : h3d.Matrix; // Initial relative pos before joint get moved by animation / dynamic system
 	public var absPos : h3d.Matrix; // Abs pos of the joint computed each frame
 
 	// Parameters
 	public var speed : h3d.Vector;
 	public var radius : Float = 0.0;
 	public var damping : Float = 0.4;
-	public var stiffness : Float = 0.1;
+	public var stiffness : Float = 0.5;
 	public var resistance : Float = 0.9;
-	public var slackness : Float = 0.01;
+	public var slackness : Float = 0.1;
 
 	public function new() {
 		super();
@@ -52,6 +52,10 @@ class DynamicJoint extends Joint {
 		speed = new h3d.Vector(0.0, 0.0, 0.0);
 		worldPos = new h3d.Vector(0.0, 0.0, 0.0);
 	}
+
+	public function set_relPos(v) {
+		return this.relPos = v;
+	}
 }
 
 private class Permut {

+ 48 - 25
h3d/scene/Skin.hx

@@ -288,7 +288,7 @@ class Skin extends MultiMaterial {
 				r._43 = j.defMat._43;
 			}
 			var dyn = Std.downcast(j, DynamicJoint);
-			if (dyn != null)
+			if (dyn != null && dyn.relPos == null)
 				dyn.relPos = r;
 			if( j.parent == null )
 				m.multiply3x4inline(r, absPos);
@@ -323,13 +323,6 @@ class Skin extends MultiMaterial {
 			}
 		}
 
-		tmp2CurrentAbsPose = [];
-		for (tmp in currentAbsPose) {
-			var tmp2 = new h3d.Matrix();
-			tmp2.load(tmp);
-			tmp2CurrentAbsPose.push(tmp2);
-		}
-
 		tmp3CurrentAbsPose = [];
 		for (tmp in currentAbsPose) {
 			var tmp2 = new h3d.Matrix();
@@ -341,18 +334,6 @@ class Skin extends MultiMaterial {
 		var deltaTime = Timer.stamp() - DynamicJoint.STAMP;
 		DynamicJoint.STAMP = Timer.stamp();
 
-		// if (g== null) {
-		// 	g = new Graphics(this.getScene());
-		// 	g.material.mainPass.setPassName("overlay");
-		// 	g.lineStyle(1, 0xFFFFFF, 1);
-		// }
-
-		// g.clear();
-
-		function convertVec(v : h3d.Vector) {
-			return new h3d.Vector(Math.round(v.x * 100) / 100,  Math.round(v.z * 100) / 100, Math.round(-v.y * 100) / 100);
-		}
-
 		for( j in skinData.allJoints ) {
 			if ( j.follow != null ) continue;
 
@@ -362,7 +343,6 @@ class Skin extends MultiMaterial {
 
 			var newWorldPos = worldPos.getPosition().clone();
 			var expectedPos = worldPos.getPosition().clone();
-			var oldWorldPos = worldPos.getPosition().clone();
 
 			// // Resistance (force resistance)
 			// var globalForce = new h3d.Vector(0, 0, 0);
@@ -375,26 +355,69 @@ class Skin extends MultiMaterial {
 			// }
 
 			// Stiffness (shape keeper)
-			var parentMovement =  tmp2CurrentAbsPose[j.parent.index].getPosition() - tmp3CurrentAbsPose[j.parent.index].getPosition();
+			var parentMovement =  currentAbsPose[j.parent.index].getPosition() - tmp3CurrentAbsPose[j.parent.index].getPosition();
             expectedPos = dynJoint.relPos.multiplied(tmp3CurrentAbsPose[j.parent.index]).getPosition() + parentMovement;
             newWorldPos.lerp(newWorldPos, expectedPos, dynJoint.stiffness);
 
 			// Slackness (length keeper)
-			var dirToParent = (newWorldPos - tmp2CurrentAbsPose[j.parent.index].getPosition()).normalized();
+			var dirToParent = (newWorldPos - currentAbsPose[j.parent.index].getPosition()).normalized();
             var lengthToParent = dynJoint.relPos.getPosition().length();
-            expectedPos = tmp2CurrentAbsPose[j.parent.index].getPosition() + dirToParent * lengthToParent;
+            expectedPos = currentAbsPose[j.parent.index].getPosition() + dirToParent * lengthToParent;
 			newWorldPos.lerp(expectedPos, newWorldPos, dynJoint.slackness);
 
 			// Collision
 			// TODO
 
+			// Apply computed position to joint
 			// dynJoint.speed = (dynJoint.speed + (newWorldPos - oldWorldPos) * (1.0 / deltaTime)) * 0.5;
 			currentAbsPose[j.index].setPosition(newWorldPos);
-			tmp2CurrentAbsPose[j.index].setPosition(newWorldPos);
 
 			if( dynJoint.bindIndex >= 0 )
 				currentPalette[dynJoint.bindIndex].multiply3x4inline(j.transPos, currentAbsPose[j.index]);
 		}
+
+		function recomputeAbsPosFrom(dynJoint: DynamicJoint) {
+			currentAbsPose[dynJoint.index] = new Matrix();
+			currentAbsPose[dynJoint.index].identity();
+			currentAbsPose[dynJoint.index].multiply3x4inline(dynJoint.relPos, currentAbsPose[dynJoint.parent.index]);
+
+			if( dynJoint.bindIndex >= 0 )
+				currentPalette[dynJoint.bindIndex].multiply3x4inline(dynJoint.transPos, currentAbsPose[dynJoint.index]);
+
+			if (dynJoint.subs != null) {
+				for (s in dynJoint.subs)
+					recomputeAbsPosFrom(cast s);
+			}
+		}
+
+		for( j in skinData.allJoints ) {
+			if ( j.follow != null ) continue;
+
+			var dynJoint = Std.downcast(j, h3d.anim.Skin.DynamicJoint);
+			if (dynJoint == null) continue;
+			if (dynJoint.subs.length != 1) continue;
+
+			var child = Std.downcast(dynJoint.subs[0], DynamicJoint);
+
+			var p = currentAbsPose[dynJoint.index].getPosition();
+			currentAbsPose[dynJoint.index].load(tmp3CurrentAbsPose[dynJoint.index]);
+			currentAbsPose[dynJoint.index].setPosition(p);
+
+			var q = new Quat();
+			var offset = currentAbsPose[child.index].getPosition() - currentAbsPose[dynJoint.index].getPosition();
+			offset.transform3x3(currentAbsPose[dynJoint.index].getInverse());
+			q.initMoveTo(child.relPos.getPosition().normalized(), offset.normalized());
+
+			currentAbsPose[dynJoint.index].multiply(q.toMatrix(), currentAbsPose[dynJoint.index]);
+
+			if( dynJoint.bindIndex >= 0 )
+				currentPalette[dynJoint.bindIndex].multiply3x4inline(j.transPos, currentAbsPose[dynJoint.index]);
+
+			for (s in dynJoint.subs) {
+				recomputeAbsPosFrom(cast s);
+			}
+		}
+
 		init = true;
 	}
 

+ 9 - 4
hxd/fmt/fbx/HMDOut.hx

@@ -1048,9 +1048,14 @@ class HMDOut extends BaseLibrary {
 
 			var parent = j.parent;
 			while(parent != null) {
-				if (parent.model.getName().indexOf(dynName) >= 0)
-					return true;
-				parent = parent.parent;
+				if (parent.model != null) {
+					if (parent.model.getName().indexOf(dynName) >= 0)
+						return true;
+					parent = parent.parent;
+				}
+				else {
+					break;
+				}
 			}
 
 			return false;
@@ -1059,7 +1064,7 @@ class HMDOut extends BaseLibrary {
 		// create joints
 		for( o in joints ) {
 			if( o.isMesh ) throw "assert";
-			var j = isDynamic('_Cape', o) ? new h3d.anim.Skin.DynamicJoint() : new h3d.anim.Skin.Joint();
+			var j = isDynamic('_Cape02', o) ? new h3d.anim.Skin.DynamicJoint() : new h3d.anim.Skin.Joint();
 			getDefaultMatrixes(o.model); // store for later usage in animation
 			j.index = o.model.getId();
 			j.name = o.model.getName();

+ 1 - 1
hxd/fmt/hmd/Library.hx

@@ -368,7 +368,7 @@ class Library {
 		}
 
 		for( joint in skin.joints ) {
-			var j = isDynamic('B_Cape02', joint) ? new h3d.anim.Skin.DynamicJoint() : new h3d.anim.Skin.Joint();
+			var j = isDynamic('DYN', joint) ? new h3d.anim.Skin.DynamicJoint() : new h3d.anim.Skin.Joint();
 			j.name = joint.name;
 			j.index = s.allJoints.length;
 			j.defMat = joint.position.toMatrix();