Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Point normals (again)

    SDK Help
    0
    21
    13.7k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

      On 25/01/2009 at 04:22, xxxxxxxx wrote:

      ...also note that the above implies that you will likely end up with many 'duplicate' normals (anywhere polygons share a common vertex and there is no phong-edge-break).  This is fine if you're just interested in what the normals are, but may require further processing if you want to eliminate duplicates and convert it to a table lookup (ie. my Riptide / Riptide Pro .obj exporters do that before saving the normals).

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

        On 25/01/2009 at 04:43, xxxxxxxx wrote:

        Oops.. I left out something in my latest code sample above... whether you get a buffer returned from CreatePhongNormals() or my other code above, in each case be sure to GeFree() the buffer when done :).
        EDIT: I see that I also left off the '*' on Vector *pVert ; Vector *pNorm ; declarations above (I typed that example in by hand - spur of the moment).
        EDIT2: Actually, because of the way the rest of that is coded, those would just be Vectors instead of pointers to Vectors, so just ignore the 'p' in front of those variable names 🙂 .

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

          On 25/01/2009 at 05:00, xxxxxxxx wrote:

          Ah!! OK, then either I misunderstood the documentation, or it should be made more clear there. Thanks again! This is the best "Point Normals" thread ever 😄

          Additional question: What if my mesh is triangulated? Regarding your example with 2 quad polygons = 6 vertices = 8 elements in CreatePhongNormals() array... if I triangulate your example mesh, I would get 4 tri polygons = 6 vertices = 12 elements in normal array. Right? Because there are three vertices per polygon? Or would I still get 4 vertices per polygon (= 16 elements), just the 4th one is not used?

          Cheers,
          Jack

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

            On 25/01/2009 at 05:25, xxxxxxxx wrote:

            Quote: Originally posted by c4dJack on 25  January 2009
            >
            > * * *
            >
            > ...I would get 4 tri polygons = 6 vertices = 12 elements in normal array. Right? Because there are three vertices per polygon? Or would I still get 4 vertices per polygon (= 16 elements), just the 4th one is not used?
            >
            >
            > * * *

            Underlined.
            Basically, you always get 4 x number_of_polygons ... one for each (a,b,c,d) corner of the quad - whether the 4th is used, or not.
            As an aside, this is also how the UVW Tag works... except that it has routines to let you get each uv-polygon:  UVWStruct uvw = pUVs->Get(polyNdx);   I modeled the NormalStruct on the UVWStruct

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

              On 25/01/2009 at 05:37, xxxxxxxx wrote:

              It's best to think of it this way:
              CPolygon = vertex-polygon
              UVWStruct = uv-polygon
              NormalStruct = normal-polygon
              ...all of the above always have 4 elements (a,b,c,d).   The only practical difference is that the CPolygon contains indices into the vertex array as it's elements and the other two contain the actual UV/Normal Vector itself instead of an index, as the 4 elements.

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                On 05/08/2009 at 10:40, xxxxxxxx wrote:

                Sorry, to push this up again, but:

                What , if I don't work with polygons, but just with points? I can't use NormalStruct results here, since I just have a point index. How can I find out the Vertex Normal for a specific point?

                Thanks in advance!

                Cheers,
                Jack

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                  On 05/08/2009 at 11:33, xxxxxxxx wrote:

                  I'm trying to understand this, so I wrote a function to get the Vertex Normal of just one point (I know this will be slow if I want them for several points, but it's just a test).

                  Strangely, I get the weirdest results. The normals point in all kinds of directions, but not into the correct one.

                  > \> Vector GetVertexNormal(LONG PointIndex, PolygonObject \*op) \> { \>      // Variables \>      CPolygon \*pNeighborPoly; \>      Neighbor neighbor; \>      LONG j, faceCnt, \*pFaces = NULL; \>      Vector v1, v2, vNorm = Vector(0,0,0); \>      CPolygon \*m_pPolys = op->GetPolygonW(); \>      Vector \*m_pPoints = op->GetPointW(); \> \>      // Init Neighbor class \>      if (!neighbor.Init(op->GetPointCount(), m_pPolys, op->GetPolygonCount(), NULL)) \>           return vNorm; \> \>      // Get polygons attached to point \>      neighbor.GetPointPolys(PointIndex, &pFaces;, &faceCnt;); \> \>      for(j=0; j<faceCnt; j++) \>     { \>         pNeighborPoly = &m;\_pPolys[pFaces[j]]; \> \>         // Compute face normal \>         v1 = m_pPoints[pNeighborPoly->b] - m_pPoints[pNeighborPoly->a]; \>         v2 = m_pPoints[pNeighborPoly->c] - m_pPoints[pNeighborPoly->a]; \>         vNorm += v1 % v2; // get cross-product \>     } \>      vNorm /= faceCnt; \> \>      // Return resuling normal vector \>      return !vNorm; \> } \>

                  Thanks for any help!

                  Greetings,
                  Jack

                  1 Reply Last reply Reply Quote 0
                  • H
                    Helper
                    last edited by

                    THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                    On 05/08/2009 at 12:07, xxxxxxxx wrote:

                    I'm just waking up, but your code "looks" ok (should be working), so I'm wondering if maybe the code that's asking for 'some' point's normal is maybe asking about the wrong point?  (or something).
                    Anyway, for debugging purposes, I sometimes call a utility routine like this...
                    >

                    \>     
                    \>     
                    \>       
                    \>     > //-------------------------------------------------------------  
                    \>     > // AddSplineObject()  
                    \>     > //-------------------------------------------------------------  
                    \>     > void AddSplineObject(BaseDocument *pDoc, const String& name, const Vector& pos, const Vector& axis, const Real& length)  
                    \>     > {  
                    \>     >  SplineObject *pSpline = SplineObject::Alloc(2,Tlinear);  // allocate spline object  
                    \>     >  if( pSpline )  
                    \>     >  {  
                    \>     >   if( pSpline->MakeVariableTag(Tsegment,1) )  
                    \>     >   {  
                    \>     >    Vector *padr = pSpline->GetPointW();  
                    \>     >    Segment *sadr = pSpline->GetSegmentW();
                    \>     
                    \>     
                    \>     
                    \>     
                    \>        sadr[0].cnt    = 2;  
                    \>     >    sadr[0].closed = false;
                    \>     
                    \>     
                    \>     
                    \>     
                    \>        padr[0] = pos;  
                    \>     >    padr[1] = pos + (axis * length);
                    \>     
                    \>     
                    \>     
                    \>     
                    \>        pSpline->SetName(name);  
                    \>     >    pDoc->InsertObject(pSpline, NULL, NULL);  
                    \>     >    pDoc->AddUndo(UNDO_NEW, pSpline);  
                    \>     >    pSpline->Message(MSG_UPDATE);  
                    \>     >   }  
                    \>     >  }  
                    \>     > }  
                    \>     > 
                    \> 
                    \> 
                    

                    ...you can pass the point your asking about as the 'pos' arg, and the generated normal as the 'axis' arg and use 1 or 10 or whatever for the length.  It adds a spline object, showing a visual representation of the normal (be sure to either StartUndo() or comment out that AddUndo() line).

                    1 Reply Last reply Reply Quote 0
                    • H
                      Helper
                      last edited by

                      THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                      On 05/08/2009 at 12:16, xxxxxxxx wrote:

                      ....in your code, I'd also change:

                          
                          
                            
                          vNorm = Vector(0,0,0);
                          
                          
                          
                          
                          to
                          
                          
                          
                          
                          vNorm = Vector(0,1,0); //default to pointing straight up  
                          
                      

                      ...and also, after:

                          
                          
                            
                          // Get polygons attached to point  
                               neighbor.GetPointPolys(PointIndex, &pFaces, &faceCnt);
                          
                          
                          
                          
                          ...you should add:
                          
                          
                          
                          
                               if( !faceCnt ) return vNorm;  
                          
                      

                      ...to avoid any potential divide-by-zero below there.

                      1 Reply Last reply Reply Quote 0
                      • H
                        Helper
                        last edited by

                        THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                        On 05/08/2009 at 12:24, xxxxxxxx wrote:

                        Also keep in mind that if edge-breaks are involved, each vertex can have more than one Normal.  In other words, (vertex) Normals are really polygon-relative - none of the above code takes edge-breaks into account, so you end up with smoothed (averaged) normals at each vertex.

                        1 Reply Last reply Reply Quote 0
                        • H
                          Helper
                          last edited by

                          THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                          On 05/08/2009 at 14:40, xxxxxxxx wrote:

                          In this particular case I won't care about edge breaks. Each Vertex Normal should just be the average of it's surrounding polygons.

                          But I HAVE to get the normal vectors by addressing them with the point index.

                          My code is now like this.
                          I pass an initialized Neighbor class object to the function, that speeds it up a lot. Anyway, the normals still point into totally stupid directions.

                          Also I noticed, that faceCnt is always 3 for each point. But the geometry is (for testing) just a cube subdivided object, so there *should* be 4 faces for each point.

                          > Vector GetVertexNormal(LONG PointIndex, PolygonObject \*op, Neighbor \*neighbor) \> { \>      // Variables \>      CPolygon \*pNeighborPoly; \>      LONG j, faceCnt, \*pFaces = NULL; \>      Vector v1, v2, vNorm = Vector(C_FLOATZERO, C_FLOATONE, C_FLOATZERO); \>      CPolygon \*m_pPolys = op->GetPolygonW(); \>      Vector \*m_pPoints = op->GetPointW(); \> \>      // Get polygons attached to point \>      neighbor->GetPointPolys(PointIndex, &pFaces;, &faceCnt;); \>      if(!faceCnt) return vNorm; \> \>      for(j=0; j<faceCnt; j++) \>     { \>         pNeighborPoly = &m;\_pPolys[pFaces[j]]; \> \>         // Compute face normal \>         v1 = m_pPoints[pNeighborPoly->b] - m_pPoints[pNeighborPoly->a]; \>         v2 = m_pPoints[pNeighborPoly->c] - m_pPoints[pNeighborPoly->a]; \>         vNorm += v1 % v2; // get cross-product \>     } \>      vNorm /= faceCnt; \> \>      // Return resuling normal vector \>      return !vNorm; \> }

                          Greetings,
                          Jack

                          1 Reply Last reply Reply Quote 0
                          • H
                            Helper
                            last edited by

                            THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                            On 05/08/2009 at 15:10, xxxxxxxx wrote:

                            Oh wait. My mistake. Code works fine. If I modify the geometry while calculating an array of Vertex normals, it's no wonder they point into seemingly stupid directions.

                            Thanks a thousand times!

                            Cheers,
                            Jack

                            1 Reply Last reply Reply Quote 0
                            • H
                              Helper
                              last edited by

                              THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                              On 06/08/2009 at 00:32, xxxxxxxx wrote:

                              That looks ok to me. Just some stuff you can improve (taking triangles or quadrangles into account) :

                              > \> for (j=0; j<faceCnt; j++) \> { \>      pNeighborPoly = &m;\_pPolys[pFaces[j]]; \>       \>      // Compute face normal \>      if (pNeighborPoly->c == pNeighborPoly->d)     //triangle \>      { \>           v1 = m_pPoints[pNeighborPoly->b] - m_pPoints[pNeighborPoly->a]; \>           v2 = m_pPoints[pNeighborPoly->c] - m_pPoints[pNeighborPoly->a]; \>      } \>      else     //quadrangle \>      { \>           v1 = m_pPoints[pNeighborPoly->c] - m_pPoints[pNeighborPoly->a]; \>           v2 = m_pPoints[pNeighborPoly->d] - m_pPoints[pNeighborPoly->b]; \>      } \>       \>      vNorm += v1 % v2; // get cross-product \> } \> \> //vNorm /= faceCnt; not necessary, normalizing is enough \> \> // Return resuling normal vector \> return !vNorm; \>

                              cheers,
                              Matthias

                              1 Reply Last reply Reply Quote 0
                              • H
                                Helper
                                last edited by

                                THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

                                On 06/08/2009 at 03:07, xxxxxxxx wrote:

                                Quote: Originally posted by Giblet on 05  August 2009
                                >
                                > * * *
                                >
                                > ....in your code, I'd also change:
                                >
                                >

                                \>     
                                \>     
                                \>       
                                \>     > vNorm = Vector(0,0,0);
                                \>     
                                \>     
                                \>     
                                \>     
                                \>     to
                                \>     
                                \>     
                                \>     
                                \>     
                                \>     vNorm = Vector(0,1,0); //default to pointing straight up
                                \>     
                                \>      
                                \>     
                                \>     ....  
                                \>     > 
                                \> 
                                \> 
                                

                                >
                                > * * *
                                D'oh!  Ignore the above suggestion... or at least reset it to all zeros before you enter that loop below there - I was just trying to account for points not connected to ANY polygons, but you should probably handle that error condition differently anyway.
                                @Matthias - thanks for the corrections/additions... I'd forgotten about th normalization, so that extra divide at the end of the loop is not needed.

                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post