Buoyancy issues / water collision
by Scott Przybylski · in Torque 3D Professional · 05/22/2012 (9:58 am) · 8 replies
Hello, first off, I'm new to T3D, just bought it the other day after messing with the demo for a couple days.
My plan is to eventually make a boat racing game/sim, but as an initial physics test I was just trying to add a buoy that floats on the water. Unfortunately I'm having some issues. I was able to load the buoy mesh, setup the materials, and after much tinkering add the PhysicsShapeData.
I dropped the buoy onto the scene, started the physics simulation and the buoy started bouncing off the water up into the air. I eventually managed to mess with the parameters enough so that it would sit on the water. Here's where I'm having problems.
Either the buoy increasingly bounces higher, or eventually stops bobbing and the physics simulation freezes it. How do I get it to bob constantly in the water like something would in real life? Also there appears to be no pitch/roll, it only bobs straight up and down. How would I make it so that it pitches and rolls when it floats?
Thanks,
Scott
My plan is to eventually make a boat racing game/sim, but as an initial physics test I was just trying to add a buoy that floats on the water. Unfortunately I'm having some issues. I was able to load the buoy mesh, setup the materials, and after much tinkering add the PhysicsShapeData.
I dropped the buoy onto the scene, started the physics simulation and the buoy started bouncing off the water up into the air. I eventually managed to mess with the parameters enough so that it would sit on the water. Here's where I'm having problems.
Either the buoy increasingly bounces higher, or eventually stops bobbing and the physics simulation freezes it. How do I get it to bob constantly in the water like something would in real life? Also there appears to be no pitch/roll, it only bobs straight up and down. How would I make it so that it pitches and rolls when it floats?
Thanks,
Scott
About the author
Attempting to create a Hydroplane Racing simulation with Torque 3D.
#2
To properly simulate buoyancy on your vehicle, you basically need to figure out some partitioning scheme (you can also just use the vertices of the mesh, but the problem with it is that it *has* to be symmetrical or the boat will just roll over) in order to determine where you'll apply buoyancy forces along the object.
After you figure out a partitioning scheme you can work on making the buoyancy physics work properly. You'll basically just add the forces in like it does for the current buoyancy, but for each point given by your partition scheme instead of for one point only. This should give you proper rotation and the like. To get it feeling right you'll also need to add in drag and such.
05/23/2012 (12:08 pm)
@Scott, this is because the buoyancy model used is quite simple from what I recall. You'll need to create something more complex if you want to have a water surface suitable for running boats on. I suggest figuring out where it does the buoyancy calculation in the engine, then making a special version of it for the WaterVehicle class. To properly simulate buoyancy on your vehicle, you basically need to figure out some partitioning scheme (you can also just use the vertices of the mesh, but the problem with it is that it *has* to be symmetrical or the boat will just roll over) in order to determine where you'll apply buoyancy forces along the object.
After you figure out a partitioning scheme you can work on making the buoyancy physics work properly. You'll basically just add the forces in like it does for the current buoyancy, but for each point given by your partition scheme instead of for one point only. This should give you proper rotation and the like. To get it feeling right you'll also need to add in drag and such.
#3
What do you mean by a partitioning scheme?
Also, how would I access mesh information from PhysicsShape? I can't see anyway to do that. I'm guessing I would need that information to determine how deep underwater certain points are to calculate the force?
As a quick test, I tried to take the bounding box of the object using getWorldBox(). I then iterated through the points doing the calculation that was already there. Surprisingly it worked really well for my buoy object. However, the boat model seemed to bounce out of control.
Thanks,
Scott
05/23/2012 (10:15 pm)
@Ross, so I've figured out where its doing the buoyancy calculation in void PhysicsShape::_updateContainerForces(). What do you mean by a partitioning scheme?
Also, how would I access mesh information from PhysicsShape? I can't see anyway to do that. I'm guessing I would need that information to determine how deep underwater certain points are to calculate the force?
As a quick test, I tried to take the bounding box of the object using getWorldBox(). I then iterated through the points doing the calculation that was already there. Surprisingly it worked really well for my buoy object. However, the boat model seemed to bounce out of control.
Thanks,
Scott
#4
I'll have to look into how the buoyancy is working with PhysicsShapes. You may need to create a more accurate PhysicsShape for your vehicle. I have some code that allows you to easily create more custom PhysX shapes for a vehicle. I'll have to grab it while I'm at home, but the gist of it is that you use the collision primitive type markers in your 3d application (i.e., colbox, colsphere, colmesh, colcapsule along with collision-1 etc markers) and then pass in the Shape itself to the PhysicsShape builder.
Anyway I'll grab that when I get home and post up an explanation and the code.
05/25/2012 (10:41 am)
By partitioning scheme, I just mean some way to separate an arbitrary model into some sort of regular grid. A simple way of doing this would be to figure out some heuristic to use in order to make a set of bounding boxes that would cover the model better than a single bounding volume. The reason it's acting funny right now is that the buoyancy is being applied at the wrong places/not enough places. After you'd partition it somehow, you could use those as the points to apply physics for buoyancy instead of whatever it's doing now (like you did with the buoy, but the vehicle will need more to be stable).I'll have to look into how the buoyancy is working with PhysicsShapes. You may need to create a more accurate PhysicsShape for your vehicle. I have some code that allows you to easily create more custom PhysX shapes for a vehicle. I'll have to grab it while I'm at home, but the gist of it is that you use the collision primitive type markers in your 3d application (i.e., colbox, colsphere, colmesh, colcapsule along with collision-1 etc markers) and then pass in the Shape itself to the PhysicsShape builder.
Anyway I'll grab that when I get home and post up an explanation and the code.
#5
They do their buoyancy calculation from the water class rather than the physics body, however I think that's also, so they can deform the water. I was thinking, since I'm probably going to be using the infinite Water Plane, maybe I could use the physicsShape bounding box to come up with a horizontal grid (this sounds similar to what you said). Then use an arbitrary depth lower than the water height and RayCast up to find the depth, so I can calculate the volume of displaced water.
By a set of bounding boxes, do you mean to have multiple collision primitives, and get the bounding box of each of those? If I figured out the total area in x, y of the shape. Can I just RayCast up from the bottom of the water and the physics library will handle testing the multiple collision shapes?
Thanks for your help,
Scott
05/25/2012 (11:24 am)
OK, cool, I aslo looked at the Open Source PAL projects code, so I could see how they did the buoyancy and I think I finally I understand what needs to be done. It looks like they split the water mesh up into a grid, then RayCast up from the water depth.They do their buoyancy calculation from the water class rather than the physics body, however I think that's also, so they can deform the water. I was thinking, since I'm probably going to be using the infinite Water Plane, maybe I could use the physicsShape bounding box to come up with a horizontal grid (this sounds similar to what you said). Then use an arbitrary depth lower than the water height and RayCast up to find the depth, so I can calculate the volume of displaced water.
By a set of bounding boxes, do you mean to have multiple collision primitives, and get the bounding box of each of those? If I figured out the total area in x, y of the shape. Can I just RayCast up from the bottom of the water and the physics library will handle testing the multiple collision shapes?
Thanks for your help,
Scott
#6
Oh, I guess I should also mention that I'm using a colmesh that is just a basic pyramid for this shape.
Another Update:
If I use a convex hull with bullet, it seems like it starts to work. When I drop the buoy in, it starts to rotate, but then when the other part of the buoy goes in, it seems to just speed up the rotation rather than go back the other direction, so it just starts to spin continuously.
Thanks,
Scott
05/27/2012 (12:02 pm)
OK, so I went ahead and tried to implement what I mentioned above, unfortunately, its not working how I expected. Using bullet, the shape acts pretty much exactly like it used to, where it just bounces straight up and down. In PhysX, the buoy appears to get launched sideways, spinning out of control and dissapears. Here's my code so far, any help would be greatly appreciated!Oh, I guess I should also mention that I'm using a colmesh that is just a basic pyramid for this shape.
Another Update:
If I use a convex hull with bullet, it seems like it starts to work. When I drop the buoy in, it starts to rotate, but then when the other part of the buoy goes in, it seems to just speed up the rotation rather than go back the other direction, so it just starts to spin continuously.
void PhysicsShape::_updateContainerForces()
{
PROFILE_SCOPE( PhysicsShape_updateContainerForces );
// If we're not simulating don't update forces.
if ( !mWorld->isEnabled() )
return;
ContainerQueryInfo info;
info.box = getWorldBox();
info.mass = getDataBlock()->mass;
// Find and retreive physics info from intersecting WaterObject(s)
getContainer()->findObjects( getWorldBox(), WaterObjectType|PhysicalZoneObjectType, findRouter, &info );
// Calculate buoyancy and drag
F32 angDrag = getDataBlock()->angularDamping;
F32 linDrag = getDataBlock()->linearDamping;
//Get the bottom plane of the bounding box
Point3F tl = info.box.computeVertex(info.box.FarBottomLeft);
Point3F tr = info.box.computeVertex(info.box.FarBottomRight);
Point3F bl = info.box.computeVertex(info.box.NearBottomLeft);
Point3F br = info.box.computeVertex(info.box.NearBottomRight);
//Get the width/height of the bottom plane
F32 width = mSqrt(mSquared(tr.x - tl.x) + mSquared(tr.y - tl.y));
F32 height = mSqrt(mSquared(bl.x - tl.x) + mSquared(bl.y - tl.y));
//Make the plane square
if(width < height)
width = height;
else
height = width;
//For now just pick an arbitrary grid size
F32 step = width / 50.0;
//The center of the grid cell
F32 cellCenter = step * 0.5f;
F32 density = getDataBlock()->buoyancyDensity;
for(int j = 0; j < 50; j += 1) {
for(int i = 0; i < 50; i += 1) {
//Get the x, y coordinates of the first cell
F32 x = (tl.x + (i * step)) - cellCenter;
F32 y = (tl.y - (j * step)) + cellCenter;
RayInfo hit;
//Cast a ray from 5 meters below the water surface (for now) up to the water surface.
if(mWorld->castRay(Point3F(x,y,info.waterHeight-5),Point3F(x,y,info.waterHeight), &hit, Point3F(0,1,0))) {
if(hit.point.z > info.waterHeight)
continue;
//If we get a hit, store the point as bottom hit, so we know where the bottom of the shape is at this grid cell.
Point3F bottomHit = hit.point;
F32 z = bottomHit.z;
//This code is for determining if the shape is completely underwater.
//Cast a ray down from the water surface to 5 meters below (for now)
bool isHit = mWorld->castRay(Point3F(x,y,info.waterHeight),Point3F(x,y,info.waterHeight-5), &hit, Point3F(0,-1,0));
Point3F topHit = hit.point;
//If we don't get a hit, set the top to the water height.
if(!isHit)
topHit.z = info.waterHeight;
//Calculate the water displacement for this cell
F32 top = (topHit.z < info.waterHeight) ? topHit.z : info.waterHeight;
if(mFabs(topHit.z - bottomHit.z) < 0.001)
top = info.waterHeight;
F32 disp = mFabs(top - bottomHit.z);
//Calculate the volume of water displaced for this cell
F32 volumeDisplaced = (disp * step * step);
//Calculate the water density between the object and the water.
F32 density = (info.waterDensity / density);
//Calculate the total buoyancy force
F32 buoyancy = -mWorld->getGravity().z * density * volumeDisplaced * getDataBlock()->mass;
mPhysicsRep->applyImpulse( Point3F(x,y,z), Point3F(0,0,buoyancy));
}
}
}
// Update the dampening as the container might have changed.
if ( info.waterCoverage > 0.0f )
{
F32 waterDragScale = info.waterViscosity * getDataBlock()->waterDampingScale;
F32 powCoverage = mPow( info.waterCoverage, 0.25f );
angDrag = mLerp( angDrag, angDrag * waterDragScale, powCoverage );
linDrag = mLerp( linDrag, linDrag * waterDragScale, powCoverage );
}
mPhysicsRep->setDamping( linDrag, angDrag );
// Apply physical zone forces.
Point3F cmass = mPhysicsRep->getCMassPosition();
if ( !info.appliedForce.isZero() )
mPhysicsRep->applyImpulse( cmass, info.appliedForce );
}Thanks,
Scott
#7
Anyway, I realized one reason why I'm not getting anywhere with Bullet. The buoyancy stuff doesn't seem to work at all to begin with. The physicsShape just spins out of control with the default physicsShape code. Should this be reported as a bug?
Scott
05/29/2012 (8:21 pm)
@Ross, I'm interested in seeing what you did. I know its possible to add multiple Collision objects to a mesh. I tried adding 4 ColSphere's at the corners of the buoy and a ColCone for the center. Unfortunately, by default it doesn't calculate the buoyancy stuff for each collision shape in the physics shape. I'm guessing that's what you were referring to with the code you have?Anyway, I realized one reason why I'm not getting anywhere with Bullet. The buoyancy stuff doesn't seem to work at all to begin with. The physicsShape just spins out of control with the default physicsShape code. Should this be reported as a bug?
Scott
Torque Owner Scott Przybylski
HydroSim
Am I doing something wrong? Does my collision info need to be setup in a certain way?
Thanks,
Scott