Esempio n. 1
0
    // https://blackpawn.com/texts/pointinpoly/
    bool IsSameSide(MyVector3 p1, MyVector3 p2, MyVector3 a, MyVector3 b)
    {
        var cp1 = MyVector3.Cross(b - a, p1 - a);
        var cp2 = MyVector3.Cross(b - a, p2 - a);

        return(MyVector3.Dot(cp1, cp2) >= 0);
    }
Esempio n. 2
0
        List <MyVector3> ProjectTrajAccording2Profile(List <MyVector2> trajpoints)
        {
            List <MyVector3> output        = new List <MyVector3>();
            MyVector3        profilenormal = this.topCircle.Normal;
            MyVector3        profilecenter = this.topCircle.Center;
            MyVector3        viewvector    = this.camera.target; //suppose to be (0,0,1)

            //find a plane that is almost vertical to view vector and the normal line of profile is on the plane
            MyVector3 temp = profilenormal.Cross(viewvector);
            MyVector3 targetplanenormal = profilenormal.Cross(temp);

            targetplane = new MyPlane(profilecenter, targetplanenormal);

            output = this.Proj2dToPlane(targetplane, trajpoints);
            return(output);
        }
Esempio n. 3
0
    //calculate the x velocity resulting from the ball sliding on the floor for a time deltaTime
    private MyVector3 HorizontalVelocityAfterSliding(float deltaTime)
    {
        if (pureRolling)
        {
            return(velocityPreviousFrame);
        }
        MyVector3 afterSlidingVel;
        MyVector3 horizontal_velocityPreviousFrame =
            new MyVector3(velocityPreviousFrame.getX(), 0, velocityPreviousFrame.getZ());
        //calculate the variation in the angular momentum and x component of the linear momentum
        float     arbitraryConst1         = 5f;
        MyVector3 frictionDirection       = horizontal_velocityPreviousFrame.Scale(-1).UnitVector();
        MyVector3 linearMomentumVariation = frictionDirection.Scale(
            arbitraryConst1 * floorFriction * mass * deltaTime);
        MyVector3 angularMomentumVariation = MyVector3.Cross(
            new MyVector3(0, -radius, 0),
            linearMomentumVariation);

        afterSlidingVel             = MyVector3.Add(horizontal_velocityPreviousFrame, linearMomentumVariation.Scale(1 / mass));
        angularMomentumCurrentFrame = MyVector3.Add(angularMomentumCurrentFrame, angularMomentumVariation);
        MyVector3 contactPointTangentVel = MyVector3.Cross(AngularVelocity(angularMomentumCurrentFrame), new MyVector3(0, -radius, 0));

        if (contactPointTangentVel.Magnitude() > afterSlidingVel.Magnitude())
        {
            pureRolling = true;
            //calculate the rolling horizintal velocity
            //pure rolling law: speed = (radius) * (angular vel)
            float MRsquared_over_I = (mass * radius * radius) / momentOfInertia;
            afterSlidingVel =
                MyVector3.Subtract(afterSlidingVel.Scale(MRsquared_over_I), contactPointTangentVel).Scale(1 / (1 + MRsquared_over_I));
            angularMomentumCurrentFrame = MyVector3.Cross(afterSlidingVel, new MyVector3(0, -1, 0)).Scale(momentOfInertia / radius);
        }
        return(afterSlidingVel);
    }
Esempio n. 4
0
        private static MyVector3 Get3PlanesInterPoint(ref MyPlane p1, ref MyPlane p2, ref MyPlane p3)
        {
            //P = -d1 * N2xN3 / N1.N2xN3 - d2 * N3xN1 / N2.N3xN1 - d3 * N1xN2 / N3.N1xN2
            MyVector3 v =
                -p1.D * MyVector3.Cross(p2.Normal, p3.Normal) / MyVector3.Dot(p1.Normal, MyVector3.Cross(p2.Normal, p3.Normal))
                - p2.D * MyVector3.Cross(p3.Normal, p1.Normal) / MyVector3.Dot(p2.Normal, MyVector3.Cross(p3.Normal, p1.Normal))
                - p3.D * MyVector3.Cross(p1.Normal, p2.Normal) / MyVector3.Dot(p3.Normal, MyVector3.Cross(p1.Normal, p2.Normal));

            return(v);
        }
Esempio n. 5
0
        /// <summary>
        /// Extracts perspective camera parameters from the frustum, doesn't work with orthographic frustums.
        /// </summary>
        /// <returns>Perspective camera parameters from the frustum</returns>
        public MyFrustumCameraParams GetCameraParams()
        {
            var corners     = GetCorners();
            var cameraParam = new MyFrustumCameraParams();

            cameraParam.Position    = Get3PlanesInterPoint(ref pRight, ref pTop, ref pLeft);
            cameraParam.LookAtDir   = pNear.Normal;
            cameraParam.UpDir       = MyVector3.Normalize(MyVector3.Cross(pRight.Normal, pNear.Normal));
            cameraParam.FOV         = (float)((Math.PI / 2.0 - Math.Acos(MyVector3.Dot(pNear.Normal, pTop.Normal))) * 2);
            cameraParam.AspectRatio = (corners[6] - corners[5]).Length() / (corners[4] - corners[5]).Length();
            cameraParam.ZNear       = (cameraParam.Position + (pNear.Normal * pNear.D)).Length();
            cameraParam.ZFar        = (cameraParam.Position + (pFar.Normal * pFar.D)).Length();
            return(cameraParam);
        }
Esempio n. 6
0
        /// <summary>
        /// Creates a new frustum relaying on perspective camera parameters
        /// </summary>
        /// <param name="cameraPos">The camera pos.</param>
        /// <param name="lookDir">The look dir.</param>
        /// <param name="upDir">Up dir.</param>
        /// <param name="fov">The fov.</param>
        /// <param name="znear">The znear.</param>
        /// <param name="zfar">The zfar.</param>
        /// <param name="aspect">The aspect.</param>
        /// <returns>The bounding frustum calculated from perspective camera</returns>
        public static MyBoundingFrustum FromCamera(MyVector3 cameraPos, MyVector3 lookDir, MyVector3 upDir, float fov, float znear, float zfar, float aspect)
        {
            //http://knol.google.com/k/view-frustum

            lookDir = MyVector3.Normalize(lookDir);
            upDir   = MyVector3.Normalize(upDir);

            MyVector3 nearCenter     = cameraPos + lookDir * znear;
            MyVector3 farCenter      = cameraPos + lookDir * zfar;
            float     nearHalfHeight = (float)(znear * Math.Tan(fov / 2f));
            float     farHalfHeight  = (float)(zfar * Math.Tan(fov / 2f));
            float     nearHalfWidth  = nearHalfHeight * aspect;
            float     farHalfWidth   = farHalfHeight * aspect;

            MyVector3 rightDir = MyVector3.Normalize(MyVector3.Cross(upDir, lookDir));
            MyVector3 Near1    = nearCenter - nearHalfHeight * upDir + nearHalfWidth * rightDir;
            MyVector3 Near2    = nearCenter + nearHalfHeight * upDir + nearHalfWidth * rightDir;
            MyVector3 Near3    = nearCenter + nearHalfHeight * upDir - nearHalfWidth * rightDir;
            MyVector3 Near4    = nearCenter - nearHalfHeight * upDir - nearHalfWidth * rightDir;
            MyVector3 Far1     = farCenter - farHalfHeight * upDir + farHalfWidth * rightDir;
            MyVector3 Far2     = farCenter + farHalfHeight * upDir + farHalfWidth * rightDir;
            MyVector3 Far3     = farCenter + farHalfHeight * upDir - farHalfWidth * rightDir;
            MyVector3 Far4     = farCenter - farHalfHeight * upDir - farHalfWidth * rightDir;

            var result = new MyBoundingFrustum();

            result.pNear   = new MyPlane(Near1, Near2, Near3);
            result.pFar    = new MyPlane(Far3, Far2, Far1);
            result.pLeft   = new MyPlane(Near4, Near3, Far3);
            result.pRight  = new MyPlane(Far1, Far2, Near2);
            result.pTop    = new MyPlane(Near2, Far2, Far3);
            result.pBottom = new MyPlane(Far4, Far1, Near1);

            result.pNear.Normalize();
            result.pFar.Normalize();
            result.pLeft.Normalize();
            result.pRight.Normalize();
            result.pTop.Normalize();
            result.pBottom.Normalize();

            result.pMatrix = MyMatrix.LookAtLH(cameraPos, cameraPos + lookDir * 10, upDir) * MyMatrix.PerspectiveFovLH(fov, aspect, znear, zfar);

            return(result);
        }
Esempio n. 7
0
    void LateUpdate()
    {
        //CONSTRAINTS
        for (int i = jointsPositions.Length - 2; i >= 0; i--)
        {
            if (i > 0)
            {
                ToParent = new MyVector3(joints[i - 1].position.x - joints[i].position.x, joints[i - 1].position.y - joints[i].position.y, joints[i - 1].position.z - joints[i].position.z).normalized();
                ToChild  = new MyVector3(joints[i + 1].position.x - joints[i].position.x, joints[i + 1].position.y - joints[i].position.y, joints[i + 1].position.z - joints[i].position.z).normalized();
                axis     = MyVector3.Cross(ToParent, ToChild).normalized();

                float angle = Mathf.Acos(MyVector3.Dot(ToParent, ToChild) / (ToParent.magnitude() * ToChild.magnitude())) * Mathf.Rad2Deg;

                if (angle > maxAngle || angle < ((i == 1) ? minAngle * 4 : minAngle))
                {
                    angle = Mathf.Clamp(angle, ((i == 1) ? minAngle * 4 : minAngle), maxAngle);

                    joints[i].rotation = joints[i - 1].rotation;
                    joints[i].Rotate(new Vector3(axis.x, axis.y, axis.z), 180 + angle, Space.World);
                }
            }
            else if (i == 0)
            {
                ToParent = new MyVector3(0, -1, 0);
                ToChild  = new MyVector3(joints[i + 1].position.x - joints[i].position.x, joints[i + 1].position.y - joints[i].position.y, joints[i + 1].position.z - joints[i].position.z).normalized();
                axis     = MyVector3.Cross(ToParent, ToChild).normalized();

                float angle = Mathf.Acos(MyVector3.Dot(ToParent, ToChild) / (ToParent.magnitude() * ToChild.magnitude())) * Mathf.Rad2Deg;

                if (angle > maxAngle + maxAngle / 4 || angle < maxAngle - maxAngle / 4)
                {
                    angle = Mathf.Clamp(angle, maxAngle - maxAngle / 4, maxAngle + maxAngle / 4);

                    joints[i].rotation = Quaternion.identity;
                    joints[i].Rotate(new Vector3(axis.x, axis.y, axis.z), 240 + angle, Space.World);
                }
            }
        }
    }
Esempio n. 8
0
    void Update()
    {
        // Copy the joints positions to work with
        //TODO
        copy[0] = new MyVector3(joints[0].position);

        //copy[0] = joints[0].position;

        for (int i = 0; i < joints.Length - 1; i++)
        {
            copy[i + 1]  = new MyVector3(joints[i + 1].position);
            distances[i] = (copy[i + 1] - copy[i]).Module();

            //copy[i + 1] = joints[i + 1].position;
            //distances[i] = (copy[i + 1] - copy[i]).magnitude;
        }
        // CALCULATE ALSO THE DISTANCE BETWEEN JOINTS

        //done = TODO
        done = (copy[copy.Length - 1] - new MyVector3(target.position)).Module() < tresholdCondition;

        //done = (copy[copy.Length - 1] - target.position).magnitude < tresholdCondition;

        if (!done)
        {
            float targetRootDist = (copy[0] - new MyVector3(target.position)).Module();

            //float targetRootDist = Vector3.Distance(copy[0], target.position);

            // Update joint positions
            if (targetRootDist > distances.Sum())
            {
                // The target is unreachable
                for (int i = 0; i < copy.Length - 1; i++)
                {
                    float r = (new MyVector3(target.position) - copy[i]).Module();

                    //float r = (target.position - copy[i]).magnitude;
                    float lambda = distances[i] / r;

                    copy[i + 1] = (1 - lambda) * copy[i] + (lambda * new MyVector3(target.position));

                    //copy[i + 1] = (1 - lambda) * copy[i] + (lambda * target.position);
                }
            }
            else
            {
                MyVector3 b = copy[0];

                //Vector3 b = copy[0];

                // The target is reachable
                //while (TODO)

                float difference = (copy[copy.Length - 1] - new MyVector3(target.position)).Module();

                //float difference = (copy[copy.Length - 1] - target.position).magnitude;

                while (difference > tresholdCondition) // treshold = tolerance
                {
                    // numIterations++;

                    // STAGE 1: FORWARD REACHING
                    //TODO
                    copy[copy.Length - 1] = new MyVector3(target.position);

                    //copy[copy.Length - 1] = target.position;

                    for (int i = copy.Length - 2; i > 0; i--)
                    {
                        float r = (copy[i + 1] - copy[i]).Module();

                        //float r = (copy[i + 1] - copy[i]).magnitude;
                        float lambda = distances[i] / r;

                        copy[i] = (1 - lambda) * copy[i + 1] + lambda * copy[i];
                    }

                    // STAGE 2: BACKWARD REACHING
                    //TODO
                    copy[0] = b;

                    for (int i = 0; i < copy.Length - 1; i++)
                    {
                        float r = (copy[i + 1] - copy[i]).Module();

                        //float r = (copy[i + 1] - copy[i]).magnitude;
                        float lambda = distances[i] / r;

                        copy[i + 1] = (1 - lambda) * copy[i] + lambda * copy[i + 1];
                    }

                    difference = (copy[copy.Length - 1] - new MyVector3(target.position)).Module();

                    //difference = (copy[copy.Length - 1] - target.position).magnitude;
                }
            }

            // Update original joint rotations
            for (int i = 0; i <= joints.Length - 2; i++)
            {
                // float originalAngle = joints[i].rotation.w;

                MyQuat parentRotation = new MyQuat(joints[i + 1].rotation);
                MyQuat childRotation  = new MyQuat(joints[i].rotation);

                //TODO
                // Rotation
                MyVector3 vectorA = new MyVector3(joints[i + 1].position) - new MyVector3(joints[i].position);
                MyVector3 vectorB = copy[i + 1] - copy[i];

                //Vector3 vectorA = joints[i + 1].position - joints[i].position;
                //Vector3 vectorB = copy[i + 1] - copy[i];

                // float angle = Mathf.Acos(Vector3.Dot(vectorA.normalized, vectorB.normalized)) * Mathf.Rad2Deg;
                float cosA = (MyVector3.Dot(vectorA.Normalize(), vectorB.Normalize()));
                float sinA = MyVector3.Cross(vectorA.Normalize(), vectorB.Normalize()).Module();

                //float cosA = (Vector3.Dot(vectorA.normalized, vectorB.normalized));
                //float sinA = Vector3.Cross(vectorA.normalized, vectorB.normalized).magnitude;

                // Atan = Cos | Atan2 = denominador y...
                float angle = Mathf.Atan2(sinA, cosA) * Mathf.Rad2Deg;

                MyVector3 axis = MyVector3.Cross(vectorA, vectorB).Normalize();

                //Vector3 axis = Vector3.Cross(vectorA, vectorB).normalized;

                // joints[i].rotation = Quaternion.AngleAxis(angle, axis) * joints[i].rotation;

                joints[i].rotation = MyQuat.Multiply(MyQuat.Axis2Quad(angle, axis), childRotation).ToUnityQuat();


                //joints[i].rotation = MyQuat.Multiply(MyQuat.Axis2Quad(angle, axis), childRotation).ToUnityQuat();

                childRotation = new MyQuat(joints[i].rotation);

                float angleTest = MyQuat.Angle(parentRotation, childRotation);

                if (Mathf.Abs(angleTest) > maxAngleRotation)
                {
                    joints[i + 1].rotation = joints[i].rotation;
                }


                joints[i + 1].position = new Vector3(copy[i + 1].x, copy[i + 1].y, copy[i + 1].z);


                //joints[i + 1].position = copy[i + 1];
            }
        }
    }
Esempio n. 9
0
    void Update()
    {
        // Copy the joints positions to work with
        for (int i = 0; i < joints.Length; i++)
        {
            copy[i] = new MyVector3(joints[i].position.x, joints[i].position.y, joints[i].position.z); //Copy the joints
            if (i < joints.Length - 1)
            {
                distances[i] = MyVector3.Distance(joints[i + 1].position, joints[i].position); //Calculate the distances
            }
        }

        done = (copy[copy.Length - 1] - new MyVector3(target.position.x, target.position.y, target.position.z)).magnitude < treshold_condition;

        if (!done)
        {
            float targetRootDist = MyVector3.Distance(copy[0], new MyVector3(target.position.x, target.position.y, target.position.z));

            // Update joint positions
            if (targetRootDist > distances.Sum())
            {
                // The target is unreachable
                for (int i = 0; i < copy.Length - 1; i++)
                {
                    float r      = (new MyVector3(target.position.x, target.position.y, target.position.z) - copy[i]).magnitude;
                    float lambda = distances[i] / r;
                    copy[i + 1] = copy[i] * (1 - lambda) + new MyVector3(target.position.x, target.position.y, target.position.z) * lambda;
                }
            }
            else
            {
                MyVector3 b    = copy[0];
                float     difA = (copy[copy.Length - 1] - new MyVector3(target.position.x, target.position.y, target.position.z)).magnitude;

                // The target is reachable
                while (difA > treshold_condition)
                {
                    // STAGE 1: FORWARD REACHING
                    copy[copy.Length - 1] = new MyVector3(target.position.x, target.position.y, target.position.z);
                    for (int i = copy.Length - 2; i > 0; i--)
                    {
                        float r      = (copy[i + 1] - copy[i]).magnitude;
                        float lambda = distances[i] / r;
                        copy[i] = copy[i + 1] * (1 - lambda) + copy[i] * lambda;
                    }

                    // STAGE 2: BACKWARD REACHING
                    copy[0] = b;
                    for (int i = 0; i < copy.Length - 1; i++)
                    {
                        float r      = (copy[i + 1] - copy[i]).magnitude;
                        float lambda = distances[i] / r;
                        copy[i + 1] = copy[i] * (1 - lambda) + copy[i + 1] * lambda;
                    }

                    difA = (copy[copy.Length - 1] - new MyVector3(target.position.x, target.position.y, target.position.z)).magnitude;
                }
            }

            // Update original joint rotations
            for (int i = 0; i <= joints.Length - 2; i++)
            {
                MyQuaternion parentQuat = new MyQuaternion(joints[i + 1].rotation);
                MyQuaternion myQuat     = new MyQuaternion(joints[i].rotation);

                MyVector3 A = new MyVector3(joints[i + 1].position - joints[i].position);
                MyVector3 B = copy[i + 1] - copy[i];

                float cosa = MyVector3.Dot(MyVector3.Normalize(A), MyVector3.Normalize(B));
                float sina = MyVector3.Cross(MyVector3.Normalize(A), MyVector3.Normalize(B)).magnitude;

                float alpha = Mathf.Atan2(sina, cosa) * Mathf.Rad2Deg;

                MyVector3 myAxis = MyVector3.Normalize(MyVector3.Cross(A, B));
                //Vector3 axis = new Vector3(myAxis.x, myAxis.y, myAxis.z);

                myQuat = MyQuaternion.AngleAxis(alpha, ref myAxis);

                Quaternion quat = new Quaternion(myQuat.x, myQuat.y, myQuat.z, myQuat.w);

                joints[i].rotation = quat * joints[i].rotation;
                //joints[i].rotation = Quaternion.AngleAxis(alpha, axis) * joints[i].rotation;

                myQuat = new MyQuaternion(joints[i].rotation);

                float localAngle = MyQuaternion.Angle(parentQuat, myQuat);

                if (Mathf.Abs(localAngle) > maxRotation)
                {
                    joints[i + 1].rotation = joints[i].rotation;
                }

                joints[i + 1].position = new Vector3(copy[i + 1].x, copy[i + 1].y, copy[i + 1].z);
            }
        }
    }
Esempio n. 10
0
        private void RayTracein3DPlane(List <MyVector3> points, MyVector3 curp, MyVector3 curdire, MyVector3 sectionPlaneNormal, out int norInsec, out int notNorInsec)
        {
            // Param
            double insecPs_Dist_theshold          = 0.01;
            double insecP_DistBetweenRay_theshold = 20;

            MyVector3 cutNormal = sectionPlaneNormal.Cross(curdire).Normalize();

            ray = new Line3(curp, cutNormal);

            norInsec    = -1; // Normal side
            notNorInsec = -1; // Not Normal side
            double dist_left  = double.MaxValue;
            double dist_right = double.MaxValue;

            for (int i = 0; i < points.Count; i++)
            {
                double dist_temp = ray.DistanceToLine(points[i]);
                if ((points[i] - curp).Dot(cutNormal) > 0)
                {
                    // Normal side
                    if (dist_left > dist_temp)
                    {
                        dist_left = dist_temp;
                        norInsec  = i;
                    }
                }
                else
                {
                    // Not Normal side
                    if (dist_right > dist_temp)
                    {
                        dist_right  = dist_temp;
                        notNorInsec = i;
                    }
                }
            }

            if (norInsec == -1)
            {
                norInsec = notNorInsec;
                System.Console.WriteLine("Warining: norInsec == -1");
                return;
            }
            else if (notNorInsec == -1)
            {
                notNorInsec = norInsec;
                System.Console.WriteLine("Warining: notNorInsec == -1");
                return;
            }
            else if (norInsec == -1 && notNorInsec == -1)
            {
                System.Console.WriteLine("Error: Ray Tracein3DPlane, no intersection points");
                return;
            }

            if (MyVector3.Distance(points[norInsec], points[notNorInsec]) < insecPs_Dist_theshold)
            {
                // this two intersection is too close, so let them become same one.s
                System.Console.WriteLine("Warining: two intersection is too close");
                norInsec = notNorInsec;
                return;
            }

            if (ray.DistanceToLine(points[norInsec]) > insecP_DistBetweenRay_theshold ||
                ray.DistanceToLine(points[notNorInsec]) > insecP_DistBetweenRay_theshold)
            {
                System.Console.WriteLine("Warining: two intersection is too far");
                // this two intersection is too far, so let them become same one.s
                norInsec = notNorInsec;
                return;
            }
        }
Esempio n. 11
0
        public void CylinderSnapping()
        {
            // Get Boundary2
            if (boundaryPoints_2d == null)
            {
                boundaryPoints_2d = GetBoundaryPoints(mark);
            }
            List <MyVector2> boundary2 = ExtractOutline(edgeImage, boundaryPoints_2d);

            // Project  2D edge points
            //topCircle = new MyCircle(topCircle.Center, topCircle.Radius, -topCircle.Normal);
            MyVector3 normal       = topCircle.Normal.Cross(this.camera.target).Cross(topCircle.Normal);
            MyPlane   sectionPlane = new MyPlane(topCircle.Center, normal);

            boundary3 = Proj2dToPlane(sectionPlane, boundary2);

            topCircle = CiriFixTopCircle(topCircle, boundary3);

            // UpdateCircleNormal
            //        foreach (var pbondary3 in pbondary3)
            //        {

            //        }
            //        if (topCircle.Center)
            //{

            //}

            // Algorithm Init Params
            double offset = topCircle.Radius / 50;

            cur_p    = topCircle.Center - offset * topCircle.Normal;
            cur_dire = 1.0 * topCircle.Normal;
            MyVector3 cur_dire_new = new MyVector3(cur_dire);
            MyVector3 cur_p_new    = new MyVector3(-1 * cur_p);

            Insection1 = new MyVector3(1, 1, 1);
            Insection2 = new MyVector3(0, 0, 0);
            int       norInsec    = -1;
            int       notNorInsec = -1;
            MyVector3 tangential1 = new MyVector3(1, 1, 1);
            MyVector3 tangential2 = new MyVector3(1, 1, 1);

            List <MyCircle> CircleLists = new List <MyCircle>();

            CircleLists.Add(topCircle);     // Fix first circle

            int    iter = 0;
            double r    = double.MaxValue;

            System.Console.WriteLine(Insection1.Dot(tangential2));
            System.Console.WriteLine(Math.Cos(2.0 / 3.0 * Math.PI));
            int MaxInter = 1000;

            GeneratedCenters = new List <MyVector3>();
            List <double>    radius  = new List <double>();
            List <double>    weights = new List <double>();
            List <MyVector3> dires   = new List <MyVector3>();

            while (--MaxInter > 0)                                           //
            {
                if (Insection1 == Insection2)                                // 交点一直保持相同
                {
                    System.Console.WriteLine("Warning: Insection is same!"); // 半径过小
                    break;
                }
                if (cur_dire.Dot(cur_dire_new) < 0)                                 // 移动方向反向
                {
                    System.Console.WriteLine("Warning: Move Direction!");
                    break;
                }
                if (cur_p + offset * cur_dire == cur_p_new)                         // 中心点没有移动
                {
                    System.Console.WriteLine("Warning: Center not move!");
                    break;
                }

                RayTracein3DPlane(boundary3,
                                  cur_p_new,
                                  cur_dire_new.Cross(sectionPlane.Normal()),
                                  sectionPlane.Normal(),
                                  out norInsec,
                                  out notNorInsec);
                System.Console.WriteLine("{0} , {1}",
                                         MyVector3.Distance(boundary3[norInsec], cur_p_new),
                                         MyVector3.Distance(boundary3[notNorInsec], cur_p_new));
                test1 = new Line3(boundary3[norInsec], cur_p_new - boundary3[norInsec]);
                test2 = new Line3(boundary3[notNorInsec], cur_p_new - boundary3[notNorInsec]);

                if (MyVector3.Distance(boundary3[norInsec], cur_p_new) < topCircle.Radius / 20 || // close to bottom
                    MyVector3.Distance(boundary3[notNorInsec], cur_p_new) < topCircle.Radius / 20)
                {
                    System.Console.WriteLine("Warning: Close to bottom!");
                    break;
                }

                if (tangential1.Dot(tangential2) < Math.Cos(2.0 / 3.0 * Math.PI))   //切线相向
                {
                    System.Console.WriteLine("Warning: tangential get oppsite direction!");
                    break;
                }
                if (r < 0.0001)
                {
                    System.Console.WriteLine("Warning: Radius is too small!");      // 半径过小
                    break;
                }
                //if (MyVector3.Distance(cur_p, cur_p_new) )
                //{
                //    System.Console.WriteLine("Warning: Radius is too small!");    // 半径过小
                //    break;
                //}

                if (iter != 0)
                {
                    //offset = 1 / MyVector3.Distance(cur_p, cur_p_new) * 0.000001 + 0.5 * offset;
                    offset = topCircle.Radius / 20;
                    //System.Console.WriteLine("{0}", offset);
                    cur_dire = cur_dire_new;
                    cur_p    = cur_p_new + offset * cur_dire;
                    CircleLists.Add(new MyCircle(cur_p, r, cur_dire));

                    // Get Data for Fit
                    double weight = Math.Abs(cur_dire_new.Dot(cur_dire));
                    GeneratedCenters.Add(cur_p_new);
                    weights.Add(weight);
                    radius.Add(r);
                    dires.Add(cur_dire);
                }

                // Step1: Get IntersectionPoitn
                RayTracein3DPlane(boundary3, cur_p, cur_dire, sectionPlane.Normal(), out norInsec, out notNorInsec);

                // Step2 : Get Two Local Tangential
                Insection1  = boundary3[norInsec];
                Insection2  = boundary3[notNorInsec];
                tangential1 = GetLocalTangential(norInsec, boundary3, cur_dire);
                tangential2 = GetLocalTangential(notNorInsec, boundary3, cur_dire);

                // Visualization
                setdirecLine = new Line3(cur_p, cur_dire);
                setLine1     = new Line3(Insection1, tangential1);
                setLine2     = new Line3(Insection2, tangential2);

                // Step3 : Get New Cur Direction and Cur Point
                cur_dire_new = (tangential1 + tangential2) / 2;
                RayTracein3DPlane(boundary3, cur_p, cur_dire_new, sectionPlane.Normal(), out norInsec, out notNorInsec);
                cur_p_new = (boundary3[norInsec] + boundary3[notNorInsec]) / 2;
                r         = 0.5 * MyVector3.Distance(boundary3[norInsec], boundary3[notNorInsec]);

                iter++;
                this.view.Refresh();
            }

            // Fit centers and radius;
            GeneratedCenters = FittingCentersCurve(GeneratedCenters, weights);
            int inter = 1;

            while (inter-- > 0)
            {
                radius = FittRadius(radius);
            }

            // ReBuild Object
            CircleLists.Clear();
            CircleLists.Add(topCircle);         // Fix first circle
            for (int i = 0; i < GeneratedCenters.Count; i++)
            {
                CircleLists.Add(new MyCircle(GeneratedCenters[i], radius[i], dires[i]));
            }

            CurveCyliner = new SweepMesh(CircleLists);
        }
Esempio n. 12
0
    void Update()
    {
        if (target.position.y > 1.25f)
        {
            for (int i = 0; i < joints.Length; i++)
            {
                jointsPositions[i] = new MyVector3(joints[i].position.x, joints[i].position.y, joints[i].position.z);
            }
            targetPosition = new MyVector3(target.position.x, target.position.y, target.position.z);

            // Copy the joints positions to work with
            // and calculate all the distances
            for (int i = 0; i < copy.Length; i++)
            {
                copy[i] = jointsPositions[i];
                if (i < distances.Length)
                {
                    distances[i] = (jointsPositions[i + 1] - jointsPositions[i]).magnitude();
                }
            }

            done = (targetPosition - jointsPositions[jointsPositions.Length - 1]).magnitude() < threshold_distance;
            if (!done)
            {
                float targetRootDist = MyVector3.Distance(copy[0], targetPosition);

                // Update joint positions
                if (targetRootDist > distances.Sum())
                {
                    // The target is unreachable
                    for (int i = 0; i < copy.Length - 1; i++)
                    {
                        float dist = (targetPosition - copy[i]).magnitude();
                        float lam  = distances[i] / dist;
                        copy[i + 1] = (1 - lam) * copy[i] + lam * targetPosition;
                    }
                }
                else
                {
                    // The target is reachable
                    iter = 0;
                    while (!done /*|| iter < maxIter*/)
                    {
                        // STAGE 1: FORWARD REACHING
                        copy[copy.Length - 1] = targetPosition;
                        for (int i = copy.Length - 1; i > 0; i--)
                        {
                            MyVector3 temp = (copy[i - 1] - copy[i]).normalized();
                            temp        = temp * distances[i - 1];
                            copy[i - 1] = temp + copy[i];
                        }

                        // STAGE 2: BACKWARD REACHING
                        copy[0] = jointsPositions[0];
                        for (int i = 0; i < copy.Length - 2; i++)
                        {
                            MyVector3 temp = (copy[i + 1] - copy[i]).normalized();
                            temp        = temp * distances[i];
                            copy[i + 1] = temp + copy[i];
                        }

                        done = (targetPosition - copy[copy.Length - 1]).magnitude() < threshold_distance;
                        iter++;
                    }
                }

                // Update original joint rotations
                for (int i = 0; i <= joints.Length - 2; i++)
                {
                    MyVector3 a = jointsPositions[i + 1] - jointsPositions[i];

                    MyVector3 b    = copy[i + 1] - copy[i];
                    MyVector3 axis = MyVector3.Cross(a, b).normalized();

                    float cosa = MyVector3.Dot(a, b) / (a.magnitude() * b.magnitude());
                    float sina = MyVector3.Cross(a.normalized(), b.normalized()).magnitude();

                    float angle = Mathf.Atan2(sina, cosa);

                    MyQuaternion q         = new MyQuaternion(Mathf.Cos(angle / 2), axis.x * Mathf.Sin(angle / 2), axis.y * Mathf.Sin(angle / 2), axis.z * Mathf.Sin(angle / 2));
                    MyQuaternion actualRot = new MyQuaternion(joints[i].rotation.w, joints[i].rotation.x, joints[i].rotation.y, joints[i].rotation.z);
                    MyQuaternion newRot    = MyQuaternion.multiply(q, actualRot);


                    jointsPositions[i] = copy[i];
                    joints[i].position = new Vector3(jointsPositions[i].x, jointsPositions[i].y, jointsPositions[i].z);
                    joints[i].rotation = new Quaternion(newRot.x, newRot.y, newRot.z, newRot.w);

                    for (int j = i; j < joints.Length; j++)   //Actualizar posiciones de los hijos despues de rotar
                    {
                        jointsPositions[j] = new MyVector3(joints[j].position.x, joints[j].position.y, joints[j].position.z);
                    }
                }
            }
        }
    }
Esempio n. 13
0
    private void FixedUpdate()
    {
        //simulation start upon press of the spacebar
        if (Input.GetKeyDown(KeyCode.Space) == true)
        {
            startSimulation = true;
        }
        if (!startSimulation)
        {
            return;
        }

        if (fullStop)
        {
            return; //simulation ended
        }
        float t = Time.fixedDeltaTime;

        if (stopBouncing)
        {
            if (pureRolling)
            {//case 1: the ball is rolling on the floor without sliding
                float dumping = 1 -
                                (5 - 4 / (1 + mass)) *
                                (floorFriction / (4 * floorFriction + 6)) *
                                (1 + 49 / (1 + 10 * Mathf.Abs(velocityPreviousFrame.Magnitude()))) *
                                t; //arbitrary dumping factor. No real physical meaning.
                velocityCurrentFrame = velocityPreviousFrame.Scale(dumping);
                if (velocityCurrentFrame.Magnitude() < 0.01f)
                {//the velocity is low enough to be neglectable
                    velocityCurrentFrame = MyVector3.Zero();
                    fullStop             = true;
                }
                //calculate the avarage velocity between two consecutive frames and use it to calculate the new position
                MyVector3 avgVelocity  = MyVector3.Lerp(velocityPreviousFrame, velocityCurrentFrame, 0.5f);
                MyVector3 displacement = avgVelocity.Scale(t);
                position = MyVector3.Add(position, displacement);
                MoveGameObject();
                angularMomentumCurrentFrame = MyVector3.Cross(velocityCurrentFrame, new MyVector3(0, -1, 0)).Scale(momentOfInertia / radius);
                RotateGameObject(t);
                velocityPreviousFrame        = velocityCurrentFrame;
                angularMomentumPreviousFrame = angularMomentumCurrentFrame;
            }
            else
            {//case 2: the ball is rolling on the floor with sliding
                velocityCurrentFrame = HorizontalVelocityAfterSliding(t);
                //calculate the avarage velocity between two consecutive frames and use it to calculate the new position
                MyVector3 avgVelocity  = MyVector3.Lerp(velocityPreviousFrame, velocityCurrentFrame, 0.5f);
                MyVector3 displacement = avgVelocity.Scale(t);
                position = MyVector3.Add(position, displacement);
                MoveGameObject();
                //angularMomentumCurrentFrame set in the X_VelocityAfterSliding() function
                RotateGameObject(t);
                velocityPreviousFrame        = velocityCurrentFrame;
                angularMomentumPreviousFrame = angularMomentumCurrentFrame;
            }
        }
        else
        {//the ball is still bouncing
            MyVector3 deltaVel = gravity.Scale(t);
            velocityCurrentFrame = MyVector3.Add(velocityPreviousFrame, deltaVel);
            //calculate the avarage velocity between two consecutive frames and use it to calculate the new position
            MyVector3 avgVelocity        = MyVector3.Lerp(velocityPreviousFrame, velocityCurrentFrame, 0.5f);
            MyVector3 displacement       = avgVelocity.Scale(t);
            MyVector3 newPosition        = MyVector3.Add(position, displacement);
            float     distanceFromGround = newPosition.DistanceFromPlane(ground) - radius;
            if (distanceFromGround < 0)
            {                                                             //case 3: the ball is bouncing and has partially fallen balow the plane of the ground
                float impactVel_y            = Y_ImpactVelocity();
                float velocityCurrentFrame_y = impactVel_y * restitution; //upwards speed after bounce
                if (velocityCurrentFrame_y < tresholdStopBouncing)
                {                                                         //the speed after the bounce is small enough to be ignored
                    stopBouncing           = true;
                    velocityCurrentFrame_y = 0;
                }
                MyVector3 horzVelocityCurrentFrame = HorizontalVelocityAfterSliding(t + 0.001f * impactVel_y + 8 * t * (1 - 1 / Mathf.Sqrt(1 + mass)));
                //position ball on top of the ground
                position = MyVector3.Add(newPosition, ground.Normal().Scale(-distanceFromGround));
                MoveGameObject();
                //angularMomentumCurrentFrame set in the X_VelocityAfterSliding() function
                RotateGameObject(t);
                angularMomentumPreviousFrame = angularMomentumCurrentFrame;
                velocityPreviousFrame        = new MyVector3(horzVelocityCurrentFrame.getX(), velocityCurrentFrame_y, horzVelocityCurrentFrame.getZ());
            }
            else
            {//case 4: the ball is bouncing and is in mid-air
                velocityPreviousFrame = velocityCurrentFrame;
                position = newPosition;
                MoveGameObject();
                RotateGameObject(t);
            }
        }
    }
Esempio n. 14
0
 public static MyVector3 Cross(MyVector2 a, MyVector2 b)
 {
     return(MyVector3.Cross(a, b));
 }
Esempio n. 15
0
    // Running the solver - all the joints are iterated through once every frame
    void Update()
    {
        // if the target hasn't been reached
        if (!done)
        {
            // if the Max number of tries hasn't been reached
            if (tries <= Mtries)
            {
                // starting from the second last joint (the last being the end effector)
                // going back up to the root
                for (int i = joints.Length - 2; i >= 0; i--)
                {
                    // The vector from the ith joint to the end effector
                    MyVector3 r1 = new MyVector3(joints[joints.Length - 1].position - joints[i].position);
                    // The vector from the ith joint to the target
                    MyVector3 r2 = tpos - new MyVector3(joints[i].position);

                    // to avoid dividing by tiny numbers
                    if (r1.magnitude * r2.magnitude <= 0.001f)
                    {
                        cos[i] = 1.0f;
                        sin[i] = 0.0f;
                    }
                    else
                    {
                        // find the components using dot and cross product
                        cos[i] = MyVector3.Dot(r1, r2) / (r1.magnitude * r2.magnitude);

                        sin[i] = MyVector3.Cross(r1, r2).magnitude / (r1.magnitude * r2.magnitude);
                    }

                    // The axis of rotation
                    MyVector3 axis = MyVector3.Cross(r1, r2);

                    // find the angle between r1 and r2 (and clamp values if needed avoid errors)
                    theta[i] = Mathf.Acos(cos[i]);

                    //Optional. correct angles if needed, depending on angles invert angle if sin component is negative
                    if (sin[i] < 0)
                    {
                        theta[i] *= -1;
                    }



                    // obtain an angle value between -pi and pi, and then convert to degrees
                    theta[i] *= Mathf.Rad2Deg;

                    // rotate the ith joint along the axis by theta degrees in the world space.
                    MyQuaternion quat = MyQuaternion.AngleAxis(theta[i], ref axis);

                    Quaternion fQuat = new Quaternion(quat.x, quat.y, quat.z, quat.w);

                    joints[i].rotation = fQuat * joints[i].rotation;
                }

                // increment tries
                tries++;
            }
        }

        // find the difference in the positions of the end effector and the target
        float dif = (tpos - new MyVector3(joints[joints.Length - 1].position)).magnitude;

        // if target is within reach (within epsilon) then the process is done
        if (dif < epsilon)
        {
            done = true;
        }
        // if it isn't, then the process should be repeated
        else
        {
            done = false;
        }

        // the target has moved, reset tries to 0 and change tpos
        if (new MyVector3(targ.position) != tpos)
        {
            tries = 0;
            tpos  = new MyVector3(targ.position);
        }
    }