Erroneous buoyancy in btHfFluid

Post Reply
IvarHeyguen
Posts: 2
Joined: Sat Jun 25, 2011 9:11 am
Location: Trondheim, Norway
Contact:

Erroneous buoyancy in btHfFluid

Post by IvarHeyguen »

I've been experimenting a little with John McCutchan's height field fluid demo and discovered very strange behaviour.

If I drop a wedge-shaped convex body into the fluid, it starts oscillating around it’s vertex instead of turning flat. Moreover, this state of equilibrium is stable, i.e. if I disturb it with another rigid body, it will return to this anomalous position.

I’ve uploaded a video of this problem to youtube: http://youtu.be/jOC1CIkiPsM

I’d be glad to trace the problem and fix it, but I need some help to understand the current algorithm. Does anyone know if there is some documentation/publications/description of the height field fluid implementation in Bullet (except for http://www.bulletphysics.org/Bullet/php ... f=9&t=1528 of course). It would be nice to have a high level overview of this feature.

As far as I understand it now, the essence of the current approach is encapsulated in the processColumn function. The submerged volume calculation is based on voxels. For each submerged voxel, we calculate the mass of displaced water as mass_w = voxelVolume * density * floatyness, where voxelVolume=(4/3)*pi*r^3 (just volume of a sphere). Then we apply upward impulse, equal to mass_w – gravity at the relative position of a voxel. Some questions here: 1. Why are we using voxels for the displaced water mass calculation? Isn’t it more precise to just integrate the volume of the fluid itself? 2. Why are we subtracting the gravity from the mass of the displaced water. Shouldn’t we subtract the mass of the body, enclosed in the water column?

Finally, here is the source code I used in the HfFluidDemo.cpp to catch the bug:

Code: Select all

void Wedge_Floatyness (HfFluidDemo* fluidDemo)
{
	btHfFluid* fluid = NULL;

	fluid = new btHfFluid (btScalar(0.25), 100, 100);
	btTransform xform;
	xform.setIdentity ();
	xform.getOrigin() = btVector3(btScalar(-10.0), btScalar(-5.0), btScalar(-10.0));
	fluid->setWorldTransform (xform);
	fluid->setHorizontalVelocityScale (btScalar(0.0f));
	fluid->setVolumeDisplacementScale (btScalar(0.0f));
	fluidDemo->getHfFluidDynamicsWorld()->addHfFluid (fluid);

	for (int i = 0; i < fluid->getNumNodesLength()*fluid->getNumNodesWidth(); i++)
	{
		fluid->setFluidHeight(i, btScalar(5.0f));
	}

	fluid->prep ();

	btScalar floatyness = btScalar(1.0f);
	btScalar start_x = btScalar(-5.0f);
	btScalar start_z = btScalar(-2.0f);

	btVector3 points1[6]={btVector3(0,0,0), btVector3(5,0,0),btVector3(0,5,0),btVector3(0,0,1),btVector3(5,0,1),btVector3(0,5,1)};
	btConvexShape* hullA = new btConvexHullShape(&points1[0].getX(),6);	
	btHfFluidBuoyantConvexShape* buoyantConvex = new btHfFluidBuoyantConvexShape(hullA);
	buoyantConvex->generateShape(btScalar(0.25f), btScalar(0.25f));
	buoyantConvex->setFloatyness(1.0f);
	fluidDemo->m_collisionShapes.push_back(buoyantConvex);
	btTransform startConvexTransform;
	startConvexTransform.setIdentity();
	btScalar massConvex(1.0f);
	btVector3 localConvexInertia(0,0,0);
	buoyantConvex->calculateLocalInertia(massConvex,localConvexInertia);
	btVector3 originConvex = btVector3(start_x, 3.5f, start_z);
	startConvexTransform.setOrigin(originConvex);
	btDefaultMotionState* myMotionConvexState = new btDefaultMotionState(startConvexTransform);
	btRigidBody::btRigidBodyConstructionInfo rbConvexInfo(massConvex,myMotionConvexState,buoyantConvex,localConvexInertia);
	btRigidBody* bodyConvex = new btRigidBody(rbConvexInfo);
	fluidDemo->getHfFluidDynamicsWorld()->addRigidBody(bodyConvex);
}
Post Reply