Macha Posted November 2, 2013 Share Posted November 2, 2013 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. Quote Link to comment Share on other sites More sharing options...
graham Posted November 2, 2013 Share Posted November 2, 2013 I've done this using http://www.sidefx.com/docs/hdk13.0/class_g_u___ray_intersect.html Quote Link to comment Share on other sites More sharing options...
Macha Posted November 2, 2013 Author Share Posted November 2, 2013 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? Quote Link to comment Share on other sites More sharing options...
Guest mantragora Posted November 2, 2013 Share Posted November 2, 2013 (edited) 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 November 2, 2013 by mantragora Quote Link to comment Share on other sites More sharing options...
Macha Posted November 3, 2013 Author Share Posted November 3, 2013 Ah, and is that also why the destructor is virtual? Quote Link to comment Share on other sites More sharing options...
Guest mantragora Posted November 3, 2013 Share Posted November 3, 2013 (edited) 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 November 3, 2013 by mantragora Quote Link to comment Share on other sites More sharing options...
Macha Posted November 4, 2013 Author Share Posted November 4, 2013 (edited) 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 November 4, 2013 by Macha Quote Link to comment Share on other sites More sharing options...
graham Posted November 4, 2013 Share Posted November 4, 2013 A few things: You could just do GA_ROAttributeRef Patt(gdp->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->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->getPos3(ptOff); // do something with the position. } Quote Link to comment Share on other sites More sharing options...
Macha Posted November 5, 2013 Author Share Posted November 5, 2013 (edited) 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 input1const 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 testingstd::cout << " My collision: " << typeid(myCollision).name() << "\n";//Loop over pointsGA_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 November 5, 2013 by Macha Quote Link to comment Share on other sites More sharing options...
Macha Posted November 5, 2013 Author Share Posted November 5, 2013 (edited) double post Edited November 5, 2013 by Macha Quote Link to comment Share on other sites More sharing options...
petz Posted November 5, 2013 Share Posted November 5, 2013 untested but should work. GA_FOR_ALL_PTOFF(gdp, ptOff){pos = gdp->getPos3(ptOff);// initialize hitInfo to hold hitshitInfo.reset();hitInfo.init(1e+6, 0.005, GU_FIND_CLOSEST, 0.001);// send rayint hitNum = myCollision->sendRay(pos, searchdir, hitInfo);// check hitif(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] Quote Link to comment Share on other sites More sharing options...
Macha Posted November 6, 2013 Author Share Posted November 6, 2013 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] Quote Link to comment Share on other sites More sharing options...
Macha Posted November 6, 2013 Author Share Posted November 6, 2013 Sorry, my bad, the collision appears to work. So the questions that remain are whether adding points like this in a loop is acceptable, and if a struct is the way to go. Quote Link to comment Share on other sites More sharing options...
Guest mantragora Posted November 6, 2013 Share Posted November 6, 2013 (edited) 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 November 6, 2013 by mantragora Quote Link to comment Share on other sites More sharing options...
graham Posted November 6, 2013 Share Posted November 6, 2013 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. Quote Link to comment Share on other sites More sharing options...
Macha Posted November 7, 2013 Author Share Posted November 7, 2013 (edited) How do you use GA_Detail::appendPoint() ? I tried (C11): auto appendPt = gdp->appendPoint();[/CODE] and when I query the type it created it returns GEO_Point. Edited November 7, 2013 by Macha Quote Link to comment Share on other sites More sharing options...
symek Posted November 7, 2013 Share Posted November 7, 2013 (edited) I think Graham meant appendPointOffset() Edited November 7, 2013 by symek Quote Link to comment Share on other sites More sharing options...
Guest mantragora Posted November 7, 2013 Share Posted November 7, 2013 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. Quote Link to comment Share on other sites More sharing options...
Macha Posted November 7, 2013 Author Share Posted November 7, 2013 (edited) 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 November 7, 2013 by Macha Quote Link to comment Share on other sites More sharing options...
edward Posted November 7, 2013 Share Posted November 7, 2013 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->appendPointBlock(hitPositions.size()); for (int i = 0; i < hitPositions.size(); i++, ptoff++) gdp->setPos3(ptoff, hitPositions[i]); Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.