public void Apply()
        {
            Vector3d Origin    = BendPlane.Origin;
            Vector3d BendAxis1 = BendPlane.Z;

            float sideSign = (BendAngle > 0) ? 1 : -1;
            MeshVertexSelection vertices = new MeshVertexSelection(Mesh);

            foreach (int vid in Mesh.VertexIndices())
            {
                Vector3d v    = Mesh.GetVertex(vid);
                float    sign = BendPlane.DistanceToPlaneSigned((Vector3f)v, 1);
                if (sign * sideSign > 0)
                {
                    vertices.Select(vid);
                }
            }

            Quaterniond rotation = Quaterniond.AxisAngleD(BendPlane.X, -BendAngle);

            foreach (int vid in vertices)
            {
                Vector3d v    = Mesh.GetVertex(vid);
                Vector3d vNew = rotation * (v - Origin) + Origin;
                Mesh.SetVertex(vid, vNew);
            }
        }
            public override fMesh MakeGeometry(AxisGizmoFlags widget)
            {
                switch (widget)
                {
                case AxisGizmoFlags.AxisTranslateY:
                    if (MyAxisTranslateY == null)
                    {
                        Radial3DArrowGenerator arrowGen = new Radial3DArrowGenerator()
                        {
                            HeadLength = 2.0f, TipRadius = 0.1f, StickLength = 1.5f, Clockwise = true
                        };
                        DMesh3 mesh = arrowGen.Generate().MakeDMesh();
                        MeshNormals.QuickCompute(mesh);
                        MeshTransforms.Translate(mesh, 0.5 * Vector3d.AxisY);
                        DMesh3 flip = new DMesh3(mesh);
                        MeshTransforms.Rotate(flip, Vector3d.Zero, Quaterniond.AxisAngleD(Vector3d.AxisX, 180));
                        MeshEditor.Append(mesh, flip);
                        MyAxisTranslateY = new fMesh(mesh);
                    }
                    return(MyAxisTranslateY);

                default:
                    return(null);
                }
            }
Beispiel #3
0
 public GridDistanceField()
 {
     Origin   = -100 * Vector3d.One;
     Rotation = Quaterniond.AxisAngleD(Vector3d.AxisX, 45) * Quaterniond.AxisAngleD(Vector3d.AxisZ, 45);
     CellSize = 8.0f;
     Radius   = 1.0f;
 }
Beispiel #4
0
        void update_hole_mesh()
        {
            CappedCylinderGenerator cylgen = new CappedCylinderGenerator()
            {
                BaseRadius = 0.5f, TopRadius = 0.5f, Height = 1, Slices = this.subdivisions,
                Clockwise  = true
            };
            DMesh3 mesh = cylgen.Generate().MakeDMesh();

            MeshTransforms.Rotate(mesh, Vector3d.Zero, Quaterniond.AxisAngleD(Vector3d.AxisX, 90));
            CavityPreviewSO.ReplaceMesh(mesh, true);
        }
Beispiel #5
0
        /// <summary>
        /// Cut through-hole either vertically or horizontally.
        ///
        /// One current failure mode is if we get more than two ray-hits, which
        /// can happen due pathological cases or unexpected mesh shape. Currently
        /// trying to handle the pathological cases (ie ray hits adjacent triangles cases)
        /// via sorting, not sure if this works spectacularly well.
        ///
        /// </summary>
        protected bool CutThroughHole(DMesh3 mesh, HoleInfo hi, Vector3d translate)
        {
            Vector3d basePoint = CombinedBounds.Center - CombinedBounds.Extents.y * Vector3d.AxisY + translate;

            // do we need to compute spatial DS for each hole? not super efficient...
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);

            Vector3d origin    = Vector3d.Zero;
            Vector3d direction = Vector3d.One;

            if (hi.IsVertical)
            {
                direction = Vector3d.AxisY;
                origin    = basePoint + new Vector3d(hi.XZOffset.x, 0, hi.XZOffset.y) - 100 * direction;
            }
            else
            {
                origin    = basePoint + hi.Height * Vector3d.AxisY;
                direction = Quaterniond.AxisAngleD(Vector3d.AxisY, hi.AroundAngle) * Vector3d.AxisX;
            }

            // Find upper and lower triangles that contain center-points of
            // holes we want to cut. This is the most error-prone part
            // because we depend on ray-hits, which is not very reliable...

            Ray3d ray1 = new Ray3d(origin, direction);
            Ray3d ray2 = new Ray3d(origin + 10000 * direction, -direction);

            if (hi.GroupIDFilters.a > 0)
            {
                spatial.TriangleFilterF = (tid) => {
                    return(mesh.GetTriangleGroup(tid) == hi.GroupIDFilters.a);
                };
            }
            int hit_1 = spatial.FindNearestHitTriangle(ray1);

            spatial.TriangleFilterF = null;

            if (hi.GroupIDFilters.b > 0)
            {
                spatial.TriangleFilterF = (tid) => {
                    return(mesh.GetTriangleGroup(tid) == hi.GroupIDFilters.b);
                };
            }
            int hit_2 = spatial.FindNearestHitTriangle(ray2);

            spatial.TriangleFilterF = null;

            if (hit_1 == DMesh3.InvalidID || hit_2 == DMesh3.InvalidID)
            {
                return(false);
            }
            if (hit_1 == hit_2)
            {
                return(false);
            }

            List <int> hitTris = new List <int>()
            {
                hit_1, hit_2
            };


            Frame3f projectFrame = new Frame3f(ray1.Origin, ray1.Direction);

            int nVerts = 32;

            if (hi.Vertices != 0)
            {
                nVerts = hi.Vertices;
            }
            double    angleShiftRad = hi.AxisAngleD * MathUtil.Deg2Rad;
            Polygon2d circle        = Polygon2d.MakeCircle(hi.Radius, nVerts, angleShiftRad);


            List <EdgeLoop> edgeLoops = new List <EdgeLoop>();

            foreach (int hit_tid in hitTris)
            {
                try {
                    MeshInsertProjectedPolygon insert = new MeshInsertProjectedPolygon(mesh, circle, projectFrame, hit_tid)
                    {
                        SimplifyInsertion = true
                    };
                    if (insert.Insert())
                    {
                        // if we have extra edges just randomly collapse
                        EdgeLoop loop = insert.InsertedLoop;

                        if (loop.VertexCount > circle.VertexCount)
                        {
                            loop = simplify_loop(mesh, loop, circle.VertexCount);
                        }

                        edgeLoops.Add(loop);
                    }
                    else
                    {
                        f3.DebugUtil.Log("insert.Insert() failed!!");
                        return(false);
                    }
                } catch (Exception e) {
                    // ignore this loop but we might already be in trouble...
                    f3.DebugUtil.Log("insert.Insert() threw exception for hole {0}!!", hi.nHole);
                    f3.DebugUtil.Log(e.Message);
                }
            }
            if (edgeLoops.Count != 2)
            {
                return(false);
            }

            try {
                MeshEditor editor = new MeshEditor(mesh);
                EdgeLoop   l0     = edgeLoops[0];
                EdgeLoop   l1     = edgeLoops[1];
                l1.Reverse();
                editor.StitchVertexLoops_NearestV(l0.Vertices, l1.Vertices);

                // split edges around the holes we cut. This is helpful
                // if we are going to do additional operations in these areas,
                // as it gives us extra rings to work with
                //MeshEdgeSelection edges = new MeshEdgeSelection(mesh);
                //edges.SelectVertexEdges(l0.Vertices);
                //edges.SelectVertexEdges(l1.Vertices);
                //DMesh3.EdgeSplitInfo splitInfo;
                //foreach ( int eid in edges )
                //    mesh.SplitEdge(eid, out splitInfo);

                return(true);
            } catch {
                f3.DebugUtil.Log("stitch threw exception!");
                return(false);
            }
        }
Beispiel #6
0
        public static void test_Matrix3d()
        {
            {
                Matrix3d Identity = new Matrix3d(true);
                for (int r = 0; r < 3; ++r)
                {
                    for (int c = 0; c < 3; ++c)
                    {
                        Util.gDevAssert((r == c) ? Identity[r, c] == 1 : Identity[r, c] == 0);
                    }
                }
            }

            {
                double[] buffer = new double[9] {
                    1, 2, 3, 4, 5, 6, 7, 8, 9
                };
                Matrix3d M = new Matrix3d(buffer);
                for (int r = 0; r < 3; ++r)
                {
                    for (int c = 0; c < 3; ++c)
                    {
                        Util.gDevAssert(M[r, c] == buffer[r * 3 + c]);
                    }
                }
                for (int k = 0; k < 9; ++k)
                {
                    Util.gDevAssert(M[k] == buffer[k]);
                }

                Matrix3d M2 = new Matrix3d(new Vector3d(1, 2, 3), new Vector3d(4, 5, 6), new Vector3d(7, 8, 9), true);
                Util.gDevAssert(M.EpsilonEqual(M2, 0));
                Matrix3d M3 = new Matrix3d(new Vector3d(1, 4, 7), new Vector3d(2, 5, 8), new Vector3d(3, 6, 9), false);
                Util.gDevAssert(M.EpsilonEqual(M3, 0));

                Util.gDevAssert(M.Transpose().Transpose().EpsilonEqual(M, 0));
                Util.gDevAssert(M.EpsilonEqual(new Matrix3d(M.ToBuffer()), 0));

                Matrix3d Det = new Matrix3d(6, 1, 1, 4, -2, 5, 2, 8, 7);
                Util.gDevAssert(Det.Determinant == -306);

                Matrix3d Mult       = M * M;
                Matrix3d MultResult = new Matrix3d(30, 36, 42, 66, 81, 96, 102, 126, 150);
                Util.gDevAssert(Mult.EpsilonEqual(MultResult, 0));

                Matrix3d Mult2 = new Matrix3d(M * M.Column(0), M * M.Column(1), M * M.Column(2), false);
                Util.gDevAssert(Mult2.EpsilonEqual(MultResult, 0));
            }


            {
                Random     r       = new Random(31337);
                Vector3d[] axes    = TestUtil.RandomPoints3(100, r, Vector3d.Zero);
                double[]   angles  = TestUtil.RandomScalars(100, r, new Interval1d(-180, 180));
                Vector3d[] testPts = TestUtil.RandomPoints3(100, r, Vector3d.Zero, 10);

                for (int k = 0; k < angles.Length; ++k)
                {
                    Vector3d    axis     = axes[k].Normalized;
                    double      angle    = angles[k];
                    Vector3d    pt       = testPts[k];
                    Matrix3d    MRotAxis = Matrix3d.AxisAngleD(axis, angle);
                    Quaterniond QRotAxis = Quaterniond.AxisAngleD(axis, angle);
                    Util.gDevAssert(
                        (MRotAxis * pt).EpsilonEqual(QRotAxis * pt, 100 * MathUtil.Epsilon));

                    Matrix3d QRotAxisM = QRotAxis.ToRotationMatrix();
                    Util.gDevAssert(MRotAxis.EpsilonEqual(QRotAxisM, 10 * MathUtil.Epsilon));

                    Quaterniond QuatCons = new Quaterniond(MRotAxis);
                    Util.gDevAssert(
                        (QuatCons * pt).EpsilonEqual(QRotAxis * pt, 100 * MathUtil.Epsilon));


                    // test 3x3 SVD

                    Matrix3d tmpM = MRotAxis;
                    tmpM[0, 0] += 0.0001; tmpM[1, 1] -= 0.0001; tmpM[0, 2] += 0.1;

                    SingularValueDecomposition fullsvd = new SingularValueDecomposition(3, 3, 999);
                    uint     result = fullsvd.Solve(tmpM.ToBuffer(), -1);
                    double[] U      = new double[9], V = new double[9], S = new double[3];
                    fullsvd.GetU(U); fullsvd.GetV(V);
                    fullsvd.GetSingularValues(S);
                    Matrix3d MU = new Matrix3d(U), MV = new Matrix3d(V);
                    Matrix3d Sdiag = new Matrix3d(S[0], S[1], S[2]);

                    // U is eigenvectors of ATA, V is eigenvectors of AAT
                    Vector3d rRight = Vector3d.Zero, rLeft = Vector3d.Zero;
                    Matrix3d ATA = tmpM.Transpose() * tmpM, AAT = tmpM * tmpM.Transpose();
                    for (int j = 0; j < 3; ++j)
                    {
                        double   eval       = Sdiag[j, j] * Sdiag[j, j];
                        Vector3d right_evec = MV.Column(j);
                        rRight[j] = (ATA * right_evec - eval * right_evec).Length;
                        Vector3d left_evec = MU.Column(j);
                        rLeft[j] = (AAT * left_evec - eval * left_evec).Length;
                    }
                    Util.gDevAssert(rRight.Length < MathUtil.ZeroTolerancef && rLeft.Length < MathUtil.ZeroTolerancef);

                    // [RMS] if U or V contains a reflection, we need to get rid of it
                    if (MU.Determinant < 0)
                    {
                        MU    *= -1;
                        Sdiag *= -1;
                    }
                    if (MV.Determinant < 0)
                    {
                        MV    *= -1;
                        Sdiag *= -1;
                    }

                    Matrix3d MRecons = MU * Sdiag * MV.Transpose();
                    Util.gDevAssert((tmpM * pt).EpsilonEqual(MRecons * pt, 1000 * MathUtil.Epsilon));

                    Quaterniond qU = new Quaterniond(MU);
                    Util.gDevAssert((MU * pt).EpsilonEqual(qU * pt, 100 * MathUtil.Epsilon));
                    Quaterniond qV = new Quaterniond(MV.Transpose());
                    Util.gDevAssert((MV.Transpose() * pt).EpsilonEqual(qV * pt, 100 * MathUtil.Epsilon));
                    Vector3d ptQ = qU * (Sdiag * (qV * pt));
                    Util.gDevAssert((tmpM * pt).EpsilonEqual(ptQ, 1000 * MathUtil.Epsilon));

                    Matrix3d MQRecons = qU.ToRotationMatrix() * Sdiag * qV.ToRotationMatrix();
                    Util.gDevAssert((tmpM * pt).EpsilonEqual(MQRecons * pt, 1000 * MathUtil.Epsilon));


                    // U is eigenvectors of ATA, V is eigenvectors of AAT
                    Vector3d qRight = Vector3d.Zero, qLeft = Vector3d.Zero;
                    for (int j = 0; j < 3; ++j)
                    {
                        double   eval       = Sdiag[j, j] * Sdiag[j, j];
                        Vector3d right_evec = qV.Conjugate().ToRotationMatrix().Column(j);
                        qRight[j] = (ATA * right_evec - eval * right_evec).Length;
                        Vector3d left_evec = qU.ToRotationMatrix().Column(j);
                        qLeft[j] = (AAT * left_evec - eval * left_evec).Length;
                    }
                    Util.gDevAssert(qRight.Length < MathUtil.ZeroTolerancef && qLeft.Length < MathUtil.ZeroTolerancef);


                    double fast_eps = 0.001;

                    FastQuaternionSVD svd      = new FastQuaternionSVD(tmpM, MathUtil.Epsilon, 4);
                    Matrix3d          QQRecons = svd.ReconstructMatrix();
                    Util.gDevAssert((tmpM * pt).EpsilonEqual(QQRecons * pt, fast_eps));

                    Matrix3d svdS = new Matrix3d(svd.S[0], svd.S[1], svd.S[2]);

                    Matrix3d QQRecons2 =
                        svd.U.ToRotationMatrix() * svdS * svd.V.Conjugate().ToRotationMatrix();
                    Util.gDevAssert((tmpM * pt).EpsilonEqual(QQRecons2 * pt, fast_eps));

                    Vector3d ptQSVD = svd.U * (svdS * (svd.V.Conjugate() * pt));
                    Util.gDevAssert((tmpM * pt).EpsilonEqual(ptQSVD, fast_eps));

                    // U is eigenvectors of ATA, V is eigenvectors of AAT
                    Vector3d qqRight = Vector3d.Zero, qqLeft = Vector3d.Zero;
                    for (int j = 0; j < 3; ++j)
                    {
                        double   eval       = svdS[j, j] * svdS[j, j];
                        Vector3d right_evec = svd.V.ToRotationMatrix().Column(j);
                        qqRight[j] = (ATA * right_evec - eval * right_evec).Length;
                        Vector3d left_evec = svd.U.ToRotationMatrix().Column(j);
                        qqLeft[j] = (AAT * left_evec - eval * left_evec).Length;
                    }
                    Util.gDevAssert(qqRight.Length < fast_eps && qqLeft.Length < fast_eps);
                }
            }
        }