Revision: 73161
          http://sourceforge.net/p/brlcad/code/73161
Author:   starseeker
Date:     2019-05-23 19:14:50 +0000 (Thu, 23 May 2019)
Log Message:
-----------
Start refactoring vertex normal logic (not done yet)

Modified Paths:
--------------
    brlcad/trunk/src/libbrep/cdt.cpp
    brlcad/trunk/src/libbrep/cdt.h
    brlcad/trunk/src/libbrep/cdt_edge.cpp
    brlcad/trunk/src/libbrep/cdt_util.cpp

Modified: brlcad/trunk/src/libbrep/cdt.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt.cpp    2019-05-23 18:22:05 UTC (rev 73160)
+++ brlcad/trunk/src/libbrep/cdt.cpp    2019-05-23 19:14:50 UTC (rev 73161)
@@ -36,9 +36,7 @@
        ON_SimpleArray<BrepTrimPoint> *points,
        const ON_BrepFace &face,
        const ON_BrepLoop *loop,
-       fastf_t max_dist,
-       std::map<int, ON_3dPoint *> *vert_pnts,
-       std::map<int, ON_3dPoint *> *vert_norms
+       fastf_t max_dist
        )
 {
     int trim_count = loop->TrimCount();
@@ -54,7 +52,8 @@
            const ON_BrepVertex& v1 = face.Brep()->m_V[trim->m_vi[0]];
            ON_3dPoint *p3d = (*s_cdt->vert_pnts)[v1.m_vertex_index];
            
(*s_cdt->strim_pnts)[face.m_face_index].insert(std::make_pair(trim->m_trim_index,
 p3d));
-           ON_3dPoint *n3d = (*s_cdt->vert_norms)[v1.m_vertex_index];
+           // TODO - use face normals for this, not avg
+           ON_3dPoint *n3d = (*s_cdt->vert_avg_norms)[v1.m_vertex_index];
            if (n3d) {
                
(*s_cdt->strim_norms)[face.m_face_index].insert(std::make_pair(trim->m_trim_index,
 n3d));
            }
@@ -87,7 +86,7 @@
        }
 
        if (!trim->m_trim_user.p) {
-           (void)getEdgePoints(s_cdt, edge, *trim, max_dist, vert_pnts, 
vert_norms);
+           (void)getEdgePoints(s_cdt, edge, *trim, max_dist);
            //bu_log("Initialized trim->m_trim_user.p: Trim %d (associated with 
Edge %d) point count: %zd\n", trim->m_trim_index, trim->Edge()->m_edge_index, 
m->size());
        }
        if (trim->m_trim_user.p) {
@@ -143,7 +142,7 @@
        if (s_to_maxdist->find(face.SurfaceOf()) != s_to_maxdist->end()) {
            max_dist = (*s_to_maxdist)[face.SurfaceOf()];
        }
-       Process_Loop_Edges(s_cdt, &brep_loop_points[li], face, loop, max_dist, 
s_cdt->vert_pnts, s_cdt->vert_norms);
+       Process_Loop_Edges(s_cdt, &brep_loop_points[li], face, loop, max_dist);
     }
 
     // Handle a variety of situations that complicate loop handling on closed 
surfaces
@@ -348,6 +347,54 @@
     return 0;
 }
 
+static ON_3dVector
+calc_trim_vnorm(ON_BrepVertex& v, ON_BrepTrim *trim)
+{
+    ON_3dPoint t1, t2;
+    ON_3dVector v1, v2 = ON_3dVector::UnsetVector;
+    ON_3dVector trim_norm = ON_3dVector::UnsetVector;
+
+    ON_Interval trange = trim->Domain();
+    ON_3dPoint t_2d1 = trim->PointAt(trange[0]);
+    ON_3dPoint t_2d2 = trim->PointAt(trange[1]);
+
+    ON_Plane fplane;
+    const ON_Surface *s = trim->SurfaceOf();
+    if (s->IsPlanar(&fplane, BREP_PLANAR_TOL)) {
+       trim_norm = fplane.Normal();
+       if (trim->Face()->m_bRev) {
+           trim_norm = trim_norm * -1;
+       }
+    } else {
+       int ev1, ev2 = 0;
+       if (surface_EvNormal(s, t_2d1.x, t_2d1.y, t1, v1)) {
+           if (trim->Face()->m_bRev) {
+               v1 = v1 * -1;
+           }
+           if (v.Point().DistanceTo(t1) < ON_ZERO_TOLERANCE) {
+               ev1 = 1;
+               trim_norm = v1;
+           }
+       }
+       if (surface_EvNormal(s, t_2d2.x, t_2d2.y, t2, v2)) {
+           if (trim->Face()->m_bRev) {
+               v2 = v2 * -1;
+           }
+           if (v.Point().DistanceTo(t2) < ON_ZERO_TOLERANCE) {
+               ev2 = 1;
+               trim_norm = v2;
+           }
+       }
+       // If we got both of them, go with the closest one
+       if (ev1 && ev2) {
+           bu_log("Vertex %d: got both normals\n", v.m_vertex_index);
+           trim_norm = (v.Point().DistanceTo(t1) < v.Point().DistanceTo(t2)) ? 
v1 : v2;
+       }
+    }
+
+    return trim_norm;
+}
+
 int
 ON_Brep_CDT_Tessellate(struct ON_Brep_CDT_State *s_cdt, int face_cnt, int 
*faces)
 {
@@ -358,14 +405,14 @@
     // Check for any conditions that are show-stoppers
     ON_wString wonstr;
     ON_TextLog vout(wonstr);
-    if (!brep->IsValid(&vout)) {
+    if (!s_cdt->orig_brep->IsValid(&vout)) {
        bu_log("brep is NOT valid, cannot produce watertight mesh\n");
        //return -1;
     }
 
     // For now, edges must have 2 and only 2 trims for this to work.
-    for (int index = 0; index < brep->m_E.Count(); index++) {
-        ON_BrepEdge& edge = brep->m_E[index];
+    for (int index = 0; index < s_cdt->orig_brep->m_E.Count(); index++) {
+        ON_BrepEdge& edge = s_cdt->orig_brep->m_E[index];
         if (edge.TrimCount() != 2) {
            bu_log("Edge %d trim count: %d - can't (yet) do watertight 
meshing\n", edge.m_edge_index, edge.TrimCount());
             return -1;
@@ -420,33 +467,16 @@
 
     /* If this is the first time through, get vertex normals that are the
      * average of the surface normals at the junction from faces that don't use
-     * a singular trim to reference the vertex.  When subdividing the surface
-     * during surface point builds, we use the normals as a curvature guide.
-     * When we hit singular trims, we use the normal calculated below to ensure
-     * the normal is always the same at the singularity regardless of the
-     * particular UV point on the singular trim we are evaluating.
-     *
-     * TODO - rather than averaging, we probably want to get a per-face
-     * normal for each vert.  When we hit singular trims we can do a lookup
-     * by vert, but we still want a normal specific to the face since
-     * an average will tend to visually corrupt sharp edges. Let's do this -
-     * iterate over all trims, build the set of singular trims, for those trims
-     * get the associated verts and for each vert and each face associated with
-     * that vert that has a singular trim, calculate a normal based on the
-     * surface evaluation at that point from non-singular trims in the face
-     * that share the same vertex point.*/
-    if (!s_cdt->w3dnorms->size()) {
+     * a singular trim to reference the vertex.  When subdividing the edges, we
+     * use the normals as a curvature guide.
+     */
+    if (!s_cdt->vert_avg_norms->size()) {
        for (int index = 0; index < brep->m_V.Count(); index++) {
            ON_BrepVertex& v = brep->m_V[index];
            int have_calculated = 0;
            ON_3dVector vnrml(0.0, 0.0, 0.0);
-           if (index == 595) {
-               bu_log("595: %f %f %f\n", v.Point().x, v.Point().y, 
v.Point().z);
-           }
 
            for (int eind = 0; eind != v.EdgeCount(); eind++) {
-               ON_3dPoint t1_1, t1_2, t2_1, t2_2;
-               ON_3dVector t1_v1, t1_v2, t2_v1, t2_v2 = 
ON_3dVector::UnsetVector;
                ON_3dVector trim1_norm = ON_3dVector::UnsetVector;
                ON_3dVector trim2_norm = ON_3dVector::UnsetVector;
                ON_BrepEdge& edge = brep->m_E[v.m_ei[eind]];
@@ -457,96 +487,48 @@
                ON_BrepTrim *trim1 = edge.Trim(0);
                ON_BrepTrim *trim2 = edge.Trim(1);
 
-               if (trim1->m_type == ON_BrepTrim::singular || trim2->m_type == 
ON_BrepTrim::singular) {
-                   continue;
+               if (trim1->m_type != ON_BrepTrim::singular) {
+                   trim1_norm = calc_trim_vnorm(v, trim1);
                }
 
-               ON_Interval t1range = trim1->Domain();
-               ON_Interval t2range = trim2->Domain();
-               ON_3dPoint t1_2d1 = trim1->PointAt(t1range[0]);
-               ON_3dPoint t1_2d2 = trim1->PointAt(t1range[1]);
-               ON_3dPoint t2_2d1 = trim2->PointAt(t2range[0]);
-               ON_3dPoint t2_2d2 = trim2->PointAt(t2range[1]);
-               ON_Plane plane1, plane2;
-               const ON_Surface *s1 = trim1->SurfaceOf();
-               const ON_Surface *s2 = trim2->SurfaceOf();
-               if (s1->IsPlanar(&plane1, BREP_PLANAR_TOL)) {
-                   trim1_norm = plane1.Normal();
-                   if (trim1->Face()->m_bRev) {
-                       trim1_norm = trim1_norm * -1;
-                   }
-               } else {
-                   if (surface_EvNormal(s1, t1_2d1.x, t1_2d1.y, t1_1, t1_v1)) {
-                       if (trim1->Face()->m_bRev) {
-                           t1_v1 = t1_v1 * -1;
-                       }
-                   }
-                   if (surface_EvNormal(s1, t1_2d2.x, t1_2d2.y, t1_2, t1_v2)) {
-                       if (trim1->Face()->m_bRev) {
-                           t1_v2 = t1_v2 * -1;
-                       }
-                   }
-                   trim1_norm = (v.Point().DistanceTo(t1_1) < 
v.Point().DistanceTo(t1_2)) ? t1_v1 : t1_v2;
+               if (trim2->m_type != ON_BrepTrim::singular) {
+                   trim2_norm = calc_trim_vnorm(v, trim2);
                }
-               if (s2->IsPlanar(&plane2, BREP_PLANAR_TOL)) {
-                   trim2_norm = plane2.Normal();
-                   if (trim2->Face()->m_bRev) {
-                       trim2_norm = trim2_norm * -1;
-                   }
-               } else {
 
-                   if (surface_EvNormal(s2, t2_2d1.x, t2_2d1.y, t2_1, t2_v1)) {
-                       if (trim2->Face()->m_bRev) {
-                           t2_v1 = t2_v1 * -1;
-                       }
-                   }
-                   if (surface_EvNormal(s2, t2_2d2.x, t2_2d2.y, t2_2, t2_v2)) {
-                       if (trim2->Face()->m_bRev) {
-                           t2_v2 = t2_v2 * -1;
-                       }
-                   }
-                   trim2_norm = (v.Point().DistanceTo(t2_1) < 
v.Point().DistanceTo(t2_2)) ? t2_v1 : t2_v2;
-               }
+               // Stash normals coming from non-singular trims at vertices for 
faces.  If a singular trim
+               // needs a normal in 3D, want to use one of these
+               if (trim1_norm != ON_3dVector::UnsetVector) {
+                   ON_3dPoint *t1pnt = new ON_3dPoint(trim1_norm);
+                   
(*s_cdt->vert_face_norms)[v.m_vertex_index][trim1->Face()->m_face_index].insert(t1pnt);
+                   s_cdt->w3dnorms->push_back(t1pnt);
 
-               if (index == 595) {
-                   bu_log("trim face %d normal: %f %f %f\n", 
trim1->Face()->m_face_index, trim1_norm.x, trim1_norm.y, trim1_norm.z);
-                   bu_log("trim face %d normal: %f %f %f\n", 
trim2->Face()->m_face_index, trim2_norm.x, trim2_norm.y, trim1_norm.z);
+                   // Add the normal to the vnrml total
+                   vnrml += trim1_norm;
+                   have_calculated = 1;
                }
+               if (trim2_norm != ON_3dVector::UnsetVector) {
+                   ON_3dPoint *t2pnt = new ON_3dPoint(trim2_norm);
+                   
(*s_cdt->vert_face_norms)[v.m_vertex_index][trim2->Face()->m_face_index].insert(t2pnt);
+                   s_cdt->w3dnorms->push_back(t2pnt);
 
-               // Want the angle between the two faces to not be "sharp" - if
-               // it is, we don't want to use the average, since that will
-               // tend to introduce visual artifacts at the vertex.
-               //
-               // TODO - come up with a strategy to allow a fallback to this
-               // anyway if the surface is just giving nonsense answers at the
-               // edge...
-               if (trim1_norm == ON_3dVector::UnsetVector) {
-                   continue;
-               }
-               if (trim2_norm == ON_3dVector::UnsetVector) {
-                   continue;
-               }
-               if (ON_DotProduct(trim1_norm, trim2_norm) > 0.5) {
-                   vnrml += trim1_norm;
+                   // Add the normal to the vnrml total
                    vnrml += trim2_norm;
                    have_calculated = 1;
-               } else {
-                   continue;
                }
-               if (index == 523) {
-                   bu_log("normal sum: %f %f %f\n", vnrml.x, vnrml.y, vnrml.z);
-               }
+
            }
            if (!have_calculated) {
                continue;
            }
+
+           // Average all the successfully calculated normals into a new unit 
normal 
            vnrml.Unitize();
 
            // We store this as a point to keep C++ happy...  If we try to
            // propagate the ON_3dVector type through all the CDT logic it
            // triggers issues with the compile.
-           (*s_cdt->vert_norms)[index] = new ON_3dPoint(vnrml);
-           s_cdt->w3dnorms->push_back((*s_cdt->vert_norms)[index]);
+           (*s_cdt->vert_avg_norms)[index] = new ON_3dPoint(vnrml);
+           s_cdt->w3dnorms->push_back((*s_cdt->vert_avg_norms)[index]);
        }
     }
 
@@ -582,7 +564,7 @@
        // runs - if pre-existing solutions for "high level" splits exist,
        // reuse them and dig down to find where we need further refinement to
        // create new points.
-        (void)getEdgePoints(s_cdt, &edge, trim1, max_dist, s_cdt->vert_pnts, 
s_cdt->vert_norms);
+        (void)getEdgePoints(s_cdt, &edge, trim1, max_dist);
 
     }
 

Modified: brlcad/trunk/src/libbrep/cdt.h
===================================================================
--- brlcad/trunk/src/libbrep/cdt.h      2019-05-23 18:22:05 UTC (rev 73160)
+++ brlcad/trunk/src/libbrep/cdt.h      2019-05-23 19:14:50 UTC (rev 73161)
@@ -97,10 +97,12 @@
 
     /* 3D data */
     std::vector<ON_3dPoint *> *w3dpnts;
-    std::map<int, ON_3dPoint *> *vert_pnts;
     std::vector<ON_3dPoint *> *w3dnorms;
-    std::map<int, ON_3dPoint *> *vert_norms;
 
+    std::map<int, ON_3dPoint *> *vert_pnts;
+    std::map<int, ON_3dPoint *> *vert_avg_norms;
+    std::map<int, std::map<int, std::set<ON_3dPoint *>>> *vert_face_norms;
+
     /* singular trim info */
     std::map<int, std::map<int,ON_3dPoint *>> *strim_pnts;
     std::map<int, std::map<int,ON_3dPoint *>> *strim_norms;
@@ -164,9 +166,7 @@
        struct ON_Brep_CDT_State *s_cdt,
        ON_BrepEdge *edge,
        ON_BrepTrim &trim,
-       fastf_t max_dist,
-       std::map<int, ON_3dPoint *> *vert_pnts,
-       std::map<int, ON_3dPoint *> *vert_norms
+       fastf_t max_dist
        );
 
 void

Modified: brlcad/trunk/src/libbrep/cdt_edge.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt_edge.cpp       2019-05-23 18:22:05 UTC (rev 
73160)
+++ brlcad/trunk/src/libbrep/cdt_edge.cpp       2019-05-23 19:14:50 UTC (rev 
73161)
@@ -240,9 +240,7 @@
        struct ON_Brep_CDT_State *s_cdt,
        ON_BrepEdge *edge,
        ON_BrepTrim &trim,
-       fastf_t max_dist,
-       std::map<int, ON_3dPoint *> *vert_pnts,
-       std::map<int, ON_3dPoint *> *vert_norms
+       fastf_t max_dist
        )
 {
     struct brep_cdt_tol cdt_tol = BREP_CDT_TOL_ZERO;
@@ -313,8 +311,8 @@
     }
 
     /* For the start and end points, use the vertex point */
-    edge_start_3d = (*vert_pnts)[edge->Vertex(0)->m_vertex_index];
-    edge_end_3d = (*vert_pnts)[edge->Vertex(1)->m_vertex_index];
+    edge_start_3d = (*s_cdt->vert_pnts)[edge->Vertex(0)->m_vertex_index];
+    edge_end_3d = (*s_cdt->vert_pnts)[edge->Vertex(1)->m_vertex_index];
 
     /* Normalize the domain of the curve to the ControlPolygonLength() of the
      * NURBS form of the curve to attempt to minimize distortion in 3D to
@@ -366,8 +364,8 @@
     ON_3dVector trim1_start_normal, trim1_end_normal = 
ON_3dVector::UnsetVector;
     ON_3dVector trim2_start_normal, trim2_end_normal = 
ON_3dVector::UnsetVector;
     ON_3dPoint *t1_sn, *t1_en, *t2_sn, *t2_en = NULL;
-    ON_3dPoint *edge_start_3dnorm = 
(*vert_norms)[edge->Vertex(0)->m_vertex_index];
-    ON_3dPoint *edge_end_3dnorm = 
(*vert_norms)[edge->Vertex(1)->m_vertex_index];
+    ON_3dPoint *edge_start_3dnorm = 
(*s_cdt->vert_avg_norms)[edge->Vertex(0)->m_vertex_index];
+    ON_3dPoint *edge_end_3dnorm = 
(*s_cdt->vert_avg_norms)[edge->Vertex(1)->m_vertex_index];
 
     /* trim 1 */
     if (!surface_EvNormal(s1, trim1_start_2d.x, trim1_start_2d.y, tmpp, 
trim1_start_normal)) {

Modified: brlcad/trunk/src/libbrep/cdt_util.cpp
===================================================================
--- brlcad/trunk/src/libbrep/cdt_util.cpp       2019-05-23 18:22:05 UTC (rev 
73160)
+++ brlcad/trunk/src/libbrep/cdt_util.cpp       2019-05-23 19:14:50 UTC (rev 
73161)
@@ -169,7 +169,8 @@
     cdt->w3dpnts = new std::vector<ON_3dPoint *>;
     cdt->vert_pnts = new std::map<int, ON_3dPoint *>;
     cdt->w3dnorms = new std::vector<ON_3dPoint *>;
-    cdt->vert_norms = new std::map<int, ON_3dPoint *>;
+    cdt->vert_avg_norms = new std::map<int, ON_3dPoint *>;
+    cdt->vert_face_norms = new std::map<int, std::map<int, std::set<ON_3dPoint 
*>>>;
     cdt->strim_pnts = new std::map<int,std::map<int, ON_3dPoint *> >;
     cdt->strim_norms = new std::map<int,std::map<int, ON_3dPoint *> >;
     cdt->vert_to_on = new std::map<int, ON_3dPoint *>;
@@ -237,7 +238,8 @@
     delete s_cdt->w3dpnts;
     delete s_cdt->vert_pnts;
     delete s_cdt->w3dnorms;
-    delete s_cdt->vert_norms;
+    delete s_cdt->vert_avg_norms;
+    delete s_cdt->vert_face_norms;
     delete s_cdt->strim_pnts;
     delete s_cdt->strim_norms;
     delete s_cdt->vert_to_on;

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to