Jump to content

Sampling environment


Recommended Posts

As a learning excerise I want to create a sop node that shoots random rays from points and stores those rays that have hit something.

Is there a rayhit like method somewhere? What is the best way to go about this? Are there examples?

Any tips and hints welcome. I have basic C++ knowledge and can find my way around some code but have not much HDK experience at all.

Link to comment
Share on other sites

I'm going through the SOP_SParticle example there. In this, and some other examples I noticed that there is a myConstructor with an OP_Node* return value, and it just calls the standard constructor.

What is the reason for that?

Link to comment
Share on other sites

Guest mantragora

Since it returns it as a OP_Node and not as SOP_SParticle, registration part doesn't have access to any additional methods that where created in SOP_SParticle, just the ones that where inherited from OP_Node. Houdini doesn't need access to SOP_SParticle methods anywhere beside operator itself, so it's a safety solution.

PS. you can call myConstructor() method however you want. I like to name them CreateSOP() for SOPs, CreatePOP() for POPs and so on.

Edited by mantragora
Link to comment
Share on other sites

Guest mantragora

A good rule is, if a class have any virtual method, it should also have virtual destructor. There are other reasons for this too, but I think you will find better explanations for it on StackOverflow. I'm sure you will find there questions like these explained by C++ masters.

My advice, go thru OOP programming. Polymorphism, Abstract/Virtual keywords, inheritance and composition. It will be easier to undestand what is happening in HDK. Especially that we have now dependency graphs added to documentation that helps a lot in finding your way there.

Edited by mantragora
Link to comment
Share on other sites

So, I want to go through all the points of a geo and get their positions. Here is what I got so far, but I don't know how to actually get at the Position vectors.


GA_ROAttributeRef Patt;
UT_Vector3 mypos;
Patt = gdp->findFloatTuple(GA_ATTRIB_POINT, "P" ,3);
//Patt = gdp->findPointVectorAttrib(GA_SCOPE_PUBLIC, "P"); // OK?
GA_ROHandleT<UT_Vector3> poshandle(Patt.getAttribute());
if (Patt.isValid())
{
for (GA_Iterator it(gdp->getPointRange()); !it.atEnd(); it.advance())
{
GA_Offset offset = it.getOffset();
// get P like this?
poshandle.get(offset);
std::cout << "P: " << typeid(poshandle).name() << std::endl; // ?? how to get at P values?
// or like this?
mypos = gdp->getPos3(offset); //
std::cout << typeid(mypos).name() << std::endl;
}
}
[/CODE]

I have also seen [color=#000000][font=Lucida Grande', Verdana, Geneva, Arial, sans-serif][size=3][b]GA_FOR_ALL_GPOINTS. [/b][/size][/font][/color]Is that a preferred way to go through points?

Edited by Macha
Link to comment
Share on other sites

A few things:

You could just do

GA_ROAttributeRef Patt(gdp-&gt;getP());

to get the position without the need to do a search.

Your building of the vector handle could be simplified using the existing typedef and using P directly:

GA_ROHandleV3 poshande(gdp-&gt;getP());

poshandle.get(offset) will return a UT_Vector3 so you can just assign pos to the result:

pos = poshandle.get(offset);

GA_FOR_ALL_GPOINTS is frowned upon because it makes use of the old GEO_Point class which is deprecated.

In terms of keeping it simple I'd just do this:

GA_Offset ptOff;

UT_Vector3 pos;

GA_FOR_ALL_PTOFF(gdp, ptOff)
{
	pos = gdp-&gt;getPos3(ptOff);
// do something with the position.
}

Link to comment
Share on other sites

I've got geo now from a second input. I loop over the points and seem to be able to cast rays. I get a GU_Rayintersect object but, err, I'm not quite sure what to do with it. How can I find out what it has hit and where?


// get input1
const GU_Detail *input1 = inputGeo(1);
std::cout << "type :" << typeid(input1).name() << " info: " << input1->info(std::cout) << std::endl;

myCollision = new GU_RayIntersect; // remember its' a class member
//GU_RayIntersect myRay;
myCollision->init(input1);
UT_Vector3 searchdir(0.0, 0.0, 10.0);
GU_RayInfo info(searchdir.normalize()); // just testing
std::cout << " My collision: " << typeid(myCollision).name() << "\n";

//Loop over points
GA_Offset ptOff;
UT_Vector3 pos ;
GA_FOR_ALL_PTOFF(gdp, ptOff)
{
pos = gdp->getPos3(ptOff);
myCollision->sendRay(pos, searchdir, info);
std::cout << "myCollision type: " << typeid(myCollision).name()
<< "...." << myCollision
<< std::endl; // looks OK but now what?
}
[/CODE]

Edited by Macha
Link to comment
Share on other sites

untested but should work.


GA_FOR_ALL_PTOFF(gdp, ptOff)
{
pos = gdp->getPos3(ptOff);
// initialize hitInfo to hold hits
hitInfo.reset();
hitInfo.init(1e+6, 0.005, GU_FIND_CLOSEST, 0.001);
// send ray
int hitNum = myCollision->sendRay(pos, searchdir, hitInfo);
// check hit
if(hitNum)
{
// get prim hit by ray
const GEO_Primitive *hitPrim = hitInfo.myPrim;
float hitU = hitInfo.myU;
float hitV = hitInfo.myV;
// get position of hit
UT_Vector4 hitPos;
hitPrim->evaluateInteriorPoint(hitPos, hitU, hitV);

cout << hitPos << endl;
}
}
[/CODE]

Link to comment
Share on other sites

Thanks to everybody's input. I greatly appreciate it.

Here is what I have now.

I have added a function that returns sample positions based on stratified random samples. Just before the point loop I make a vector container with structs holding those positions, so they are the same for all points (at least for the moment).

Inside the loop I check for hits and then attempt at creating points at those hit positions.

Now, 2 problems with this:

- Would it be better to write those random sample positions inside a detail attribute (Once used I don't need them again) rather than the struct? ( Iwill eventually hold more info than just random sample positions)

- When I try to place points at the hit positions something goes a bit weird. Some points have crazy point numbers like 12844378292920. Not sure if that a viewport issue because in the details view it looks fine. The point positions also don't look correct, almost as if they were offset.


// get input1 where the collision geometry resides
const GU_Detail *input1 = inputGeo(1);
std::cout << "type :" << typeid(input1).name() << " info: " << input1->info(std::cout) << std::endl;

// make sample positions and store in a vector of SHSample structs
const int SAMPLENUM = 4;
int sqrt_samples = sqrt(SAMPLENUM);
std::vector<SHSample> sampleVecs(SAMPLENUM);
SH_setup_spherical_samples(sampleVecs, sqrt_samples); // writes stratified random spherical sample positions

// get ready for collision
myCollision = new GU_RayIntersect;
GU_RayIntersect myRay;
myCollision->init(input1);

//Loop over points
GA_Offset ptOff;
UT_Vector3 pos ;
GA_FOR_ALL_PTOFF(gdp, ptOff)
{
pos = gdp->getPos3(ptOff);

// for every random sample we generated before, search for hits
for (std::vector<SHSample>::iterator it=sampleVecs.begin(); it!=sampleVecs.end(); ++it)
{
UT_Vector3 searchdir;
searchdir = pos - it->vec;
GU_RayInfo hitInfo(searchdir.normalize());
hitInfo.reset();
hitInfo.init(1e+6, 0.005, GU_FIND_CLOSEST, 0.001);
int hitNum = myCollision->sendRay(pos, searchdir, hitInfo);
myCollision->sendRay(pos, searchdir, hitInfo);
// check hit
if(hitNum)
{
// get prim hit by ray
const GEO_Primitive *hitPrim = hitInfo.myPrim;
float hitU = hitInfo.myU;
float hitV = hitInfo.myV;

// get position of hit
UT_Vector4 hitPos;
UT_Vector3 primNormal;
hitPrim->evaluateInteriorPoint(hitPos, hitU, hitV);
std::cout << "\nHitpos: " << hitPos; // looks good

// try to add a point at hitPos
GEO_Point* appendPt = gdp->appendPoint(); // is it OK to append during a loop?
appendPt->setPos(hitPos); // hmmmmmmm
}
}
std::cout << std::endl;
}
[/CODE]

Link to comment
Share on other sites

Guest mantragora

Don't have time to check it more (I'm fighting with me own HDK project now :)) but what I can tell you is that appendPoint() is going down the pipes and is marked as deprecated. Use appendPointElementCopy() instead.

EDIT:

As for looping over points and adding them in the same loop, I don't think it's a good idea since you abuse amount of points that the loop is looping thru. I think I would store those points in some const list first and then loop thru this list just to be sure I'm going thru correct list of points and my loop is not going crazy. Or maybe crate temporary gdp to which you could add those points and on the end just add this gdp to original one.

Edited by mantragora
Link to comment
Share on other sites

You should probably be iterating over all the points from your node's input geometry, not the points of the current detail. This lets you change them without worry. Also, you shouldn't be using anything to do with GEO_Point. Those things are old and deprecated and slow. Use GA_Detail::appendPoint() to append a point and get the offset back.

Link to comment
Share on other sites

Guest mantragora

I think Graham meant appendPointOffset()

Maybe third answer will be lucky ;)

It looks that even appendPointElementCopy() is SYS_DEPRECATED_HDK(13.0). That's why you need to learn finding your way in documentation on your own. HDK is going thru a lot of changes because of this new GA library.

Link to comment
Share on other sites

OK, so this is what I came up with. It works but let's hope it's the 'correct' way:

before looping over the points:


std::vector<UT_Vector4> hitPositions;
[/CODE]

during looping (only input0 gdp) I write the hit positions into the container:

[CODE]
hitPositions.push_back(hitPos);
[/CODE]

Finally, after the loop I create the extra points with the offsets:

[CODE]
for (std::vector<UT_Vector4>::iterator it=hitPositions.begin(); it!=hitPositions.end();++it)
{
std::cout << "\n..hit positions: " << *it;
GA_Offset appendPtOff = gdp->appendPointOffset();
gdp->setPos3(appendPtOff, *it);
}[/CODE]

Edited by Macha
Link to comment
Share on other sites

If you're looping over input0's gdp, why do you need to store the positions? If you are, then you might as well just do a single appendPointBlock() first ...

GA_Offset ptoff = gdp-&gt;appendPointBlock(hitPositions.size());
for (int i = 0; i &lt; hitPositions.size(); i++, ptoff++)
    gdp-&gt;setPos3(ptoff, hitPositions[i]);

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...