I was wanting to simulate buoyancy, as
seen on this page.
I did a quick source search, and I found a lot of AABB intersection functions, but didn't see anything that does polygon intersection.
No problems with [strike]rolling my own[/strike] stealing code, just don't want to reinvent the wheel.
Comments
As for the ComputeCentroid function, it could be simplified a bit given that pRef is always (0, 0).
- For all points in your polygon
- Look on which side of your water line it is
-> on the correct side (ie. underwater), then add it to your result
-> on the other side, find the intersection of the polygon segment (defined by previous point and the current tested point) and the water line and add it to your polygon result
There's a special case where the first point you test is out of water, in which case you'll need to add the intersection point the first time you get underwater.
There are many ways of handling this, one option would be to iterate first through all the points in your poly till you find one underwater, and when you're done clipping, if you didn't start with the first point underwater, then add the intersection of the segment formed by the point with which you started and its previous on with the water line, and add it as the last vertex of your polygon.
Sorry if all his doesn't sound very clear, if need be I can provide you with some code, but not sure when.
Thanks for your timely and helpful reply.
This leads to a new question: How do I get the vertices of a body part from within an events handler.
I see that orxBODY has an orxBODY_GetNextPart function, but when I attempt to get an orxBODY * using orxBODY(), I only ever get null.
Not sure how orxBODY is different/same as orxPHYSICS_BODY.
Below, everything in side the if-block marked 'experimental' is what I'm trying to make work. Everything below that is currently working for my current crappy approach to buoyancy.
As you've already guessed, the orxBODY is a component of the orxOBJECT you get from the event. A call to orxOBJECT_GET_STRUCTURE(pstObject, BODY) should do the trick.
That being said, as you're using Scroll, I'd recommend overriding the method ScrollObject::OnCollide() instead of listening to the contact event.
Globally, the orxPhysics API is the low level part mostly used by orx itself and whose structures are dependent on the plugin implementation and never exposed to orx's core, and even less to orx users, whereas the orxBody API is the "public" one.
As for getting the list of vertices, you'll have to push the part name's config section and read the vertex list from there. Don't forget they're expressed in local coordinates, so if you want them in world coordinates, you'll have to transform them by using the object's world position/rotation/scale.
The easy way to do that is to create an orxFRAME, set your object as parent, then set its local position with the vertex info and finally get the world position out of it. There's an enum to control which coord of the local or global you want to access with the Set/Get accessors.
- when you have an orxSTRUCTURE and you don't know which kind it is, a call to orxStructure_GetID() will give you the answer.
- when you have a ScrollObject and you want to downcast it to a child class of yours (and you know it's the right class), you can use the ScrollCast<MyClass>() instead of a dynamic_cast<>(). In practice it'll do a dynamic cast in debug and a static one in release, for performance sake.
This is the code I ended up using; I get compile errors when using 'orxOBJECT_GET_STRUCTURE' and 'BODY'
I saw that when I was poking around; I'm going to use it instead.
What compile error do you get exactly with this code?
Doesn't this assume that it follows the BodyPartMeshTemplate, and as such has a 'VertexList' parameter?
My particular body part looks like this:
For my (admittedly narrow) purpose, it would be nice to extract vertices from an already existing orxBODY_PART structure. Naturally spheres would return no vertices, and be a special case.
WRT use of orxFRAME, would I do setPosition with orxFRAME_SPACE_LOCAL followed by getPosition with orxFRAME_SPACE_GLOBAL? GLOBAL == WORLD?
Yes, I assumed you had a mesh. It works the same for a box though, you can get the four vertices from the TopLeft/BottomRight values.
Unfortunately orx doesn't have the info on the vertices either, I'd need to extract them all the way down from the plugin implementation, it feels like a big change affecting 3 different API layers (plugin, internal, public) for very little benefit. I'll think about it more.
Yes and yes.
Would you accept a patch?
Out of curiosity which approach are you going to take?
Looks like I'll need to add a new function to the physics plugin api, and work my way up from there. Is there any other way?
I' d support circle shapes as well, by making a regular convex polygon with the max allowed vertices for a shape, I think it's 8 by default for Box2D.
And yes, the fork button is what you want.
This is causing me a bit of trouble; it seems that it re-applies the Scale argument ... ? It was late last night, and I couldn't investigate further. I'll check it out tonight.
If you get your list of vertices from Box2D itself, you should ask it to get them in world coordinates and not in Box2D local (which are different from orx's local as Box2D doesn't do scale). You'll then need to apply the ratio between Box2D units (meters) and orx's (pixels), but you should be able to retrieve that one from orx.
I have it working, and Here's what I did:
1) Get untransformed vertices from orxPhysics plugin (from b2Fixture.shape)
For each vertice:
2) Multiply by the reciprocal of the dimension ratio
3) Translate to object pivot
4) Rotate to object rotation
5) Translate to object position
6) Translate to screen coordinates
7) Draw on screen
#1 is the new code I added to the orx code base
#2 --> 5 are in a render handler
#6, 7 are in a generic "Draw Polygon" function that I modified from the orxPhysics debug draw.
I wanted to get a custom debug draw working well, as I'll use it for debugging the actual buoyancy stuff.
Raw just-got-working code:
If I were to store them that'd mean:
- no need to modify the physics plugin interface
- scaling bodies could be done even for programmatically defined bodies (right now we're reloading the def from config everytime the scale changed)
- one could get all the info relevant to a body part, not just only the vertices, allowing for better debug drawing (sensor vs non-sensor, density, friction, restitution, collision flags/masks, ...)
- it would work out of the box in orx's world coordinates, no dimension ratio, no scaling issues
It should be a pretty straightforward modification and I could probably do it over the week-end.
Sorry not to have thought about that earlier.
Only one hitch. I have to take my calculated buoyancy force and divide it by 1,000,000. I had half expected that it would have to be divided by 10,000, since the dimension ratio is 100, so the mass in box2d would be the square of the dimension ratio.
The 1,000,000 number works perfectly; objects that are 1/2 the density of the fluid will float 1/2 out of the fluid, etc.
Any ideas?
It's weird indeed. I'll have a look when I get a computer back. If you could share your project with me, it'll make the investigation easier too, no hurries though.