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); }
public HalfEdgeVertex3(MyVector3 position, MyVector3 normal) { this.position = position; this.normal = normal; }
public Plane3(MyVector3 pos, MyVector3 normal) { this.pos = pos; this.normal = normal; }
// // 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); }
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); }
//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); }
public Triangle3(MyVector3 p1, MyVector3 p2, MyVector3 p3) { this.p1 = p1; this.p2 = p2; this.p3 = p3; }