Daniel Posted February 22, 2006 Share Posted February 22, 2006 Hello All, I've updated the source code in CVS and released a new package to download with the latest changes/additions. I've done a bit of work on it in my spare time with the hope that it would spur some interest and contributions from other people in the Houdini comunity. The project page is: http://sourceforge.net/projects/odforceplugins You'll also need to download ODE to compile this (you can get pre-compiled version of ODE which makes this easy) http://ode.org/download.html I've included a sample .hip file in the archive that outlines the features I've added. There's still a lot that can be done to improve/extend the solver and any feedback is appreciated. Mark Tucker of SESI sent me some very detailed feedback on how to improve what I have so far.. I'll post his feedback in this forum as well. I plan on posting feedback, todo's, etc on the project page so the ideas don't get lost. I'm ramping up in my current production and Sony and it's going to me more difficult for me to contribute regularly Daniel Quote Link to comment Share on other sites More sharing options...
Daniel Posted February 22, 2006 Author Share Posted February 22, 2006 Mark Tucker of SESI sent me some very detailed feedback on how to improve what I have so far.. I'll post his feedback in this forum as well. 24952[/snapback] Here it is: Now on to the code:First, I notice that you have a SIM_OdeData data type, but it isn't used anywhere. I assume it was meant to do the job that you ended up using a SIM_EmptyData for in the odeBody OTL. Both approaches are fine, but creating your own data type like SIM_OdeData lets you use those GETSET_DATA_FUNCS() macros and create PRM_Templates which make for a cleaner interface (both in the code and for the user). Not a big deal though since you have the OTL wrapper. Similarly mySIM_Geometry has one function that SIM_Geometry doesn't have, but that function is never caledin the code. So I would just get rid of those classes. In the specific case of mySIM_Geometry, if you want to be able to modify the gdp of a SIM_Geometry directly, you should use a SIM_GeometryCopy data type (you didn't need to create your own class). As a final note on mySIM_Geometry, on line 351 you cast a "const SIM_Geometry *" to a "mySIM_Geometry *", which you should never ever do with the SIM library. Even though in this case the cast to mySIM_Geometry is safe (since mySIM_Geometry has no virtual functions or member data), the casting away of the const is a mortal sin in DOPs. Doing so lets you modify data that is shared by mutliple objects, or used inthe cache (so you are modifying data back in time). If you do find that you need the funtionality provided by mySIM_Geometry::setGdp, I would suggest you use code like this: SIM_GeometryCopy *modgeo; modgeo = SIM_DATA_CREATE(*currObject, SIM_GEOMETRY_DATANAME, SIM_GeometryCopy, SIM_DATA_RETURN_EXISTING | SIM_DATA_ADOPT_EXISTING_ON_DELETE); if( modgeo ) { GU_Detail *modgdp = modgeo->lockGeometry(); // modify modgdp any way you want modgeo->releaseGeometry(); } The other big problem I see is your use of gobal data for m_odeGlobals and m_odeBodies. This means you can't have more than one ODE solver simulation in any hip file. I woudl suggest creating a SIM_Data subclass to hold this information instead. Somthing like this: class SIM_OdeWorldData : public SIM_Data { public: odeGlobals &getOrCreateOdeGlobals() { return m_odeGlobals; } std::map<int, odeBody> &getOdeBodies() { return m_odeBodies; } protected: explicit SIM_OdeWorldData(const SIM_DataFactory *factory) : BaseClass(factory), m_odeBodies(0), m_odeGlobals(0), m_shareCount(0) { } virtual ~SIM_OdeWorldData() { clear(); } // This ensures that this data is always kept in RAM, even when // the cache runs out of space and writes out the simulation // step to disk. This is necessary because the ODE data can't // be written to disk. virtual bool getCanBeSavedToDiskSubclass() const { return false; } // Start fro scratch. We create a brand new world. virtual void initiailizeSubclass() { clear(); m_odeBodies = new std::map<int, odeBody>(); m_odeGlobals = new odeGlobals(); m_shareCount = new int(1); } // To make one world equal to another, copythe data exactly. // The share count lets several of these data share the same // ODE world and bodies without worrying that the ODE data // will get deleted as long as any SIM_OdeWorldData is holding // onto it. virtual void makeEqualSubclass(const SIM_Data *src) { SIM_OdeWorldData *world; world = SIM_DATA_CASTCONST(src, SIM_OdeWorldData); if( world ) { clear(); m_shareCount = world->m_shareCount; m_odeBodies = world->m_odeBodies; m_odeGlobals = world->m_odeGlobals; (*m_shareCount)++; } } private: void clear() { if( m_shareCount ) { (*m_shareCount)--; if(*m_shareCount == 0) { m_odeBodies.clear(); delete m_odeGlobals; delete m_shareCount; } } m_shareCount = 0; m_odeGlobals = 0; m_odeBodies = 0; } std::map<int, odeBody> *m_odeBodies; odeGlobals *m_odeGlobals; int *m_shareCount; } I also notice that m_odeBodies.clear() probably doesn't free the ODE bodies, and deleting m_odeGlobals doesn't delete the ODE World. That should probably be fixed too in the clear() function... So now that you have this SIM_Data for storing the global data, in the solver, instead of doing: if(currTime == 0 || !m_odeGlobals ) initSystem(); do: SIM_OdeWorldData *worlddata; worlddata = SIM_DATA_CREATE(*this, "ODEWorld", SIM_OdeWorldData, SIM_DATA_RETURN_EXISTING); This will create a new SIM_OdeWorldData if one isn't there already, otherwise it will return a copy of the one that is already there (it returns a _copy_ of the one that's already there because you are asking for a non-const pointer). When it makes that copy, it will use makeEqualSubclass to make the copy equal to the old one, so essentially you'll be getting back the same ODE world data. A few other points. You can probably simplify the code for dealing with constraints a lot by using the SIM_ConstraintIterator class. It provides an interface to loop through all constraints of a particular type. It should be easier than looping through the constraints yourself. You should also never have to go through the "getQueryObject" functionin the solver code. You have the following code: goalAnchor->getQueryObject().getFieldString ("Options", 0, "objectname", goalObjName); Which works fine, but is much slower than: goalobj = goalAnchor->getReferencedObject(time); I would definitely split processSubData into two functions, processConstraints and procesForces. processConstraints should be something like: // Initialize all constraints. This gives constraints a chance to // prepare themselves for use, such as by looking up their // goal objects. SIM_ConstraintIterator::initConstraints(*object, time); SIM_DataFilterByType anchorFilter("SIM_ConAnchor"); SIM_ConstratinIterator conit(*object, 0, &anchorFilter, &anchorFilter, time); for (conit.rewind(); !conit.atEnd(); conit.advance()) { SIM_ConRel *conrel; const SIM_ConAnchorSpatial *spanchor, *goalspanchor; const SIM_ConAnchorRotational *rotanchor, *goalrotanchor; conrel = conit.getRelationship(); spanchor = SIM_DATA_CASTCONST(it.getCurrentAnchor(), SIM_ConAnchorSpatial); goalspanchor = SIM_DATA_CASTCONST(it.getGoalAnchor(), SIM_ConAnchorSpatial); if( spanchor && goalspanchor ) { // Handle spatial constraints. } rotanchor = SIM_DATA_CASTCONST(it.getCurrentAnchor(), SIM_ConAnchorRotational); goalrotanchor = SIM_DATA_CASTCONST(it.getGoalAnchor(), SIM_ConAnchorRotational); if( rotanchor && goalrotanchor ) { // Handle Rotational constraints. } } As for forces, you don't need to handle each force type individually. You should use the functions on the SIM_Force base class. Also, there are functions for making a calback for all data that matches a particular data type. So processForces would look something like: /// /// This is a helper class to iterate over all the forces on an object /// and sum them up. /// class ODE_EachForceCallback : public SIM_EachDataCallback { public: ODE_EachForceCallback(const UT_Vector3 &pos, const UT_Vector3 &vel, const UT_Vector3 &angvel, const fpreal mass, UT_Vector3 &force, UT_Vector3 &torque) : myPosition(pos), myVelocity(vel), myAngVel(angvel), myMass(mass), myForce(force), myTorque(torque) { } virtual ~ODE_EachForceCallback() { } virtual void callbackConst(const SIM_Data *data, const char *name); private: UT_Vector3 myPosition; UT_Vector3 myVelocity; UT_Vector3 myAngVel; fpreal myMass; UT_Vector3 &myForce; UT_Vector3 &myTorque; }; void ODE_EachForceCallback::callbackConst(const SIM_Data *data, const char *) { const SIM_Force *forcedata = SIM_DATA_CASTCONST(data, SIM_Force); UT_Vector3 force, torque; forcedata->getForce(myPosition, myVelocity, myAngVel, myMass, force, torque); myForce += force; myTorque += torque; } processForces(SIM_Object *object) { // Grab the velocity, angular velocity, mass, and center of // mass fromthe object (from the Position data). UT_Vector3 sumforces(0.0, 0.0, 0.0); UT_Vector3 sumtorque(0.0, 0.0, 0.0); ODE_EachForceCallback callback(com, vel, angvel, mass, sumforces, sumtorques); object->getObject()->forEachConstSubData(callback, SIM_DataFilterByType("SIM_Force"), SIM_FORCES_DATANAME, SIM_DataFilterNone()); // Apply sumforces and sumtorques to object... } I also noticed you calling getNthConstSubData to grab the force and constraint data. You should avoid this function whenever possible. If you call this function for each subdata, you've created an O(n^2) algorithm on the number of subdata. As a final point, I notice you don't create SIM_Impacts data on the objects. This is fine, and I don't even know if the ODE Solver is able to provide equivalent information. But if it is possible, outputting impacts into SIM_Impacts data would allow the ODE Solver to work with the SOP Solver to do denting and other such effects. You also need to be able to generate and respond to SIM_Impacts data to work with other solvers (like the cloth solver). But given the way ODE handles constraints, I don't know how much luck you'll have generating the impact information you need when one of the objects in the collision is cloth (a deforming triangle mesh). But this is all definitely more advanced funcitonality which is not required for just a solid RBD Solver. I'm going to cut myself off there. I hope you find this all helpful (but not overwhelming). If you want to post these comments more publicly (to odforce when you announce your changes, or to sourceforge) so that other people can do some of the work please feel free. And if you have more questions, please ask. All the "code" above is just off the top of my head so is no doubt full of syntactical and logical errors). Thanks for all the effort you've put into this. It's really great to see a serious open source DOPs solver... Mark Quote Link to comment Share on other sites More sharing options...
Jason Posted February 22, 2006 Share Posted February 22, 2006 Daniel, This is some awesome work here! Thank you very much. Here is a RedHat 9 compile that should work with the 8.0.474 production build of Houdini. (I will upload this to odforce soon!) SIM_SolverODE_0.2.so.gz Quote Link to comment Share on other sites More sharing options...
Daniel Posted February 22, 2006 Author Share Posted February 22, 2006 Thanks Jason! We'll probalby want to put pre-compiled plugins in the sourceforge site. For those of you who are just trying this out, you'd be wise to download the latest package on the sourceforge site. The solver really depends on a couple of OTL's to define the ode bodies. The sourceforge package includes that along with a sample hip file with various examples d Quote Link to comment Share on other sites More sharing options...
Marc Posted February 22, 2006 Share Posted February 22, 2006 Woo! Thanks Dan . Spare time eh? Enjoy it while it lasts Quote Link to comment Share on other sites More sharing options...
Jason Posted February 22, 2006 Share Posted February 22, 2006 Agh, I meant sourceforge, not odforce. Can anyone drop a Windows compile for 8.0.474 here too? Quote Link to comment Share on other sites More sharing options...
MADjestic Posted February 22, 2006 Share Posted February 22, 2006 so, this beast really works, huh? Quote Link to comment Share on other sites More sharing options...
Jason Posted February 22, 2006 Share Posted February 22, 2006 so, this beast really works, huh? 24960[/snapback] Yup, it seems to! Daniel did a marvellous job of getting a great first version out there it seems. I've played with all of his demo scenes and they work just brilliantly; and it seems like they'll get faster if we manage to get some of Mark's suggested enhancements in there. I've been trying to get the Windows version to compile for me but I'm really bad at it:) The linux one was smoothe to build but not on my Windows machine. Quote Link to comment Share on other sites More sharing options...
Daniel Posted February 22, 2006 Author Share Posted February 22, 2006 Yup, it seems to! Daniel did a marvellous job of getting a great first version out there it seems. I've played with all of his demo scenes and they work just brilliantly; and it seems like they'll get faster if we manage to get some of Mark's suggested enhancements in there.I've been trying to get the Windows version to compile for me but I'm really bad at it:) The linux one was smoothe to build but not on my Windows machine. 24961[/snapback] I should be able to get a windows ver going (hell, I worked on it under windows!). I need to install 8.0.474 here at home first, then I'll post it up. They way I had it the wondow's ver required the ode.dll in your path. I'm assuming I can build it staticly so it's all baked in? In any event, it's not a big deal to have the ode.dll as well. Probably won't get to this until tomorrow night d Quote Link to comment Share on other sites More sharing options...
Daniel Posted February 22, 2006 Author Share Posted February 22, 2006 Woo! Thanks Dan . Spare time eh? Enjoy it while it lasts 24958[/snapback] Heh, yea.. that time will die out I'm afraid. We start lighting our first sequence next month. I did most of this work a few months ago, just waited on the offical "ok" from Sony before posting anything. Work is much more demanding these days d Quote Link to comment Share on other sites More sharing options...
sibarrick Posted February 22, 2006 Share Posted February 22, 2006 Fantastic stuff Daniel, I haven't tried it yet but I will. Jason, maybe sodaPlay will now be possible Quote Link to comment Share on other sites More sharing options...
Mario Marengo Posted February 22, 2006 Share Posted February 22, 2006 Great stuff Daniel (and Mark for the great insights)! Thank you for sharing all you hard work. I would like to officially place my vote for extending days by at least 6 hrs. so that we can all have time to explore things like this... *sigh* ... oh wait, I guess that would mean shortening work days by 6 hrs... all in favor say aye! Quote Link to comment Share on other sites More sharing options...
stevenong Posted February 22, 2006 Share Posted February 22, 2006 I'm afraid 6 more hours won't be enough for Dan soon. Quote Link to comment Share on other sites More sharing options...
Daniel Posted February 23, 2006 Author Share Posted February 23, 2006 Agh, I meant sourceforge, not odforce. Can anyone drop a Windows compile for 8.0.474 here too? 24959[/snapback] Attached is a Windows Compile of the solver ( 8.0.474 ): SIM_SolverODE_0.2.zip Again, you'll still want to download the latest sourceforge distribution to get a sample hip file and a couple of support Digital Assests. The solver is farily useless without the Digital Assets to attach some solver specific attributes Daniel Quote Link to comment Share on other sites More sharing options...
craig Posted February 23, 2006 Share Posted February 23, 2006 A couple of things for people trying to follow along at home: If you are compiling on linux, the compile.sh file that does the compile, refers to SIM_SolverODE.C but there is no such file, there is only SIM_SolverODE.cpp. So you need to rename the .cpp file to .C The config.sh script says you "probably" have to comment out the typedef of int8 in ode-0.5/include/common.h. In fact, you definitely have to do this, and the file is actually ode-0.5/include/ode/config.h After that, it's all gravy! Quote Link to comment Share on other sites More sharing options...
Jason Posted February 23, 2006 Share Posted February 23, 2006 How would you (i.e., a coder better than me: anyone) suggest that we fix this type of thing? Are there namespaces or such that'd be able to scope typedefs like this to certain source files? Is it a SESI thing, an ODE thing or can the plugin developers just do it themselves somehow without having to modify the ODE or HDK headers (with potentially disasterous consequences)? Jason PS. Thanks for the Windows compile, Daniel. Quote Link to comment Share on other sites More sharing options...
MADjestic Posted March 26, 2006 Share Posted March 26, 2006 Woah, guys! I've just installed the ODE solver and it works all right. Marvelous job! It may sound silly to just say "thanks" and that's it, but... thank you thank you thank you =) PS. oh, yeah. I've just forgot to thank you once more. Quote Link to comment Share on other sites More sharing options...
Daniel Posted March 26, 2006 Author Share Posted March 26, 2006 Woah, guys!I've just installed the ODE solver and it works all right. Marvelous job! It may sound silly to just say "thanks" and that's it, but... thank you thank you thank you =) PS. oh, yeah. I've just forgot to thank you once more. 25967[/snapback] You're Welcome, You're Welcome, You're Welcome I hope as some of the coders free up they can continue to build on it.. me, I'm starting to get my hands full with work and life d 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.