Jump to content
giordiTD

Curve normals : implement this algorithm

Recommended Posts

Hi everyone this is my first topic in this community!

I am a maya TD and I have been developing and rigging a lot in that software , then one day a collegue showed me houdini and I had a big "woah" moment , it s amazing how you can move and manipulate data in houdini , that s why i decided to learn it.

I wanted to start with something I thought basic . Basically i would like to make a node (digital asset) that calculates normal along a curve by using the parallel frame transportation.

The best would be to have as input the curve then and as output the computed normals.

The algorithm is pretty simple and this is the c++ procedure i used in my maya nodes :


MVector currentNormal = firstUpVecV;
for ( int i = 0 ; i < numberOfSamplesV ; i++ )
{

double param = curveFn.findParamFromLength(i*subvidsSample);
MVector tan = curveFn.tangent(param , MSpace::kObject);
MPoint outPos;
curveFn.getPointAtParam(param , outPos , MSpace::kObject);
tan.normalize();
MVector cross1 = currentNormal^tan;
cross1.normalize() ;
MVector cross2 = tan^cross1;
cross2.normalize();
currentNormal = cross2 ;
normals[i] = cross2;

}
[/CODE]

Basically you start from a given normal and you use it to compute the next normal , then you keep in memory the normal computed and you use it for computing the next normal.

I think that might be easier with python but I really want to get it done with nodes.

What i have done so far (check the attached file please )

I start with a curve and i resample it (the number of samples is the number of normals I want to compute)

then I use a polyFrame to compute the tangents and then i go inside a vopSop :

norm1.jpg

then inside the vopsop i plug the firstUpVector (the starting normal) and the tangents in a for loop

norm2.jpg

in the end inside an if loop i start with the cross products , my problem is that if the index is 0 i use the firstUpVector as a normal then when i have recomputed the normal with a double cross product i want to keep that normal somwhere and use it for next computation . something like nromals[i - 1] ^ tangents[i]

norm3.jpg

norm4.jpg

anyone have idea about to get throught that if statement? I am stuck

thanks a lot guys!

testNormal.hipnc

  • Like 1

Share this post


Link to post
Share on other sites

It sounds like you're trying to do a recursive function in vex which won't work. VEX operates in the mindset that all input data points are processed independently of each other. You might want to look into using a foreach sop or python for a recursive function.

Share this post


Link to post
Share on other sites

It sounds like you're trying to do a recursive function in vex which won't work. VEX operates in the mindset that all input data points are processed independently of each other. You might want to look into using a foreach sop or python for a recursive function.

hei man first of all nice reel!

alright I am not going recursive , if you check the c++ code what I do is i compute the first normal then in the secondo loop I use the first computed normal to calculate the second and so on.

And I am already inside a forEach node , what I need is the node run the first index , then i need to store the computed value somewhere and being able to access it in the next loop , then I compute again and i store the value and i will use it for the next round.

example :

index 0 : compute normal0 using first provided Normal

index 1 : compute normal1 using normal 0

index 2 : compute normal2 using normal 1

and so on

Share this post


Link to post
Share on other sites

I haven't read the whole thread but if you want to store the value and then update it at each step of the foreach sop, you can use a detail attribute. Create it before the foreach sop and then read/write to it inside the foreach.

Share this post


Link to post
Share on other sites

hei man thanks I am having hard time about how to set the value to the attribute through expression basically i have two cross product after those two node I have the normal , I need then to take this value and store it in the detail attribute.

Any idea about how to achieve that?

Edited by giordiTD

Share this post


Link to post
Share on other sites

If your evaluating just one point in your foreach loop at a time, then you can use an attribute promote, going from point to detail, using the first match method.

Share this post


Link to post
Share on other sites

If your evaluating just one point in your foreach loop at a time, then you can use an attribute promote, going from point to detail, using the first match method.

so If I am not wrong that will extract the data I need from the array right?

Share this post


Link to post
Share on other sites

You can do that by using a vop on one point, just set the group to 0 and do You calculations and store them in a array. You then serialize that array, to store it as a attribute.

In the next step You use a second vop that gets that data and "publishes" the array value per point. Check out the serialize vex function for this

Martin

Share this post


Link to post
Share on other sites

ciao Marco ! eheh :)

I've been 'fighting' with the "previous frame" problem a lot lately.

The way i approached it has been using POPs and DOPs, and then feeding the result to a timeshift sop.

Basically you emit one particle per frame in a POP network, and use a VOP pop in that pop network doing your calculation.

This way you'll be able to access the "previous" point calculated cause every frame the VOP pop will be populated with the data calculated in the previous frame PLUS the newly emitted particle/point, which is the one you'll be working on.

Once you're done, you should be able to see your normals calculated one point per frame playing the simulation, cause you emit one particle per frame.

Since you don't want to be tied to a frame dependant calculation, you can add a timeshift SOP to the output of your POP network, remove the "$F" in the parameter 'frame', and put in there some expression that returns the number of your original curve

something like

npoints ("../mycurve")

The timeshift sop will take care of iterating the upstream graph as many times as the content of it's 'frame' field and provide a frame indipendent result.

The downside of this method is that you'll have to deal with a 1 input VOP node, since VOPs don't allow more than one input in POP world.

To workaround it, I started using SOP solvers in DOP world and using "add" sop inside the sop solver, kinda simulating a particle emission. This way i can take advantage of the whole SOP land and multi input awesome super fast VOP sops.

The downside of the dop solution is that , the DOP network doesn't like timeshifts, differently from POP networks.

I am still investigating this last solution.

The reason cause I don't like foreach sop is that it's slow and i find it very difficult to debug the content.

But in your specific case, the normal calculation based on the previous point is very light, so the foreach solution might be sufficient.

hei man first of all nice reel!

alright I am not going recursive , if you check the c++ code what I do is i compute the first normal then in the secondo loop I use the first computed normal to calculate the second and so on.

And I am already inside a forEach node , what I need is the node run the first index , then i need to store the computed value somewhere and being able to access it in the next loop , then I compute again and i store the value and i will use it for the next round.

example :

index 0 : compute normal0 using first provided Normal

index 1 : compute normal1 using normal 0

index 2 : compute normal2 using normal 1

and so on

Share this post


Link to post
Share on other sites

alright guys! sorry for late replay ! but work is being insane , we are entering the hot wild zone of the end of production ! by the way! I got it done , I did it with python custom operator and works like a charm.

I am still working on @mrWolf idea of using a POP network , only think that worries me a little is the performance but we will see!

normal.jpg

I also come across the sop solver and its lag node that might be an option!

Last thing will be write the node in c++ with HDK but i dont want to explore that field yet , I wanna flearn a lot more houdini itself.

For more info about the python node you can check here :

http://www.marcogior...ormals-on-curve

Of course the OTL is free download!

have fun guys!

normalCurve.otl

Share this post


Link to post
Share on other sites
Guest mantragora

There are couple changes in HDK so I had to fix some code from my previous plays and also reconfigure my VS solution a little. Anyway, here is HDK version for study if you want. Quite a lot faster, especially if you bump up point count.

Zip contains scene, source code, otl with python version (a little modified by me) and DLL compiled for H12.5.393. It's this weekend last build.

You can find download link below my vimeo video.

Video: https://vimeo.com/65535109

Edited by mantragora

Share this post


Link to post
Share on other sites

The HDK plugin mantragora posted can also be sped up ~3x as fast (55ms vs 181ms for 1mil points in that hip file) though better attribute setup and access, as well as the iteration method. I've attached the source (sorry, not compiled).

Also, in relation to a comment made earlier about inlinecpp: I find that while inlinecpp can be somewhat troublesome to debug compiling errors, I've never had a problem with the speed of the code. I ported the attached code to inlinecpp as a test and it ran in virtually identical time as the full HDK operator.

SOP_NormalCurve_source.tar.gz

  • Like 1

Share this post


Link to post
Share on other sites
Guest mantragora

O yeah, sure you can if you use iterator for attribute too. Thanks for code graham. So you really can't read vector parameters directly (only thru evalFloat) and you have to roll your own read function for it?

EDIT: I tested your code and on my computer it's slower than my code. This may be difference between how GCC/VS optimize things, or just maybe your processor gives some advantages here, maybe some instructions that main doesn't have. For 1M points - 470ms vs 550ms. Since we don't modify geometry here I speeded up it even more by changing "duplicateSource()" method to "duplicatePointSource()". This cut times another 30-40ms on may code to 420ms, and around 540ms on your version. I suppose this may be really because how both compilers handle things.

Edited by mantragora

Share this post


Link to post
Share on other sites

There are couple changes in HDK so I had to fix some code from my previous plays and also reconfigure my VS solution a little. Anyway, here is HDK version for study if you want. Quite a lot faster, especially if you bump up point count.

DOWNLOAD:

http://www.mediafire...7hp3nyd4ow7km4i

Zip contains scene, source code, otl with python version (a little modified by me) and DLL compiled for H12.5.393. It's this weekend last build.

The HDK plugin mantragora posted can also be sped up ~3x as fast (55ms vs 181ms for 1mil points in that hip file) though better attribute setup and access, as well as the iteration method. I've attached the source (sorry, not compiled).

Also, in relation to a comment made earlier about inlinecpp: I find that while inlinecpp can be somewhat troublesome to debug compiling errors, I've never had a problem with the speed of the code. I ported the attached code to inlinecpp as a test and it ran in virtually identical time as the full HDK operator.

thanks a lot guys! I am always so impressed by houdini community! they are so helpfull! I would love to go into HDK , I have developed a big bulk of c++ plugins for maya so would be crazy cool for houdini aswell, but I cannot go into it right now , I first wish to get a way better understanding and knowledge of houdini itself!

I keep this really cool stuff to so I can study it ! Thanks a lot!

Quick question is it there any other learning source about HDK rather then default documentation? I dunno maybe a book?

thanks a lot guys!

Share this post


Link to post
Share on other sites
Guest mantragora

Quick question is it there any other learning source about HDK rather then default documentation? I dunno maybe a book?

You can print HDK documentation and make a book, does this count ? :D

Compared to Maya SDK, HDK is a lot harder. You can't transfer scripting knowledge so easily from H to HDK like you can in Maya from Mel to SDK. One day took me to jump into Maya SDK and do something. Now with C# addition to Maya that is so similar to C++ API part it's even easier to implement things and transfer to C++ if you really need maximum speed or plugin for Linux. Can't say the same about HDK by a loooong shot. Mostly because of documentation. Or lack of it. While node creation and other things are quite easy if you break thru help, viewport operations are not. I haven't seen even one example made by anyone on how to make those operations in HDK.

Edited by mantragora

Share this post


Link to post
Share on other sites

You can print HDK documentation and make a book, does this count ? :D

Compared to Maya SDK, HDK is a lot harder. You can't transfer scripting knowledge so easily from H to HDK like you can in Maya from Mel to SDK. One day took me to jump into Maya SDK and do something. Now with C# addition to Maya that is so similar to C++ API part it's even easier to implement things and transfer to C++ if you really need maximum speed or plugin for Linux. Can't say the same about HDK by a loooong shot. Mostly because of documentation. Or lack of it. While node creation and other things are quite easy if you break thru help, viewport operations are not. I haven't seen even one example made by anyone on how to make those operations in HDK.

@Graham:

Do you have maybe some code that you can share that shows simple viewport operations like getting selected points, polygons etc. ?

PS. I tested your code and on my computer it's slower than my code. This may be difference between how GCC/VS optimize things, or just maybe your processor gives some advantages here, maybe some instructions that main doesn't have. For 1M points - 470ms vs 550ms. Since we don't modify geometry here I speeded up it even more by changing "duplicateSource()" method to "duplicatePointSource()". This cut times another 30-40ms on may code to 420ms, and around 540ms on your version. I suppose this may be really because how both compilers handle things.

yeah true , but didnt think was going to be easy but since i love to mess at low level in maya soon or later i will in houdini but for now I will focus on learning well the package :D thanks so much for all the help guys!

By the way such a "simple" feature like the cook time is so damm helpfull!

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

×