Jump to content

Computing Point Normals


Recommended Posts

Hi all,

I'm wondering what the recommended way is to compute point normals when they don't exist in the input detail. After looking through a few classes, my first version was:

   int andx_n;
   if((andx_n=gdp->findNormalAttribute(GEO_POINT_DICT))<0) {
      andx_n = gdp->addNormalAttribute(GEO_POINT_DICT);
      GEO_Point *ppt; UT_Vector3 nml;
      FOR_ALL_GPOINTS(gdp,ppt) { 
         gdp->computeNormal(*ppt,nml);
         *((UT_Vector3 *)ppt->getAttribData(andx_n)) = nml;
      }
   }

which works, but then, the comments in GU_Detail warn that computeNormal() could be "very slow" and to use computeNormalInternal() instead... but taking into account the behaviour of the internal versions,

/// For internal functions:
/// If nml_offset > -1, the attribute at that offset will be returned,
/// else if the geometry has a normal attribute ("N"), nml_offset
///         will be set to the offset of that attribute and that attributes
///         value will be returned,
/// else if the geometry has an internal normal attribute ("internalN")
///         the value of the internal attribute will be returned and
///         nml_offset will be set to its offset,
/// else the "internalN" attribute is created by a call to normal(1),
///         nml_offset is set to it, and the calculated value returned.
/// If nml_offset is null, the case of nml_offset == -1 is followed
/// except nml_offset is not written to.
/// Otherwise:
/// Recompute the normal. No side-effects happen, but this is much
/// slower.

the best I can come up with *has* to visit all points twice (for the case where "internalN" doesn't exist):

   int andx_n = gdp->findNormalAttribute(GEO_POINT_DICT);
   if(andx_n<0) {
      int andx_in = gdp->findAttrib("internalN",sizeof(UT_Vector3),GB_ATTRIB_VECTOR);
      GEO_Point *ppt; UT_Vector3 nml;
      if(andx_in<0) {
         UT_Vector3 dv_zero(0,0,0);
         andx_in = gdp->addAttrib("internalN",sizeof(UT_Vector3),
                                  GB_ATTRIB_VECTOR,&dv_zero);
         FOR_ALL_GPOINTS(gdp,ppt) { gdp->computeNormalInternal(*ppt,nml); }
      }
      andx_n=gdp->addNormalAttribute(GEO_POINT_DICT);
      FOR_ALL_GPOINTS(gdp,ppt) { 
         // would memcpy() be faster here?
         *((UT_Vector3 *)ppt->getAttribData(andx_n)) = 
            *((UT_Vector3 *)ppt->getAttribData(andx_in));
      }
   }

which works too, but I have a feeling that there's a faster/better/more efficient way of doing it that I haven't found yet ?

Thanks.

Link to comment
Share on other sites

Don't feel bad, I got burned the exact same way last week, that's how I knew the answer.  :P

25209[/snapback]

Heheh. Yeah, my brain goes completely numb after greping headers and looking through those doxygen pages long enough -- I'm likely to forget my own name, never mind finding a function :huh:

Cheers!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...