Esempio n. 1
0
 public UnwrapIter(int triIndex, Mat4HighPrecision transform, Edge edgeToUnwrap, int unwrappedInd0, int unwrappedInd1)
 {
     this.TriIndex      = triIndex;
     this.Transform     = transform;
     this.EdgeToUnwrap  = edgeToUnwrap;
     this.UnwrappedInd0 = unwrappedInd0;
     this.UnwrappedInd1 = unwrappedInd1;
 }
Esempio n. 2
0
        public void TestMat()
        {
            var a = new Mat4HighPrecision(1, 2, 3, 4,
                                          5, 6, 7, 8,
                                          9, 10, 11, 12,
                                          13, 14, 15, 16);

            Assert.AreEqual(new Vec4(1, 2, 3, 4), a.Row0);
            Assert.AreEqual(new Vec4(5, 6, 7, 8), a.Row1);
            Assert.AreEqual(new Vec4(9, 10, 11, 12), a.Row2);
            Assert.AreEqual(new Vec4(13, 14, 15, 16), a.Row3);

            Assert.AreEqual(new Vec4(1, 5, 9, 13), a.Col0);
            Assert.AreEqual(new Vec4(2, 6, 10, 14), a.Col1);
            Assert.AreEqual(new Vec4(3, 7, 11, 15), a.Col2);
            Assert.AreEqual(new Vec4(4, 8, 12, 16), a.Col3);

            Assert.AreEqual(Mat4HighPrecision.I(), Mat4HighPrecision.I() * Mat4HighPrecision.I());
            Assert.AreEqual(a, a * Mat4HighPrecision.I());
        }
Esempio n. 3
0
        public void TestAngleAxis()
        {
            Assert.AreEqual(
                new Vec3HighPrecision(0, 0, 1),
                (new Vec4(0, 0, -1, 0) * Mat4HighPrecision.AngleAxisRot(new Vec3HighPrecision(0, 1, 0), -1.0, 0.0)).ToVec3() // PI = -1
                );

            Vec3HighPrecision.AssertAreEqual(
                new Vec3HighPrecision(-1, 0, 0),
                (new Vec4(0, 0, -1, 0) * Mat4HighPrecision.AngleAxisRot(new Vec3HighPrecision(0, 1, 0), 0.0, 1.0)).ToVec3(), // PI/2 = 0
                "Rotation by 90 degrees along Y axis failed");

            Vec3HighPrecision.AssertAreEqual(
                new Vec3HighPrecision(1, 0, 0),
                (new Vec4(0, 0, -1, 0) * Mat4HighPrecision.AngleAxisRot(new Vec3HighPrecision(0, 1, 0), 0.0, -1.0)).ToVec3(), // -PI/2 = 0
                "Rotation by -90 degrees along Y axis failed");

            Vec3HighPrecision.AssertAreEqual(
                new Vec3HighPrecision(0, -1, 0),
                (new Vec4(0, 0, -1, 0) * Mat4HighPrecision.AngleAxisRot(new Vec3HighPrecision(1, 0, 0), 0.0, -1.0)).ToVec3(), // -PI/2 = 0
                "Rotation by 90 degrees along X axis failed");

            var rnd = new System.Random();

            for (int i = 0; i < 100; i++)
            {
                var k = (new Vec3HighPrecision(rnd.NextDouble(), rnd.NextDouble(), rnd.NextDouble()) -
                         new Vec3HighPrecision(0.5, 0.5, 0.5)) * 100.0;
                var v = (new Vec3HighPrecision(rnd.NextDouble(), rnd.NextDouble(), rnd.NextDouble()) -
                         new Vec3HighPrecision(0.5, 0.5, 0.5)) * 100.0;
                var a     = rnd.NextDouble() * Math.PI * 2.0 - Math.PI;
                var vr    = (new Vec4(v, 1.0) * Mat4HighPrecision.AngleAxisRot(k.Normalized, Math.Cos(a), Math.Sin(a))).ToVec3();
                var vproj = k.Normalized * Vec3HighPrecision.Dot(v, k.Normalized);
                var ang   = Math.Acos(Vec3HighPrecision.Dot((vproj - v).Normalized, (vproj - vr).Normalized));
                Assert.That(Math.Abs(a), Is.EqualTo(ang).Within(0.00001), "Random rotation around random axis failed.");
            }
        }
Esempio n. 4
0
 static void EnqueueNeighborTriangles(int currTriIndex, Tri t, Mat4HighPrecision ntf, int v0, int v1, int v2, Action <UnwrapIter> pushAction, Dictionary <Edge, EdgeTris> connections)
 {
     pushAction(new UnwrapIter(GetNeighborTriangle(currTriIndex, connections[new Edge(t.p0, t.p1)]), ntf, new Edge(t.p0, t.p1), v0, v1));
     pushAction(new UnwrapIter(GetNeighborTriangle(currTriIndex, connections[new Edge(t.p1, t.p2)]), ntf, new Edge(t.p1, t.p2), v1, v2));
     pushAction(new UnwrapIter(GetNeighborTriangle(currTriIndex, connections[new Edge(t.p2, t.p0)]), ntf, new Edge(t.p2, t.p0), v2, v0));
 }
Esempio n. 5
0
        static UnwrappedMesh MakeUnwrappedMesh(IReadOnlyList <Vec3> vertices, IReadOnlyList <Tri> triangles, Action <UnwrapIter> pushAction, Func <UnwrapIter> popAction)
        {
            var connections = GenerateEdgeConnections(triangles);

            int firstTri = 0;

            if (triangles.Count <= firstTri)
            {
                throw new Exception("firstTri out of bounds");
            }

            // transform first triangle on XZ plane
            Mat4HighPrecision firstRot;
            {
                var tri = triangles[firstTri];
                var p0  = vertices[tri.p0];
                var p1  = vertices[tri.p1];
                var p2  = vertices[tri.p2];
                var e0  = p1 - p0;
                var e1  = p2 - p0;
                var n   = Vec3.Cross(e0, e1);
                firstRot = Mat4HighPrecision.Axes(e0.Normalized, n.Normalized, Vec3.Cross(e0, n).Normalized).Transposed();
            }

            var firstTf = firstRot;

            var firstEdge = new Edge(triangles[firstTri].p0, triangles[firstTri].p1);

            var         iteratedTris       = new HashSet <int>();
            List <Vec3> unwrappedVertices  = new List <Vec3>();
            List <Vec3> originalVertices   = new List <Vec3>();
            List <Tri>  unwrappedTriangles = new List <Tri>();

            originalVertices.Add(vertices[firstEdge.p0]);
            originalVertices.Add(vertices[firstEdge.p1]);
            unwrappedVertices.Add((new Vec4(vertices[firstEdge.p0], 1.0) * firstRot).ToVec3());
            unwrappedVertices.Add((new Vec4(vertices[firstEdge.p1], 1.0) * firstRot).ToVec3());

            pushAction(new UnwrapIter(firstTri, firstTf, firstEdge, 1, 0));

            int N = 0;

            while (unwrappedTriangles.Count < triangles.Count)
            {
                var i = popAction();
                if (iteratedTris.Contains(i.TriIndex))
                {
                    continue;
                }
                if (i.TriIndex >= triangles.Count)
                {
                    throw new Exception("TriIndex " + i.TriIndex + " out of bounds, triangle count: " + triangles.Count);
                }
                iteratedTris.Add(i.TriIndex);
                var t = triangles[i.TriIndex];

                var a = vertices[t.p0];
                var b = vertices[t.p1];
                var c = vertices[t.p2];

                var p0 = (new Vec4(a, 1.0) * i.Transform).ToVec3();
                var p1 = (new Vec4(b, 1.0) * i.Transform).ToVec3();
                var p2 = (new Vec4(c, 1.0) * i.Transform).ToVec3();

                var e01 = i.EdgeToUnwrap.Equals(new Edge(t.p0, t.p1));
                var e12 = i.EdgeToUnwrap.Equals(new Edge(t.p1, t.p2));
                var e20 = i.EdgeToUnwrap.Equals(new Edge(t.p2, t.p0));

                //AssertOnXZPlane(p0,p1,p2, string.Format("Failed after dequeue, N={0}", N));

                Vec3HighPrecision e0, e1, mp;
                if (e01)
                {
                    e0 = p1 - p0;
                    e1 = p2 - p0;
                    mp = (p1 + p0) * 0.5;
                }
                else if (e12)
                {
                    e0 = p2 - p1;
                    e1 = p0 - p1;
                    mp = (p2 + p1) * 0.5;
                }
                else if (e20)
                {
                    e0 = p0 - p2;
                    e1 = p1 - p2;
                    mp = (p0 + p2) * 0.5;
                }
                else
                {
                    throw new Exception("Unreachable code executed.");
                }

                var n      = Vec3.Cross(e0, e1).Normalized;
                var rotDir = Math.Sign(Vec3.Dot(Vec3.Cross(n, new Vec3(0, 1, 0)), e0));

                // rotate next triangle to XZ plane rotating around the shared edge with the previous triangle (which is already on XZ plane)
                var rot = Mat4HighPrecision.Translate(mp * -1.0) *
                          Mat4HighPrecision.AngleAxisRot(e0.Normalized, n.Y, Math.Sqrt(1 - n.Y * n.Y) * rotDir) *
                          Mat4HighPrecision.Translate(mp * 1.0);

                var ntf = i.Transform * rot;

                var np0 = (new Vec4(a, 1.0) * ntf).ToVec3();
                var np1 = (new Vec4(b, 1.0) * ntf).ToVec3();
                var np2 = (new Vec4(c, 1.0) * ntf).ToVec3();

                int v0, v1, v2;
                if (e01)
                {
                    v0 = i.UnwrappedInd1;
                    v1 = i.UnwrappedInd0;
                    v2 = unwrappedVertices.Count;
                    unwrappedVertices.Add(np2);
                    originalVertices.Add(c);
                }
                else if (e12)
                {
                    v0 = unwrappedVertices.Count;
                    v1 = i.UnwrappedInd1;
                    v2 = i.UnwrappedInd0;
                    unwrappedVertices.Add(np0);
                    originalVertices.Add(a);
                }
                else if (e20)
                {
                    v0 = i.UnwrappedInd0;
                    v1 = unwrappedVertices.Count;
                    v2 = i.UnwrappedInd1;
                    unwrappedVertices.Add(np1);
                    originalVertices.Add(b);
                }
                else
                {
                    throw new Exception("Unreachable code executed.");
                }

                unwrappedTriangles.Add(new Tri(v0, v1, v2));

                EnqueueNeighborTriangles(i.TriIndex, t, ntf, v0, v1, v2, pushAction, connections);

                N++;
            }

            return(new UnwrappedMesh {
                Vertices = unwrappedVertices,
                Triangles = unwrappedTriangles,
                VerticesOriginalPositions = originalVertices
            });
        }