Esempio n. 1
0
        /// <summary>
        /// Computes all traits on the mesh.
        /// </summary>
        public void ComputeAllTraits()
        {
            HalfedgeDynamicTrait <double> cornerArea = new HalfedgeDynamicTrait <double>(this);
            VertexDynamicTrait <double>   pointArea  = new VertexDynamicTrait <double>(this);

            ComputeBoundingSphereAndBox();
            ComputePointCornerArea(cornerArea, pointArea);
            ComputeNormals(cornerArea, pointArea);
#if CURVATURE
            ComputePrincipleCurvatures(cornerArea, pointArea);
#endif

            if (!Traits.HasFaceVertexNormals)
            {
                foreach (Halfedge h in Halfedges)
                {
                    h.Traits.Normal = h.ToVertex.Traits.Normal;
                }
            }

            if (Traits.HasTextureCoordinates)
            {
                this.ComputeTangents();
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Computes vertex normals.
        /// </summary>
        public void ComputeNormals()
        {
            HalfedgeDynamicTrait <double> cornerArea = new HalfedgeDynamicTrait <double>(this);
            VertexDynamicTrait <double>   pointArea  = new VertexDynamicTrait <double>(this);

            ComputePointCornerArea(cornerArea, pointArea);
            ComputeNormals(cornerArea, pointArea);
        }
Esempio n. 3
0
        /// <summary>
        /// Computes principle curvatures on the vertices.
        /// </summary>
        public void ComputePrincipleCurvatures()
        {
            HalfedgeDynamicTrait <double> cornerArea = new HalfedgeDynamicTrait <double>(this);
            VertexDynamicTrait <double>   pointArea  = new VertexDynamicTrait <double>(this);

            ComputePointCornerArea(cornerArea, pointArea);
            ComputePrincipleCurvatures(cornerArea, pointArea);
        }
Esempio n. 4
0
        /// <summary>
        /// Computes vertex normals.
        /// </summary>
        /// <param name="cornerArea">A halfedge dynamic trait with face vertex angular areas.</param>
        /// <param name="pointArea">A vertex dynamic trait with vertex angular areas.</param>
        public void ComputeNormals(HalfedgeDynamicTrait <double> cornerArea, VertexDynamicTrait <double> pointArea)
        {
            this.Traits.HasFaceVertexNormals = true;
            FaceDynamicTrait <Vector3D> normal = new FaceDynamicTrait <Vector3D>(this);

            Vertex[] fv = new Vertex[3];

            // Compute normal for each face
            foreach (Face f in Faces)
            {
                int i = 0;
                foreach (Vertex v in f.Vertices)
                {
                    fv[i] = v;
                    ++i;
                }

                // dynamic traits
                // Compute normal for this face
                var n = Vector3D.Cross(fv[2].Traits.Position - fv[1].Traits.Position, fv[0].Traits.Position - fv[2].Traits.Position);
                n.Normalize();

                f.Traits.Normal = n;
                normal[f]       = n;
            }

            // Compute normal for each vertex
            foreach (Halfedge h in Halfedges)
            {
                if (!h.OnBoundary)  // Ignore halfedges that don't have a face
                {
                    var weight = (float)(cornerArea[h] / pointArea[h.ToVertex]);
                    h.ToVertex.Traits.Normal += weight * normal[h.Face];
                    //h.ToVertex.Traits.Normal += weight * h.Traits.Normal;
                }
            }

            // Normalize normals
            foreach (TriangleMesh.Vertex v in Vertices)
            {
                if (v.Traits.Normal.LengthSquared() > 0.0f)    // Ignore isolated points
                {
                    v.Traits.Normal.Normalize();
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Computes the angular area for each face vertex and the point area for each vertex.
        /// </summary>
        /// <param name="cornerArea">A halfedge dynamic trait to store face vertex angular areas.</param>
        /// <param name="pointArea">A vertex dynamic trait to store vertex angular areas.</param>
        public void ComputePointCornerArea(HalfedgeDynamicTrait <double> cornerArea, VertexDynamicTrait <double> pointArea)
        {
            Halfedge fh0, fh1, fh2;
            Vertex   fv0, fv1, fv2;
            Vector3D e0, e1, e2;
            double   length0, length1, length2, oneOverTotalLength;

            foreach (Face f in Faces)
            {
                // Get halfedges for this face
                fh0 = f.Halfedge;
                fh1 = fh0.Next;
                fh2 = fh1.Next;

                // Get vertices for this face
                fv0 = fh0.ToVertex;
                fv1 = fh1.ToVertex;
                fv2 = fh2.ToVertex;

                // Edge vectors
                e0 = fv2.Traits.Position - fv1.Traits.Position;
                e1 = fv0.Traits.Position - fv2.Traits.Position;
                e2 = fv1.Traits.Position - fv0.Traits.Position;

                // Triangle area
                double area = 0.5f * Vector3D.Cross(e0, e1).Length();

                // Edge lengths
                length0 = e0.Length();
                length1 = e1.Length();
                length2 = e2.Length();

                // Approximate corner area by fraction of triangle area given by opposite edge length
                oneOverTotalLength = 1.0 / (length0 + length1 + length2);
                cornerArea[fh0]    = length2 * oneOverTotalLength;
                cornerArea[fh1]    = length0 * oneOverTotalLength;
                cornerArea[fh2]    = length1 * oneOverTotalLength;

                // Add corner areas to areas for vertices
                pointArea[fv0] += cornerArea[fh0];
                pointArea[fv1] += cornerArea[fh1];
                pointArea[fv2] += cornerArea[fh2];
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Computes principle curvatures on the vertices.
        /// </summary>
        /// <param name="cornerArea">A halfedge dynamic trait with face vertex angular areas.</param>
        /// <param name="pointArea">A vertex dynamic trait with vertex angular areas.</param>
        /// <remarks>
        /// Portions of this method are based on code from the C++ trimesh2 library
        /// (from TriMesh_curvature.cc).
        /// </remarks>
        public void ComputePrincipleCurvatures(HalfedgeDynamicTrait <double> cornerArea, VertexDynamicTrait <double> pointArea)
        {
            // Add dynamic trait for principle curvature computation
            VertexDynamicTrait <double> curv = new VertexDynamicTrait <double>(this);

            // Initialize principle curvatures to zero
            foreach (Vertex v in Vertices)
            {
                v.Traits.MaxCurvature = 0.0f;
                v.Traits.MinCurvature = 0.0f;
            }

            // Initialize a coordinate system for each vertex
            foreach (Vertex v in Vertices)
            {
                if (v.Traits.Normal.GetLengthSquared() > 0.0f)    // Ignore isolated points
                {
                    // Vector that points from this vertex to an adjacent one
                    v.Traits.MaxCurvatureDirection = v.Halfedge.ToVertex.Traits.Position - v.Traits.Position;
                    v.Traits.MaxCurvatureDirection.Normalize();

                    // Get a vector orthogonal to this vector and the vertex normal
                    v.Traits.MinCurvatureDirection = Vector3D.CrossProduct(v.Traits.Normal, v.Traits.MaxCurvatureDirection);
                }
            }

            Halfedge[] fh = new Halfedge[3];
            Vertex[]   fv = new Vertex[3];
            Vector3D[] e = new Vector3D[3];
            Vector3D   t, b, dn, faceNormal;

            // Compute curvature for each face
            foreach (Face f in Faces)
            {
                // Get halfedges for this face
                fh[0] = f.Halfedge;
                fh[1] = fh[0].Next;
                fh[2] = fh[1].Next;

                // Get vertices for this face
                fv[0] = fh[0].ToVertex;
                fv[1] = fh[1].ToVertex;
                fv[2] = fh[2].ToVertex;

                // Edge vectors
                e[0] = fv[2].Traits.Position - fv[1].Traits.Position;
                e[1] = fv[0].Traits.Position - fv[2].Traits.Position;
                e[2] = fv[1].Traits.Position - fv[0].Traits.Position;

                t = e[0];
                t.Normalize();

                faceNormal = Vector3D.CrossProduct(e[0], e[1]);
                faceNormal.Normalize();

                b = Vector3D.CrossProduct(faceNormal, t);
                b.Normalize();

                // Estimate curvature by variation of normals along edges
                float[] m = new float[3];
                float[,] w = new float[3, 3];

                for (int i = 0; i < 3; ++i)
                {
                    float u = Vector3D.DotProduct(e[i], t);
                    float v = Vector3D.DotProduct(e[i], b);

                    w[0, 0] += u * u;
                    w[0, 1] += u * v;
                    w[2, 2] += v * v;

                    dn = fv[(i + 2) % 3].Traits.Normal - fv[(i + 1) % 3].Traits.Normal;

                    float dnu = Vector3D.DotProduct(dn, t);
                    float dnv = Vector3D.DotProduct(dn, b);

                    m[0] += dnu * u;
                    m[1] += dnu * v + dnv * u;
                    m[2] += dnv * v;
                }

                w[1, 1] = w[0, 0] + w[2, 2];
                w[1, 2] = w[0, 1];

                // Least squares solution
                float[] diag = new float[3];
                if (Curvature.LdlTransposeDecomp(w, diag))
                {
                    Curvature.LdlTransposeSolveInPlace(w, diag, m);

                    // Adjust curvature for vertices of this face
                    for (int i = 0; i < 3; ++i)
                    {
                        float c1, c12, c2;
                        Curvature.ProjectCurvature(t, b, m[0], m[1], m[2], fv[i].Traits.MaxCurvatureDirection, fv[i].Traits.MinCurvatureDirection, out c1, out c12, out c2);

                        float weight = cornerArea[fh[i]] / pointArea[fv[i]];
                        fv[i].Traits.MaxCurvature += weight * c1;
                        curv[fv[i]] += weight * c12;
                        fv[i].Traits.MinCurvature += weight * c2;
                    }
                }
            }

            // Compute curvature for each vertex
            foreach (Vertex v in Vertices)
            {
                if (v.Traits.Normal.GetLengthSquared() > 0.0f)    // Ignore isolated points
                {
                    Curvature.DiagonalizeCurvature(v.Traits.MaxCurvatureDirection, v.Traits.MinCurvatureDirection, v.Traits.MaxCurvature, curv[v], v.Traits.MinCurvature, v.Traits.Normal,
                                                   out v.Traits.MaxCurvatureDirection, out v.Traits.MinCurvatureDirection, out v.Traits.MaxCurvature, out v.Traits.MinCurvature);
                }
            }
        }