예제 #1
0
        public static List <InterpolationTransform> GetTransforms_UpRef(_Curve curve, List <float> tValues, Vector3 upRef)
        {
            List <InterpolationTransform> orientations = new List <InterpolationTransform>();

            foreach (float t in tValues)
            {
                InterpolationTransform transform = InterpolationTransform.GetTransform_UpRef(curve, t, upRef);

                orientations.Add(transform);
            }

            return(orientations);
        }
예제 #2
0
        public static List <InterpolationTransform> GetTransforms_FrenetNormal(_Curve curve, List <float> tValues)
        {
            List <InterpolationTransform> transforms = new List <InterpolationTransform>();

            foreach (float t in tValues)
            {
                InterpolationTransform transform = InterpolationTransform.GetTransform_FrenetNormal(curve, t);

                transforms.Add(transform);
            }

            return(transforms);
        }
예제 #3
0
        public static List <InterpolationTransform> GetTransforms_InterpolateBetweenUpVectors(
            _Curve curve, List <float> tValues, Vector3 upRefStart, Vector3 upRefEnd)
        {
            List <InterpolationTransform> transforms = new List <InterpolationTransform>();

            foreach (float t in tValues)
            {
                InterpolationTransform transform = InterpolationTransform.GetTransform_InterpolateBetweenUpVectors(curve, t, upRefStart, upRefEnd);

                transforms.Add(transform);
            }

            return(transforms);
        }
예제 #4
0
        public static InterpolationTransform GetTransform_FrenetNormal(_Curve curve, float t)
        {
            //Position on the curve at point t
            Vector3 pos = curve.GetPosition(t);

            //Forward direction (tangent) on the curve at point t
            Vector3 forwardDir = curve.GetTangent(t);

            Vector3 secondDerivativeVec = curve.GetSecondDerivativeVec(t);

            MyQuaternion orientation = InterpolationTransform.GetOrientation_FrenetNormal(forwardDir, secondDerivativeVec);


            InterpolationTransform trans = new InterpolationTransform(pos, orientation);

            return(trans);
        }
예제 #5
0
        //
        // Alternative 1.5. Similar to Alternative 1, but we know the up vector at both the start and end position
        //

        public static InterpolationTransform GetTransform_InterpolateBetweenUpVectors(
            _Curve curve, float t, Vector3 upRefStart, Vector3 upRefEnd)
        {
            //Position on the curve at point t
            Vector3 pos = curve.GetPosition(t);

            //Forward direction (tangent) on the curve at point t
            Vector3 forwardDir = curve.GetTangent(t);

            //Interpolate between the start and end up vector to get an up vector at a t position
            Vector3 interpolatedUpDir = Vector3.Normalize(BezierLinear.GetPosition(upRefStart, upRefEnd, t));

            MyQuaternion orientation = InterpolationTransform.GetOrientation_UpRef(forwardDir, interpolatedUpDir);

            InterpolationTransform trans = new InterpolationTransform(pos, orientation);

            return(trans);
        }
예제 #6
0
        public static InterpolationTransform GetTransform_UpRef(_Curve curve, float t, Vector3 upRef)
        {
            //Position on the curve at point t
            Vector3 pos = curve.GetPosition(t);

            //Forward direction (tangent) on the curve at point t
            Vector3 forwardDir = curve.GetTangent(t);

            //A simple way to get the other directions is to use LookRotation with just forward dir as parameter
            //Then the up direction will always be the world up direction, and it calculates the right direction
            //This idea is not working for all possible curve orientations
            //MyQuaternion orientation = new MyQuaternion(forwardDir);

            //Your own reference up vector
            MyQuaternion orientation = InterpolationTransform.GetOrientation_UpRef(forwardDir, upRef);

            InterpolationTransform trans = new InterpolationTransform(pos, orientation);

            return(trans);
        }
예제 #7
0
        //
        // Get a Transform (includes position and orientation) at point t
        //
        public InterpolationTransform GetTransform(float t)
        {
            //Same as when we calculate t
            MyVector3 interpolation_1_2 = _Interpolation.BezierQuadratic(posA, handleB, handleA, t);
            MyVector3 interpolation_2_3 = _Interpolation.BezierQuadratic(posA, posB, handleB, t);

            MyVector3 finalInterpolation = _Interpolation.BezierLinear(interpolation_1_2, interpolation_2_3, t);

            //This direction is always tangent to the curve
            MyVector3 forwardDir = MyVector3.Normalize(interpolation_2_3 - interpolation_1_2);

            //A simple way to get the other directions is to use LookRotation with just forward dir as parameter
            //Then the up direction will always be the world up direction, and it calculates the right direction
            Quaternion orientation = Quaternion.LookRotation(forwardDir.ToVector3());


            InterpolationTransform trans = new InterpolationTransform(finalInterpolation, orientation);

            return(trans);
        }
예제 #8
0
        //Not defined for a single point, you always need a previous transform
        //public static InterpolationTransform InterpolationTransform GetTransform_RotationMinimisingFrame()
        //{

        //}


        public static List <InterpolationTransform> GetTransforms_RotationMinimisingFrame(_Curve curve, List <float> tValues, Vector3 upRef)
        {
            List <InterpolationTransform> transforms = new List <InterpolationTransform>();

            for (int i = 0; i < tValues.Count; i++)
            {
                float t = tValues[i];

                //Position on the curve at point t
                Vector3 position = curve.GetPosition(t);

                //Forward direction (tangent) on the curve at point t
                Vector3 tangent = curve.GetTangent(t);

                //At first pos we dont have a previous transform
                if (i == 0)
                {
                    //Just use one of the other algorithms available to generate a transform at a single position
                    MyQuaternion orientation = InterpolationTransform.GetOrientation_UpRef(tangent, upRef);

                    InterpolationTransform transform = new InterpolationTransform(position, orientation);

                    transforms.Add(transform);
                }
                else
                {
                    //To calculate the orientation for this point, we need data from the previous point on the curve
                    InterpolationTransform previousTransform = transforms[i - 1];

                    MyQuaternion orientation = InterpolationTransform.GetOrientation_RotationFrame(position, tangent, previousTransform);

                    InterpolationTransform transform = new InterpolationTransform(position, orientation);

                    transforms.Add(transform);
                }
            }

            return(transforms);
        }
예제 #9
0
        //Generate a mesh
        public static Mesh GenerateMesh(List <InterpolationTransform> transforms, MeshProfile profile, float profileScale)
        {
            if (profile == null)
            {
                Debug.Log("You need to assign a mesh profile");

                return(null);
            }

            if (transforms == null || transforms.Count <= 1)
            {
                Debug.Log("You need more transforms");

                return(null);
            }


            //Test that the profile is correct
            //InterpolationTransform testTrans = transforms[1];

            //DisplayMeshProfile(profile, testTrans, profileScale);

            //Vertices
            List <UnityEngine.Vector3> vertices = new List <UnityEngine.Vector3>();

            //Normals
            List <UnityEngine.Vector3> normals = new List <UnityEngine.Vector3>();

            for (int step = 0; step < transforms.Count; step++)
            {
                InterpolationTransform thisTransform = transforms[step];

                for (int i = 0; i < profile.vertices.Length; i++)
                {
                    MyVector2 localPos2d = profile.vertices[i].point;

                    Vector3 localPos = new Vector3(localPos2d.x, localPos2d.y, 0f);

                    Vector3 pos = thisTransform.LocalToWorld_Pos(localPos * profileScale);

                    vertices.Add(pos.ToVector3());


                    //Normals
                    MyVector2 localNormal2d = profile.vertices[i].normal;

                    Vector3 localNormal = new Vector3(localNormal2d.x, localNormal2d.y, 0f);

                    Vector3 normal = thisTransform.LocalToWorld_Dir(localNormal);

                    normals.Add(normal.ToVector3());
                }
            }

            //Triangles
            List <int> triangles = new List <int>();

            //We connect the first transform with the next transform, ignoring the last transform because it doesnt have a next
            for (int step = 0; step < transforms.Count - 1; step++)
            {
                //The index where this profile starts in the list of all vertices in the entire mesh
                int profileIndexThis = step * profile.vertices.Length;
                //The index where the next profile starts
                int profileIndexNext = (step + 1) * profile.vertices.Length;

                //Each line has 2 points
                for (int line = 0; line < profile.lineIndices.Length; line++)
                {
                    int lineIndexA = profile.lineIndices[line].x;
                    int lineIndexB = profile.lineIndices[line].y;

                    //Now we can identify the vertex we need in the list of all vertices in the entire mesh
                    //The current profile
                    int thisA = profileIndexThis + lineIndexA;
                    int thisB = profileIndexThis + lineIndexB;
                    //The next profile
                    int nextA = profileIndexNext + lineIndexA;
                    int nextB = profileIndexNext + lineIndexB;

                    //Build two triangles
                    triangles.Add(thisA);
                    triangles.Add(nextA);
                    triangles.Add(nextB);

                    triangles.Add(thisB);
                    triangles.Add(thisA);
                    triangles.Add(nextB);
                }
            }

            Mesh mesh = new Mesh();

            mesh.vertices  = vertices.ToArray();
            mesh.triangles = triangles.ToArray();
            mesh.normals   = normals.ToArray();

            //mesh.RecalculateNormals();

            return(mesh);
        }
예제 #10
0
        //
        // Alternative 3. Rotation Minimising Frame (also known as "Parallel Transport Frame" or "Bishop Frame")
        //

        //Gets its stability by incrementally rotating a coordinate system (= frame) as it is translate along the curve
        //Has to be computed for the entire curve because we need the previous frame (previousTransform) belonging to a point before this point
        //Is initalized by using "Fixed Up" or "Frenet Normal"
        public static MyQuaternion GetOrientation_RotationFrame(Vector3 position, Vector3 tangent, InterpolationTransform previousTransform)
        {
            /*
             * //This version is from https://pomax.github.io/bezierinfo/#pointvectors3d
             * //Reflect the known frame onto the next point, by treating the plane through the curve at the point exactly between the next and previous points as a "mirror"
             * MyVector3 v1 = position - previousTransform.position;
             *
             * float c1 = MyVector3.Dot(v1, v1);
             *
             * MyVector3 riL = previousTransform.Right - v1 * (2f / c1) * MyVector3.Dot(v1, previousTransform.Right);
             *
             * MyVector3 tiL = previousTransform.Forward - v1 * (2f / c1) * MyVector3.Dot(v1, previousTransform.Forward);
             *
             * //This gives the next point a tangent vector that's essentially pointing in the opposite direction of what it should be, and a normal that's slightly off-kilter
             * //reflect the vectors of our "mirrored frame" a second time, but this time using the plane through the "next point" itself as "mirror".
             * MyVector3 v2 = tangent - tiL;
             *
             * float c2 = MyVector3.Dot(v2, v2);
             *
             * //Now we can calculate the normal and right vector belonging to this orientation
             * MyVector3 right = riL - v2 * (2f / c2) * MyVector3.Dot(v2, riL);
             *
             * //The source has right x tangent, but then every second normal is flipped
             * MyVector3 normal = MyVector3.Cross(tangent, right);
             *
             * MyQuaternion orientation = new MyQuaternion(tangent, normal);
             */


            //This version is from Game Programming Gems 2: The Parallel Transport Frame
            //They generate the same result and this one is easier to understand

            //The two tangents
            Vector3 T1 = previousTransform.Forward;
            Vector3 T2 = tangent;

            //You move T1 to the new position, so A is a vector going from the new position
            Vector3 A = Vector3.Cross(T1, T2);

            //This is the angle between T1 and T2
            float alpha = Mathf.Acos(Vector3.Dot(T1, T2) / (Vector3.Magnitude(T1) * Vector3.Magnitude(T2)));

            //Now rotate the previous frame around axis A with angle alpha
            MyQuaternion F1 = previousTransform.orientation;

            MyQuaternion F2 = MyQuaternion.RotateQuaternion(F1, alpha * Mathf.Rad2Deg, A);

            MyQuaternion orientation = F2;


            return(orientation);
        }