public InterpolationTransform(MyVector3 position, MyQuaternion orientation)
 {
     this.position    = position;
     this.orientation = orientation;
 }
        public static float SqrMagnitude(MyVector3 a)
        {
            float sqrMagnitude = (a.x * a.x) + (a.y * a.y) + (a.z * a.z);

            return(sqrMagnitude);
        }
        public static float SqrDistance(MyVector3 a, MyVector3 b)
        {
            float distance = SqrMagnitude(a - b);

            return(distance);
        }
 public MyQuaternion(MyVector3 forward, MyVector3 up)
 {
     this.unityQuaternion = Quaternion.LookRotation(forward.ToVector3(), up.ToVector3());
 }
        public static float Magnitude(MyVector3 a)
        {
            float magnitude = Mathf.Sqrt(SqrMagnitude(a));

            return(magnitude);
        }
        //
        // Transform between coordinate systems
        //

        //Transform a position from local to world
        //If input is MyVector3.Right * 2f then we should get a point in world space on the curve
        //at this position moved along the local x-axis 2m
        public MyVector3 LocalToWorld_Pos(MyVector3 localPos)
        {
            MyVector3 worldPos = position + MyQuaternion.RotateVector(orientation, localPos);

            return(worldPos);
        }
        public static InterpolationTransform GetTransform_UpRef(_Curve curve, float t, MyVector3 upRef)
        {
            //Position on the curve at point t
            MyVector3 pos = curve.GetPosition(t);

            //Forward direction (tangent) on the curve at point t
            MyVector3 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);
        }
Example #8
0
        public HalfEdgeVertex3(MyVector3 position, MyVector3 normal)
        {
            this.position = position;

            this.normal = normal;
        }
Example #9
0
        public Plane3(MyVector3 pos, MyVector3 normal)
        {
            this.pos = pos;

            this.normal = normal;
        }
Example #10
0
        //
        // Contract an edge if we know we are dealing only with triangles
        //

        //Returns all edge pointing to the new vertex
        public HashSet <HalfEdge3> ContractTriangleHalfEdge(HalfEdge3 e, MyVector3 mergePos, System.Diagnostics.Stopwatch timer = null)
        {
            //Step 1. Get all edges pointing to the vertices we will merge
            //And edge is going TO a vertex, so this edge goes from v1 to v2
            HalfEdgeVertex3 v1 = e.prevEdge.v;
            HalfEdgeVertex3 v2 = e.v;

            //timer.Start();
            //It's better to get these before we remove triangles because then we will get a messed up half-edge system?
            HashSet <HalfEdge3> edgesGoingToVertex_v1 = v1.GetEdgesPointingToVertex(this);
            HashSet <HalfEdge3> edgesGoingToVertex_v2 = v2.GetEdgesPointingToVertex(this);

            //timer.Stop();

            //Step 2. Remove the triangles, which will create a hole,
            //and the edges on the opposite sides of the hole are connected
            RemoveTriangleAndConnectOppositeSides(e);

            //We might also have an opposite triangle, so we may have to delete a total of two triangles
            if (e.oppositeEdge != null)
            {
                RemoveTriangleAndConnectOppositeSides(e.oppositeEdge);
            }


            //Step 3. Move the vertices to the merge position
            //Some of these edges belong to the triangles we removed, but it doesnt matter because this operation is fast

            //We can at the same time find the edges pointing to the new vertex
            HashSet <HalfEdge3> edgesPointingToVertex = new HashSet <HalfEdge3>();

            if (edgesGoingToVertex_v1 != null)
            {
                foreach (HalfEdge3 edgeToV in edgesGoingToVertex_v1)
                {
                    //This edge belonged to one of the faces we removed
                    if (edgeToV.face == null)
                    {
                        continue;
                    }

                    edgeToV.v.position = mergePos;

                    edgesPointingToVertex.Add(edgeToV);
                }
            }
            if (edgesGoingToVertex_v2 != null)
            {
                foreach (HalfEdge3 edgeToV in edgesGoingToVertex_v2)
                {
                    //This edge belonged to one of the faces we removed
                    if (edgeToV.face == null)
                    {
                        continue;
                    }

                    edgeToV.v.position = mergePos;

                    edgesPointingToVertex.Add(edgeToV);
                }
            }


            return(edgesPointingToVertex);
        }
Example #11
0
 public HalfEdgeVertex3(MyVector3 position)
 {
     this.position = position;
 }
        public MyVector3 RotateVector(MyVector3 vec)
        {
            Vector3 rotatedVec = unityQuaternion * vec.ToVector3();

            return(rotatedVec.ToMyVector3());
        }
        //Rotate a vector by using a quaternion
        public static MyVector3 RotateVector(MyQuaternion quat, MyVector3 vec)
        {
            Vector3 rotatedVec = quat.unityQuaternion * vec.ToVector3();

            return(rotatedVec.ToMyVector3());
        }
        //
        // Quaternion operations
        //

        //Rotate a quaternion some degrees around some axis
        public static MyQuaternion RotateQuaternion(MyQuaternion oldQuaternion, float angleInDegrees, MyVector3 rotationAxis)
        {
            Quaternion rotationQuaternion = Quaternion.AngleAxis(angleInDegrees, rotationAxis.ToVector3());

            //To rotate a quaternion you just multiply it with the rotation quaternion
            //Important that rotationQuaternion is first!
            Quaternion newQuaternion = rotationQuaternion * oldQuaternion.unityQuaternion;

            MyQuaternion myNewQuaternion = new MyQuaternion(newQuaternion);

            return(myNewQuaternion);
        }
        //
        // 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(MyVector3 position, MyVector3 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
            MyVector3 T1 = previousTransform.Forward;
            MyVector3 T2 = tangent;

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

            //This is the angle between T1 and T2
            float alpha = Mathf.Acos(MyVector3.Dot(T1, T2) / (MyVector3.Magnitude(T1) * MyVector3.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);
        }
Example #16
0
        //Is this edge intersecting with another edge?
        //public bool isIntersecting = false;

        public Edge3(MyVector3 p1, MyVector3 p2)
        {
            this.p1 = p1;
            this.p2 = p2;
        }
        //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, MyVector3 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
                MyVector3 position = curve.GetPosition(t);

                //Forward direction (tangent) on the curve at point t
                MyVector3 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);
        }
        //
        // Triangle to Unity mesh
        //

        //Version 1. Check that each vertex exists only once in the final mesh
        //Make sure the triangles have the correct orientation
        public static Mesh Triangle3ToCompressedMesh(HashSet <Triangle3> triangles)
        {
            if (triangles == null)
            {
                return(null);
            }


            //Step 2. Create the list with unique vertices
            //A hashset will make it fast to check if a vertex already exists in the collection
            HashSet <MyVector3> uniqueVertices = new HashSet <MyVector3>();

            foreach (Triangle3 t in triangles)
            {
                MyVector3 v1 = t.p1;
                MyVector3 v2 = t.p2;
                MyVector3 v3 = t.p3;

                if (!uniqueVertices.Contains(v1))
                {
                    uniqueVertices.Add(v1);
                }
                if (!uniqueVertices.Contains(v2))
                {
                    uniqueVertices.Add(v2);
                }
                if (!uniqueVertices.Contains(v3))
                {
                    uniqueVertices.Add(v3);
                }
            }

            //Create the list with all vertices
            List <MyVector3> meshVertices = new List <MyVector3>(uniqueVertices);


            //Step3. Create the list with all triangles by using the unique vertices
            List <int> meshTriangles = new List <int>();

            //Use a dictionay to quickly find which positon in the list a Vector3 has
            Dictionary <MyVector3, int> vector2Positons = new Dictionary <MyVector3, int>();

            for (int i = 0; i < meshVertices.Count; i++)
            {
                vector2Positons.Add(meshVertices[i], i);
            }

            foreach (Triangle3 t in triangles)
            {
                MyVector3 v1 = t.p1;
                MyVector3 v2 = t.p2;
                MyVector3 v3 = t.p3;

                meshTriangles.Add(vector2Positons[v1]);
                meshTriangles.Add(vector2Positons[v2]);
                meshTriangles.Add(vector2Positons[v3]);
            }


            //Step4. Create the final mesh
            Mesh mesh = new Mesh();

            //From MyVector3 to Vector3
            Vector3[] meshVerticesArray = new Vector3[meshVertices.Count];

            for (int i = 0; i < meshVerticesArray.Length; i++)
            {
                MyVector3 v = meshVertices[i];

                meshVerticesArray[i] = new Vector3(v.x, v.y, v.z);
            }

            mesh.vertices  = meshVerticesArray;
            mesh.triangles = meshTriangles.ToArray();

            //Should maybe recalculate bounds and normals, maybe better to do that outside this method???
            //mesh.RecalculateBounds();
            //mesh.RecalculateNormals();

            return(mesh);
        }
        //Transform a direction from local to world
        public MyVector3 LocalToWorld_Dir(MyVector3 localDir)
        {
            MyVector3 worldDir = MyQuaternion.RotateVector(orientation, localDir);

            return(worldDir);
        }
        //
        // Vector operations
        //
        public static float Dot(MyVector3 a, MyVector3 b)
        {
            float dotProduct = (a.x * b.x) + (a.y * b.y) + (a.z * b.z);

            return(dotProduct);
        }
        public static List <InterpolationTransform> GetTransforms_UpRef(_Curve curve, List <float> tValues, MyVector3 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);
        }
Example #22
0
 public Triangle3(MyVector3 p1, MyVector3 p2, MyVector3 p3)
 {
     this.p1 = p1;
     this.p2 = p2;
     this.p3 = p3;
 }