// called every frame. computation could be triggered selectively on change for performance gains public void Evaluate(int SpreadMax) { FView.SliceCount = FProjection.SliceCount = FViewProjection.SliceCount = SpreadMax; for (int i = 0; i < SpreadMax; i++) { var translate = FTranslate[i]; var rotate = FRotate[i]; var fov = FFov[i]; var shift = FShift[i]; var near = FNear[i]; var far = FFar[i]; var view = VMath.Inverse(VMath.Rotate(rotate * Math.PI * 2) * VMath.Translate(translate)); double scaleX = 1.0 / Math.Tan(fov[0] * Math.PI); double scaleY = 1.0 / Math.Tan(fov[1] * Math.PI); double fn = far / (far - near); var proj = new Matrix4x4( scaleX, 0, 0, 0, 0, scaleY, 0, 0, -2 * shift.x, -2 * shift.y, fn, 1, 0, 0, -near * fn, 0 ); FView[i] = view; FProjection[i] = proj; FViewProjection[i] = view * proj; } }
/// <summary> /// Apply delta /// </summary> /// <param name="prev"></param> /// <param name="delta"></param> /// <param name="view"></param> /// <param name="rotSpeed"></param> /// <param name="frametime"></param> public CameraProperties( CameraProperties prev, CameraDelta delta, Matrix4x4 view, double rotSpeed = 1, double frametime = 1) : this(prev) { var rotmat = new Matrix4x4(VMath.Inverse(view)) { row4 = new Vector4D(0, 0, 0, 1) }; if (delta.SetTranslation) { Translation = prev.Translation + rotmat * (delta.Translation * frametime); } if (delta.SetRotation) { var inputrotmat = new Matrix4x4(InputView) { row4 = new Vector4D(0, 0, 0, 1) }; var inrotq = Quaternion.RotationMatrix(inputrotmat.ToSlimDXMatrix()); var rottime = frametime * rotSpeed; var rotq = Quaternion.RotationYawPitchRoll((float)(delta.PitchYawRoll.y * rottime), (float)(delta.PitchYawRoll.x * rottime), (float)(delta.PitchYawRoll.z * rottime)); //Rotation = Quaternion.Normalize(inrotq * rotq * Quaternion.Invert(inrotq) * Rotation); Rotation = Quaternion.Normalize(prev.Rotation * Quaternion.Invert(inrotq) * rotq * inrotq); } if (delta.SetPivotDistance) { PivotDistance = Math.Max(0, prev.PivotDistance + delta.PivotDistance * frametime); } if (delta.SetFov) { var nfov = VMath.Map(prev.Fov, 0.01, 0.45, 0, 1, TMapMode.Clamp); nfov += delta.Fov * frametime * (nfov + 0.05); Fov = VMath.Map(nfov, 0, 1, 0.01, 0.45, TMapMode.Clamp); } if (delta.SetNear) { Near = Math.Max(0, prev.Near + delta.Near * frametime); } if (delta.SetFar) { Far = Math.Max(0, prev.Far + delta.Far * frametime); } }
public Vector2D Project(Vector3D pos, Vector3D translate, Vector3D rotate, double fov, Vector2D shift, double Aspect = 0.75, double Near = 0.5, double Far = 100) { // VMath.Rotate expects Radians var view = VMath.Inverse(VMath.Rotate(rotate * Math.PI * 2) * VMath.Translate(translate)); double scaleX = 1.0 / Math.Tan(fov * Math.PI); double scaleY = scaleX / Aspect; double fn = Far / (Far - Near); var proj = new Matrix4x4(scaleX, 0, 0, 0, 0, scaleY, 0, 0, -2 * shift.x, -2 * shift.y, fn, 1, 0, 0, -Near * fn, 0); return(ProjectVertex(pos, view * proj)); }
public bool TestHit(Vector2D cursorInSlide) { var cursorInHitRegion3 = VMath.Inverse(this.Transform) * cursorInSlide; var cursorInHitRegion = new Vector2D(cursorInHitRegion3.x, cursorInHitRegion3.y); if (TestShape == Shape.Quad) { return(Math.Abs(cursorInHitRegion.x) <= 0.5 && Math.Abs(cursorInHitRegion.y) <= 0.5); } else if (TestShape == Shape.Circle) { return(cursorInHitRegion.LengthSquared <= 0.25); } else { //default return(false); } }
public Matrix4x4 getBindShapeMatrix(string fileContents) { NumberFormatInfo nf = new CultureInfo("en-US", false).NumberFormat; char[] separators = { ',', ';' }; string[] el; Match m = Regex.Match(fileContents, @"FrameTransformMatrix \{([^\}]+)\}\s*Mesh"); if (m.Length == 0) { return(VMath.IdentityMatrix); } el = m.Groups[1].ToString().Split(separators); Matrix4x4 t = new Matrix4x4(Double.Parse(el[0], nf), Double.Parse(el[1], nf), Double.Parse(el[2], nf), Double.Parse(el[3], nf), Double.Parse(el[4], nf), Double.Parse(el[5], nf), Double.Parse(el[6], nf), Double.Parse(el[7], nf), Double.Parse(el[8], nf), Double.Parse(el[9], nf), Double.Parse(el[10], nf), Double.Parse(el[11], nf), Double.Parse(el[12], nf), Double.Parse(el[13], nf), Double.Parse(el[14], nf), Double.Parse(el[15], nf)); return(VMath.Inverse(t)); }
private double calculateTorque(IJoint joint, Vector3D axis) { Vector3D targetPosLocal = VMath.Inverse(joint.CombinedTransform) * targetPosW; Vector3D endPosLocal = VMath.Inverse(joint.CombinedTransform) * endPosW; if (double.IsInfinity(endPosLocal.x) || double.IsNaN(endPosLocal.x)) { return(0); } Vector3D f = targetPosLocal - endPosLocal; Vector3D a = axis; Vector3D b = endPosLocal; Vector3D r = new Vector3D(0); r.x = a.y * b.z - a.z * b.y; r.y = a.z * b.x - a.x * b.z; r.z = a.x * b.y - a.y * b.x; double torque = VMath.Dist(new Vector3D(0), f) * Math.Sin(vectorAngle(a, f)) * Math.Sin(vectorAngle(b, f)) * Math.Sign(Math.Cos(vectorAngle(r, f))) * 0.03; return(torque); }
public void Evaluate(int SpreadMax) { if (FSkeletonIn.SliceCount == 0) { FOut.SliceCount = 0; FSucc.SliceCount = 0; FJoint.SliceCount = 0; FNameIndex.SliceCount = 0; return; } if (FSkeletonIn[0] == null) { return; } if (FSkeletonIn.IsChanged || FJointName.IsChanged || FAnimTrIn.Stream.IsChanged || FBaseTrIn.Stream.IsChanged || FRegexSearch.IsChanged || FOpMode.IsChanged) { var spreadmax = new[] { FAnimTrIn.SliceCount, FBaseTrIn.SliceCount, FJointName.SliceCount, FSkeletonIn.SliceCount }.Max(); FOut.SliceCount = spreadmax; FSucc.SliceCount = spreadmax; FJoint.SliceCount = spreadmax; FNameIndex.SliceCount = spreadmax; FJoint.Stream.IsChanged = true; FOut.Stream.IsChanged = true; for (int i = 0; i < FOut.SliceCount; i++) { if (FOut[i] == null) { FOut[i] = new Skeleton(); } FSkeletonIn[i].CopyData(FOut[i]); FSucc[i].SliceCount = FJointName[i].SliceCount; if (FJointName.IsChanged || FRegexSearch.IsChanged || init) { FNameIndex[i].SliceCount = 0; if (FRegexSearch[i]) { FJoint[i].SliceCount = 0; for (int j = 0; j < FJointName[i].SliceCount; j++) { var pattern = new Regex(FJointName[i][j], RegexOptions.CultureInvariant | RegexOptions.Multiline); FSucc[i][j] = false; foreach (var joint in FOut[i].JointTable.Values) { if (!pattern.IsMatch(joint.Name)) { continue; } FJoint[i].Add(joint); FNameIndex[i].Add(j); FSucc[i][j] = true; } } } else { FJoint[i].SliceCount = FJointName[i].SliceCount; for (int j = 0; j < FJointName[i].SliceCount; j++) { if (!FOut[i].JointTable.ContainsKey(FJointName[i][j])) { FSucc[i][j] = false; continue; } FSucc[i][j] = true; var joint = FOut[i].JointTable[FJointName[i][j]]; FJoint[i][j] = joint; } } } for (int j = 0; j < FJoint[i].SliceCount; j++) { var joint = FJoint[i][j]; var jointin = FSkeletonIn[i].JointTable[FJoint[i][j].Name]; int jj = FRegexSearch[i] ? FNameIndex[i][j] : j; switch (FOpMode[i]) { case SetJointOperationMode.Absolute: if (joint.Parent != null) { joint.BaseTransform = FBaseTrIn[i][jj] * VMath.Inverse(joint.Parent.CombinedTransform); } else { joint.BaseTransform = FBaseTrIn[i][jj]; } joint.AnimationTransform = FAnimTrIn[i][jj]; break; case SetJointOperationMode.Override: joint.BaseTransform = FBaseTrIn[i][jj]; joint.AnimationTransform = FAnimTrIn[i][jj]; break; case SetJointOperationMode.FirstOperand: joint.BaseTransform = FBaseTrIn[i][jj] * jointin.BaseTransform; joint.AnimationTransform = FAnimTrIn[i][jj] * jointin.AnimationTransform; break; case SetJointOperationMode.SecondOperand: joint.BaseTransform = jointin.BaseTransform * FBaseTrIn[i][jj]; joint.AnimationTransform = jointin.AnimationTransform * FAnimTrIn[i][jj]; break; } } } init = false; } else { FJoint.Stream.IsChanged = false; } }
//here we go, thats the method called by vvvv each frame //all data handling should be in here public void Evaluate(int SpreadMax) { //if any of the inputs has changed //recompute the outputs bool recalculate = false; bool chainRangeChanged = false; bool recalculateOrientation = false; if (FChainStart.PinIsChanged) { FChainStart.GetString(0, out chainStart); recalculate = true; chainRangeChanged = true; } if (FChainEnd.PinIsChanged) { FChainEnd.GetString(0, out chainEnd); recalculate = true; chainRangeChanged = true; } object currInterface; if (FPoseInput.PinIsChanged || chainRangeChanged) { if (FPoseInput.IsConnected) { FPoseInput.GetUpstreamInterface(out currInterface); Skeleton s = (Skeleton)currInterface; if (outputSkeleton == null || !s.Uid.Equals(outputSkeleton.Uid)) { outputSkeleton = (Skeleton)((Skeleton)currInterface).DeepCopy(); outputSkeleton.BuildJointTable(); workingSkeleton = (Skeleton)outputSkeleton.DeepCopy(); workingSkeleton.BuildJointTable(); chainRangeChanged = true; } else { foreach (KeyValuePair <string, IJoint> pair in s.JointTable) { if (!jointChain.Exists(delegate(IJoint j) { return(j.Name == pair.Key); })) { outputSkeleton.JointTable[pair.Key].BaseTransform = pair.Value.BaseTransform; outputSkeleton.JointTable[pair.Key].AnimationTransform = pair.Value.AnimationTransform; workingSkeleton.JointTable[pair.Key].BaseTransform = pair.Value.BaseTransform; workingSkeleton.JointTable[pair.Key].AnimationTransform = pair.Value.AnimationTransform; } outputSkeleton.JointTable[pair.Key].Constraints = pair.Value.Constraints; workingSkeleton.JointTable[pair.Key].Constraints = pair.Value.Constraints; } } workingSkeleton.CalculateCombinedTransforms(); recalculate = true; } else { outputSkeleton = null; } } if (FVelocityInput.PinIsChanged) { double x; FVelocityInput.GetValue(0, out x); iterationsPerFrame = (int)(x * 10); } if (iterationsPerFrame > 0) { if (FTargetInput.PinIsChanged) { targetPosW = new Vector3D(); FTargetInput.GetValue3D(0, out targetPosW.x, out targetPosW.y, out targetPosW.z); recalculate = true; } if (FEpsilonInput.PinIsChanged) { FEpsilonInput.GetValue(0, out epsilon); recalculate = true; } if (FPoleTargetInput.PinIsChanged || FEnablePoleTargetInput.PinIsChanged) { double x; FEnablePoleTargetInput.GetValue(0, out x); enablePoleTarget = x > 0.0; poleTargetW = new Vector3D(); FPoleTargetInput.GetValue3D(0, out poleTargetW.x, out poleTargetW.y, out poleTargetW.z); recalculateOrientation = true; } if (chainRangeChanged && outputSkeleton != null) { initRotations(); } double delta = VMath.Dist(endPosW, targetPosW); if ((delta > epsilon || recalculate) && outputSkeleton != null && !string.IsNullOrEmpty(chainStart) && !string.IsNullOrEmpty(chainEnd)) { List <Vector2D> constraints = new List <Vector2D>(); for (int i = 0; i < iterationsPerFrame; i++) { for (int j = 0; j < 3; j++) { IJoint currJoint = workingSkeleton.JointTable[chainEnd]; endPosW = currJoint.CombinedTransform * new Vector3D(0); while (currJoint.Name != chainStart) { currJoint = currJoint.Parent; Vector3D rotationAxis = new Vector3D(0, 0, 0); rotationAxis[j] = 1; double torque = calculateTorque(currJoint, rotationAxis); Vector3D rot = rotations[currJoint.Name]; if ((rot[j] + torque) < currJoint.Constraints[j].x * 2 * Math.PI || (rot[j] + torque) > currJoint.Constraints[j].y * 2 * Math.PI) { torque = 0; } Matrix4x4 newTransform = VMath.Rotate(torque * rotationAxis.x, torque * rotationAxis.y, torque * rotationAxis.z) * currJoint.AnimationTransform; Vector3D testVec = newTransform * new Vector3D(0); if (!Double.IsInfinity(testVec.x) && !Double.IsNaN(testVec.x)) // an evil bug fix, to avoid n.def. values in animation transform matrix. the actual reason, why this would happen has not been found yet. { rot[j] += torque; rotations[currJoint.Name] = rot; currJoint.AnimationTransform = newTransform; outputSkeleton.JointTable[currJoint.Name].AnimationTransform = currJoint.AnimationTransform; } } } try { Matrix4x4 pre; if (workingSkeleton.JointTable[chainStart].Parent != null) { pre = workingSkeleton.JointTable[chainStart].Parent.CombinedTransform; } else { pre = VMath.IdentityMatrix; } ((JointInfo)workingSkeleton.JointTable[chainStart]).CalculateCombinedTransforms(pre); } catch (Exception) { workingSkeleton.CalculateCombinedTransforms(); } } FPoseOutput.MarkPinAsChanged(); } if ((recalculate || recalculateOrientation) && enablePoleTarget && outputSkeleton != null && !string.IsNullOrEmpty(chainStart) && !string.IsNullOrEmpty(chainEnd)) { endPosW = workingSkeleton.JointTable[chainEnd].CombinedTransform * new Vector3D(0); Vector3D poleTargetLocal = VMath.Inverse(workingSkeleton.JointTable[chainStart].CombinedTransform) * poleTargetW; Vector3D t = VMath.Inverse(workingSkeleton.JointTable[chainStart].CombinedTransform) * endPosW; // endpoint in local coords Vector3D a = VMath.Inverse(workingSkeleton.JointTable[chainStart].CombinedTransform) * (workingSkeleton.JointTable[chainStart].Children[0].CombinedTransform * new Vector3D(0)); // next child in local coords Vector3D x = t * ((a.x * t.x + a.y * t.y + a.z * t.z) / Math.Pow(VMath.Dist(new Vector3D(0), t), 2)); Vector3D y = t * ((poleTargetLocal.x * t.x + poleTargetLocal.y * t.y + poleTargetLocal.z * t.z) / Math.Pow(VMath.Dist(new Vector3D(0), t), 2)); Vector3D c = poleTargetLocal - y; Vector3D b = a - x; double angle = vectorAngle(b, c); Vector3D n = new Vector3D(); n.x = c.y * b.z - c.z * b.y; n.y = c.z * b.x - c.x * b.z; n.z = c.x * b.y - c.y * b.x; n = n / VMath.Dist(new Vector3D(0), n); FDebugOutput.SetValue(0, angle); chainRotation = RotateAroundAxis(angle, n); FPoseOutput.MarkPinAsChanged(); } if (!enablePoleTarget) { chainRotation = VMath.IdentityMatrix; } outputSkeleton.JointTable[chainStart].AnimationTransform = chainRotation * outputSkeleton.JointTable[chainStart].AnimationTransform; } FPoseOutput.SetInterface(outputSkeleton); }
public Vector2D CanvasToSlide(Vector2D cursorInCanvas) { var cursorInSlide3 = VMath.Inverse(this.Transform) * cursorInCanvas; return(new Vector2D(cursorInSlide3.x, cursorInSlide3.y)); }
public void Move(CameraDelta delta, double frametime = 1) { var rotmat = new Matrix4x4(VMath.Inverse(View)) { row4 = new Vector4D(0, 0, 0, 1) }; if (delta.SetTranslation) { Translation += rotmat * (delta.Translation * frametime); } if (delta.SetRotation) { var inputrotmat = new Matrix4x4(InputView) { row4 = new Vector4D(0, 0, 0, 1) }; var inrotq = Quaternion.RotationMatrix(inputrotmat.ToSlimDXMatrix()); var rottime = frametime * RotationSpeed; var rotq = Quaternion.RotationYawPitchRoll((float)(delta.PitchYawRoll.y * rottime), (float)(delta.PitchYawRoll.x * rottime), (float)(delta.PitchYawRoll.z * rottime)); //Rotation = Quaternion.Normalize(inrotq * rotq * Quaternion.Invert(inrotq) * Rotation); Rotation = Quaternion.Normalize(Rotation * Quaternion.Invert(inrotq) * rotq * inrotq); } if (delta.SetPivotDistance) { PivotDistance = Math.Max(0, PivotDistance + delta.PivotDistance * frametime); } if (delta.SetFov) { var nfov = VMath.Map(Fov, 0.01, 0.45, 0, 1, TMapMode.Clamp); nfov += delta.Fov * frametime * (nfov + 0.05); Fov = VMath.Map(nfov, 0, 1, 0.01, 0.45, TMapMode.Clamp); } if (delta.SetNear) { Near = Math.Max(0, Near + delta.Near * frametime); } if (delta.SetFar) { Far = Math.Max(0, Far + delta.Far * frametime); } if (Default != null) { if (delta.ResetTranslation) { Translation = new Vector3D(Default.Translation); } if (delta.ResetRotation) { Rotation = new Quaternion(Default.Rotation.X, Default.Rotation.Y, Default.Rotation.Z, Default.Rotation.W); } if (delta.ResetPivotDistance) { PivotDistance = Default.PivotDistance; } if (delta.ResetFov) { Fov = Default.Fov; } if (delta.ResetNear) { Near = Default.Near; } if (delta.ResetFar) { Far = Default.Far; } } }