Jump to content
Sign in to follow this  
yongbin

How can I calculate curve normal?

Recommended Posts

yongbin    20

Hi, houdini dev guys!

I am studying hdk and implementing a basic sop. It is similar with polyframe sop.

Now I am stuck with calculate average normal on a curve.(like facet sop) There should be a method for this. I find some calculateNormal functions on here and there. But I couldn't figure out which is one and how can I apply it.

So, please help me. General advise are also welcome!

Thank you. :)


// calculate curve's tangent or N

...

OP_ERROR
CurveAttrib::cookMySop(OP_Context &context)
{

if (lockInputs(context) >= UT_ERROR_ABORT)
return error();

duplicateSource(0, context);

GA_WOAttributeRef tangentRef;
tangentRef = gdp->addFloatTuple(GA_ATTRIB_POINT, "tangent", 3);
const GA_AIFTuple *tangentAIF = tangentRef.getAIFTuple();
GA_RWHandleV3 Phandle(gdp->findAttribute(GA_ATTRIB_POINT, "P"));
GEO_Primitive *prim;
GEO_AttributeHandle gah;
GA_FOR_ALL_PRIMITIVES(gdp, prim)
{
GA_Range ptrange = prim->getPointRange();
GA_Size npt = prim->getVertexCount()-1;
GA_Offset lastpt = prim->getPointOffset(npt);
GA_Offset firstpt = prim->getPointOffset(0);

bool curve_is_closed = false;
fpreal area = prim->calcArea();
if (!SYSalmostEqual(area, 0.0)) {
curve_is_closed = true;
}
for (GA_Iterator iterpt(ptrange.begin()); !iterpt.atEnd(); ++iterpt)
{
GA_Offset ptoff = iterpt.getOffset();
UT_Vector3 tangent;
UT_Vector3 Pcurr;
UT_Vector3 Pnext;
if ((ptoff==lastpt) && curve_is_closed) {
Pnext = Phandle.get(firstpt);
Pcurr = Phandle.get(ptoff);
tangent = Pnext-Pcurr; //circular
}
else if ((ptoff==lastpt) && !curve_is_closed) {
Pnext = Phandle.get(ptoff-1);
Pcurr = Phandle.get(ptoff);
tangent = Pcurr-Pnext; //backward
}
else {
Pnext = Phandle.get(ptoff+1);
Pcurr = Phandle.get(ptoff);
tangent = Pnext-Pcurr;
}
tangent.normalize();
tangentAIF->set(tangentRef.getAttribute(), ptoff, tangent.data(), 3);
}
}
gdp->notifyCache(GU_CACHE_ALL);
unlockInputs();
return error();
}
[/CODE]

Share this post


Link to post
Share on other sites
Stalkerx777    75

I'll bump this up, because i'm doing the same thing right now  :)  To get an average normal for curve, you can use GU_Curve class method curveNormal(). Getting GU_Curve is a little bit tricky:

GEO_Primitive *_prim = gdp->getGEOPrimitive(0);
GEO_Curve *geocurve = static_cast<GEO_Curve*>(_prim);
((GU_Curve *)geocurve->castTo())->curveNormal(out);

Now, my question is: Is there any method/class to compute tangent and bitangent vectors like polyframe sop does?

Share this post


Link to post
Share on other sites
Stalkerx777    75

Ok, never mind. It looks like it pretty simple. Here is how it's done in Polyframe SOP: 

Tangent vector = Prev. point position - Next point position

Bitangent vector = cross ( Tangent, Curve average normal)

 

P.s. doing some interesting stuff. More question to come. )

Share this post


Link to post
Share on other sites
yongbin    20

Hi, Stalkerx777.

 

Thank you for answer for this!

 

But I am really a C++ primer. So, all the type conversions break my head. :(

 

I have questions about the conversions.

 

1. How can I sure the static_cast (GEO_Primitive to GEO_Curve) is safe? I've heard static_casting base class to derived class may somewhat unsafe.

 

2. Why did you use castTo() method for GEO_Curve to GU_Primitive? It seems they don't make any relationship in perspective of class hierarchy. Is it possible to conversion?

 

3. Why did you use (GU_Curve *) instead of static_cast<GU_Curve *>, although (GU_Primitive -> GU_Curve) looks similar to (GEO_Primitive -> GEO_Curve).

 

It is hard to understand about C++ conversion even if I've read some documents about type conversion on web. (In C++, usually class hierarchy is too big and have so many conversion methods!)

 

Thanks in advance!

Edited by yongbin

Share this post


Link to post
Share on other sites
Stalkerx777    75

I'm not a c++ programmer, so sometimes i try a lot of things, before something get to work. :) Same with casting. One is old C style, other is c++ style.

((GU_Curve *)geocurve->castTo())->curveNormal(out);

I'm also not able to cast this into a variable. But i'm not tried this whit static_cast.. Maybe it works. castTo() is a special method to get GU_* type classed from GEO_*.

Try to google on c++ type casting. There is a lot of good articles.

http://msdn.microsoft.com/en-us/library/c36yw7x9.aspx

Edited by Stalkerx777

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×