/// <summary> /// Aligns the rigid bodies by correcting their orienation /// This should be called after the simulation step /// </summary> private void AlignBones() { // orient the bodies accordingly for (var i = this.BoneInset; i < this.simulatedTransforms.Count - this.BoneInset; i++) { if (!this.simulatedTransforms[i].Dynamic) { continue; } var a = this.simulatedTransforms[i - 1].Position; var b = this.simulatedTransforms[i + 1].Position; // this is the upVector computed for each bone of the rest pose var transform = this.restPoseSpace * this.restPoseTransforms[i]; // todo: direction of multiply? var y = SimdExtensions.CreateQuaternion(transform).Act(new SCNVector3(0f, 1f, 0f)); var x = SCNVector3.Normalize(b - a); var z = SCNVector3.Normalize(SCNVector3.Cross(x, y)); y = SCNVector3.Normalize(SCNVector3.Cross(z, x)); var rot = new OpenTK.Matrix3(x.X, y.X, z.X, x.Y, y.Y, z.Y, x.Z, y.Z, z.Z); this.simulatedTransforms[i].Orientation = new SCNQuaternion(rot.ToQuaternion()); } }
/// <summary> /// Returns the interpolated transform at a given length (l from 0.0 to totalLength) /// </summary> public SCNMatrix4 Transform(float l) { var position = this.Position(l); var x = this.Tangent(l); var y = SCNVector3.Normalize(this.UpVector); var z = SCNVector3.Normalize(SCNVector3.Cross(x, y)); y = SCNVector3.Normalize(SCNVector3.Cross(z, x)); var rot = new OpenTK.Matrix3(x.X, y.X, z.X, x.Y, y.Y, z.Y, x.Z, y.Z, z.Z); var matrix = SCNMatrix4.Rotate(rot.ToQuaternion()); return(matrix.SetTranslation((OpenTK.Vector3)position)); }