// 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;
            }
        }
Beispiel #2
0
        /// <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);
            }
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
            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);
                }
            }
Beispiel #5
0
        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));
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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;
            }
        }
Beispiel #8
0
        //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));
        }
Beispiel #10
0
        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;
                }
            }
        }