Added Height Field Fluid Demo to Bullet. All code stored in the Demos/HeightFieldFluidDemo directory for now.
Please see HfFluidDemo.cpp for examples of how to use the height field fluid along with buoyant collision shapes. The implementation is still lacking in my ways: 1) Need to complete more collision algorithms for buoyant collision shapes 2) Support compound buoyant shapes 3) The buoyancy model isn't that great 4) Fluid volume can be lost over time
This commit is contained in:
1017
Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.cpp
Normal file
1017
Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.cpp
Normal file
File diff suppressed because it is too large
Load Diff
224
Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.h
Normal file
224
Demos/HeightFieldFluidDemo/BulletHfFluid/btHfFluid.h
Normal file
@@ -0,0 +1,224 @@
|
||||
#ifndef __HFFLUID_H
|
||||
#define __HFFLUID_H
|
||||
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
|
||||
|
||||
class btPersistentManifold;
|
||||
class btManifoldResult;
|
||||
|
||||
// FIX AABB calculation for whole btHfFluid shape
|
||||
// Fix flags and fill ratio
|
||||
// -> Figure out the constants used in flags and fill ratio code
|
||||
// Fix volume removal
|
||||
// add buoyant convex vs. convex / concave
|
||||
// add buoyant concave support (try bunny model)
|
||||
|
||||
class btHfFluid : public btCollisionObject
|
||||
{
|
||||
public:
|
||||
btHfFluid (btScalar gridCellWidth, int numNodesWidth, int numNodesLength);
|
||||
|
||||
~btHfFluid ();
|
||||
|
||||
void predictMotion(btScalar dt);
|
||||
|
||||
/* Prep does some initial setup of the height field fluid.
|
||||
* You should call this at initialization time.
|
||||
*/
|
||||
void prep ();
|
||||
|
||||
static const btHfFluid* upcast(const btCollisionObject* colObj)
|
||||
{
|
||||
if (colObj->getInternalType()==CO_HF_FLUID)
|
||||
return (const btHfFluid*)colObj;
|
||||
return 0;
|
||||
}
|
||||
static btHfFluid* upcast(btCollisionObject* colObj)
|
||||
{
|
||||
if (colObj->getInternalType()==CO_HF_FLUID)
|
||||
return (btHfFluid*)colObj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// ::btCollisionObject
|
||||
//
|
||||
|
||||
virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const
|
||||
{
|
||||
aabbMin = m_aabbMin;
|
||||
aabbMax = m_aabbMax;
|
||||
}
|
||||
|
||||
int getNumNodesWidth () const { return m_numNodesWidth; }
|
||||
int getNumNodesLength () const { return m_numNodesLength; }
|
||||
|
||||
btScalar getGridCellWidth () const { return m_gridCellWidth; }
|
||||
btScalar widthPos (int i) const;
|
||||
btScalar lengthPos (int j) const;
|
||||
|
||||
int arrayIndex (int i, int j) const;
|
||||
int arrayIndex (btScalar i, btScalar j) const;
|
||||
int arrayIndex (unsigned int i, unsigned int j) const;
|
||||
const btScalar* getHeightArray () const;
|
||||
const btScalar* getGroundArray () const;
|
||||
const btScalar* getEtaArray () const;
|
||||
const btScalar* getVelocityUArray () const;
|
||||
const btScalar* getVelocityVArray () const;
|
||||
const bool* getFlagsArray () const;
|
||||
|
||||
void setFluidHeight (int x, int y, btScalar height);
|
||||
void setFluidHeight (int index, btScalar height);
|
||||
|
||||
void addFluidHeight (int x, int y, btScalar height);
|
||||
void addDisplaced (int i, int j, btScalar r);
|
||||
|
||||
void getAabbForColumn (int x, int y, btVector3& aabbMin, btVector3& aabbMax);
|
||||
|
||||
btScalar* getHeightArray ();
|
||||
btScalar* getGroundArray ();
|
||||
btScalar* getEtaArray ();
|
||||
btScalar* getVelocityUArray ();
|
||||
btScalar* getVelocityVArray ();
|
||||
bool* getFlagsArray ();
|
||||
|
||||
void foreachGroundTriangle(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax);
|
||||
class btHfFluidColumnCallback
|
||||
{
|
||||
public:
|
||||
btHfFluidColumnCallback () {}
|
||||
|
||||
virtual ~btHfFluidColumnCallback () {}
|
||||
|
||||
virtual bool processColumn (btHfFluid* fluid, int w, int l)
|
||||
{
|
||||
return true; // keep going
|
||||
}
|
||||
};
|
||||
|
||||
void foreachFluidColumn (btHfFluidColumnCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax);
|
||||
|
||||
void foreachSurfaceTriangle (btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax);
|
||||
protected:
|
||||
int m_numNodesWidth;
|
||||
int m_numNodesLength;
|
||||
|
||||
btScalar m_gridCellWidth;
|
||||
btScalar m_gridWidth;
|
||||
btScalar m_gridLength;
|
||||
|
||||
btScalar m_gridCellWidthInv;
|
||||
|
||||
btVector3 m_aabbMin;
|
||||
btVector3 m_aabbMax;
|
||||
|
||||
void setGridDimensions (btScalar gridCellWidth,
|
||||
int numNodesWidth, int numNodesLength);
|
||||
|
||||
btScalar bilinearInterpolate (const btScalar* array, btScalar i, btScalar j);
|
||||
|
||||
btScalar advect (const btScalar* array, btScalar i, btScalar j, btScalar di, btScalar dj, btScalar dt);
|
||||
|
||||
void advectEta (btScalar dt);
|
||||
void updateHeight (btScalar dt);
|
||||
|
||||
void advectVelocityU (btScalar dt);
|
||||
void advectVelocityV (btScalar dt);
|
||||
void updateVelocity (btScalar dt);
|
||||
|
||||
void transferDisplaced (btScalar dt);
|
||||
|
||||
void setReflectBoundaryLeft ();
|
||||
void setReflectBoundaryRight ();
|
||||
void setReflectBoundaryTop ();
|
||||
void setReflectBoundaryBottom ();
|
||||
|
||||
void setAbsorbBoundaryLeft (btScalar dt);
|
||||
void setAbsorbBoundaryRight (btScalar dt);
|
||||
void setAbsorbBoundaryTop (btScalar dt);
|
||||
void setAbsorbBoundaryBottom (btScalar dt);
|
||||
|
||||
void computeFlagsAndFillRatio ();
|
||||
btScalar computeHmin (int i, int j);
|
||||
btScalar computeHmax (int i, int j);
|
||||
btScalar computeEtaMax (int i, int j);
|
||||
|
||||
void allocateArrays ();
|
||||
|
||||
void debugTests ();
|
||||
|
||||
btScalar* m_temp; // temp
|
||||
int m_heightIndex;
|
||||
btScalar* m_height[2];
|
||||
btScalar* m_ground;
|
||||
btScalar* m_eta; // height - ground
|
||||
btScalar* m_u[2];
|
||||
btScalar* m_v[2];
|
||||
int m_rIndex;
|
||||
btScalar* m_r[2];
|
||||
int m_velocityIndex;
|
||||
bool* m_flags;
|
||||
btScalar* m_fillRatio;
|
||||
|
||||
// tweakables
|
||||
btScalar m_globalVelocityU;
|
||||
btScalar m_globalVelocityV;
|
||||
btScalar m_gravity;
|
||||
btScalar m_volumeDisplacementScale;
|
||||
btScalar m_horizontalVelocityScale;
|
||||
|
||||
btScalar m_epsHeight;
|
||||
btScalar m_epsEta;
|
||||
public:
|
||||
// You can enforce a global velocity at the surface of the fluid
|
||||
// default: 0.0 and 0.0
|
||||
void setGlobaVelocity (btScalar globalVelocityU, btScalar globalVelocityV);
|
||||
void getGlobalVelocity (btScalar& globalVelocityU, btScalar& globalVelocityV) const;
|
||||
|
||||
// Control force of gravity, should match physics world
|
||||
// default: -10.0
|
||||
void setGravity (btScalar gravity);
|
||||
btScalar getGravity () const;
|
||||
|
||||
// When a body is submerged into the fluid, the displaced fluid
|
||||
// is spread to adjacent cells. You can control the percentage of this
|
||||
// by setting this value between 0.0 and 1.0
|
||||
// default: 0.5
|
||||
void setVolumeDisplacementScale (btScalar volumeDisplacementScale);
|
||||
btScalar getVolumeDisplacementScale () const;
|
||||
|
||||
// The horizontal velocity of the fluid can influence bodies submerged
|
||||
// in the fluid. You can control how much influence by setting this
|
||||
// between 0.0 and 1.0
|
||||
// default: 0.5
|
||||
void setHorizontalVelocityScale (btScalar horizontalVelocityScale);
|
||||
btScalar getHorizontalVelocityScale () const;
|
||||
};
|
||||
|
||||
class btRigidBody;
|
||||
class btIDebugDraw;
|
||||
class btHfFluidBuoyantConvexShape;
|
||||
|
||||
class btHfFluidColumnRigidBodyCallback : public btHfFluid::btHfFluidColumnCallback
|
||||
{
|
||||
protected:
|
||||
btRigidBody* m_rigidBody;
|
||||
btHfFluidBuoyantConvexShape* m_buoyantShape;
|
||||
btIDebugDraw* m_debugDraw;
|
||||
int m_numVoxels;
|
||||
btVector3 m_voxelPositionsXformed[32*32*32];
|
||||
bool m_voxelSubmerged[32*32*32];
|
||||
btVector3 m_aabbMin;
|
||||
btVector3 m_aabbMax;
|
||||
btScalar m_volume;
|
||||
btScalar m_density;
|
||||
btScalar m_floatyness;
|
||||
public:
|
||||
btHfFluidColumnRigidBodyCallback (btRigidBody* rigidBody, btIDebugDraw* debugDraw, btScalar density, btScalar floatyness);
|
||||
bool processColumn (btHfFluid* fluid, int w, int l);
|
||||
btScalar getVolume () const { return m_volume; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "LinearMath/btAabbUtil2.h"
|
||||
#include "BulletCollision/CollisionShapes/btConvexShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
|
||||
|
||||
#include "BulletHfFluid/btHfFluidBuoyantConvexShape.h"
|
||||
|
||||
btHfFluidBuoyantConvexShape::btHfFluidBuoyantConvexShape (btConvexShape* convexShape)
|
||||
{
|
||||
m_convexShape = convexShape;
|
||||
m_shapeType = HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE;
|
||||
m_radius = btScalar(0.f);
|
||||
m_totalVolume = btScalar(0.0f);
|
||||
m_floatyness = btScalar(1.5f);
|
||||
}
|
||||
|
||||
void btHfFluidBuoyantConvexShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
||||
{
|
||||
return m_convexShape->getAabb (t, aabbMin, aabbMax);
|
||||
}
|
||||
|
||||
void btHfFluidBuoyantConvexShape::setMargin(btScalar margin)
|
||||
{
|
||||
m_convexShape->setMargin (margin);
|
||||
}
|
||||
|
||||
void btHfFluidBuoyantConvexShape::setLocalScaling(const btVector3& scaling)
|
||||
{
|
||||
m_convexShape->setLocalScaling (scaling);
|
||||
}
|
||||
|
||||
const char* btHfFluidBuoyantConvexShape::getName() const
|
||||
{
|
||||
return "HF_FLUID_BUOYANT_CONVEX_SHAPE";
|
||||
}
|
||||
|
||||
const btVector3& btHfFluidBuoyantConvexShape::getLocalScaling() const
|
||||
{
|
||||
return m_convexShape->getLocalScaling();
|
||||
}
|
||||
|
||||
void btHfFluidBuoyantConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
|
||||
{
|
||||
m_convexShape->calculateLocalInertia (mass, inertia);
|
||||
}
|
||||
|
||||
btScalar btHfFluidBuoyantConvexShape::getMargin() const
|
||||
{
|
||||
return m_convexShape->getMargin();
|
||||
}
|
||||
|
||||
//must be above the machine epsilon
|
||||
#define REL_ERROR2 btScalar(1.0e-6)
|
||||
static bool intersect(btVoronoiSimplexSolver* simplexSolver,
|
||||
const btTransform& transformA,
|
||||
const btTransform& transformB,
|
||||
btConvexShape* a,
|
||||
btConvexShape* b)
|
||||
{
|
||||
|
||||
btScalar squaredDistance = SIMD_INFINITY;
|
||||
btTransform localTransA = transformA;
|
||||
btTransform localTransB = transformB;
|
||||
btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
|
||||
localTransA.getOrigin() -= positionOffset;
|
||||
localTransB.getOrigin() -= positionOffset;
|
||||
btScalar delta = btScalar(0.);
|
||||
btVector3 v = btVector3(1.0f, 0.0f, 0.0f);
|
||||
simplexSolver->reset ();
|
||||
do
|
||||
{
|
||||
btVector3 seperatingAxisInA = (-v)* transformA.getBasis();
|
||||
btVector3 seperatingAxisInB = v* transformB.getBasis();
|
||||
|
||||
btVector3 pInA = a->localGetSupportVertexNonVirtual(seperatingAxisInA);
|
||||
btVector3 qInB = b->localGetSupportVertexNonVirtual(seperatingAxisInB);
|
||||
|
||||
btVector3 pWorld = localTransA(pInA);
|
||||
btVector3 qWorld = localTransB(qInB);
|
||||
|
||||
btVector3 w = pWorld - qWorld;
|
||||
delta = v.dot(w);
|
||||
|
||||
// potential exit, they don't overlap
|
||||
if ((delta > btScalar(0.0)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (simplexSolver->inSimplex (w))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
simplexSolver->addVertex (w, pWorld, qWorld);
|
||||
|
||||
if (!simplexSolver->closest(v))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
btScalar previousSquaredDistance = squaredDistance;
|
||||
squaredDistance = v.length2();
|
||||
|
||||
if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} while (!simplexSolver->fullSimplex() && squaredDistance > REL_ERROR2 * simplexSolver->maxVertex());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void btHfFluidBuoyantConvexShape::generateShape (btScalar radius, btScalar gap)
|
||||
{
|
||||
btTransform T;
|
||||
T.setIdentity ();
|
||||
btVector3 aabbMin, aabbMax;
|
||||
getAabb (T, aabbMin, aabbMax);
|
||||
|
||||
m_radius = radius;
|
||||
m_numVoxels = 0;
|
||||
|
||||
btVoronoiSimplexSolver simplexSolver;
|
||||
btSphereShape sphereShape(radius);
|
||||
for (int i = 0; i < MAX_VOXEL_DIMENSION; i++)
|
||||
{
|
||||
for (int j = 0; j < MAX_VOXEL_DIMENSION; j++)
|
||||
{
|
||||
for (int k = 0; k < MAX_VOXEL_DIMENSION; k++)
|
||||
{
|
||||
btVector3 point;
|
||||
btTransform sT;
|
||||
sT.setIdentity ();
|
||||
|
||||
point.setX(aabbMin.getX() + (i * btScalar(2.0f) * radius) + (i * gap));
|
||||
point.setY(aabbMin.getY() + (j * btScalar(2.0f) * radius) + (j * gap));
|
||||
point.setZ(aabbMin.getZ() + (k * btScalar(2.0f) * radius) + (k * gap));
|
||||
|
||||
if (TestPointAgainstAabb2(aabbMin, aabbMax, point))
|
||||
{
|
||||
btTransform sT;
|
||||
sT.setIdentity ();
|
||||
sT.setOrigin (point);
|
||||
|
||||
if (intersect (&simplexSolver, T, sT, m_convexShape, &sphereShape))
|
||||
{
|
||||
m_voxelPositions[m_numVoxels] = point;
|
||||
m_numVoxels++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_volumePerVoxel = btScalar(4.0f)/btScalar(3.0f)*SIMD_PI*radius*radius*radius;
|
||||
m_totalVolume = m_numVoxels * m_volumePerVoxel;
|
||||
m_radius = radius;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef __BT_HFFLUID_BUOYANT_CONVEX_SHAPE_H
|
||||
#define __BT_HFFLUID_BUOYANT_CONVEX_SHAPE_H
|
||||
|
||||
#include "LinearMath/btVector3.h"
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
|
||||
#define MAX_VOXEL_DIMENSION 32
|
||||
|
||||
class btConvexShape;
|
||||
|
||||
class btHfFluidBuoyantConvexShape : public btCollisionShape
|
||||
{
|
||||
public:
|
||||
btHfFluidBuoyantConvexShape (btConvexShape* convexShape);
|
||||
|
||||
void generateShape (btScalar radius, btScalar gap);
|
||||
|
||||
btConvexShape* getConvexShape () { return m_convexShape; }
|
||||
|
||||
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
|
||||
virtual void setMargin(btScalar margin);
|
||||
virtual btScalar getMargin() const;
|
||||
virtual void setLocalScaling(const btVector3& scaling);
|
||||
virtual const btVector3& getLocalScaling() const;
|
||||
virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
|
||||
virtual const char* getName()const;
|
||||
|
||||
btScalar getVoxelRadius () const { return m_radius; }
|
||||
btScalar getTotalVolume () const { return m_totalVolume; }
|
||||
btScalar getVolumePerVoxel () const { return m_volumePerVoxel; }
|
||||
btScalar getFloatyness () const { return m_floatyness; }
|
||||
void setFloatyness (btScalar floatyness) { m_floatyness = floatyness; }
|
||||
int getNumVoxels () const { return m_numVoxels; }
|
||||
const btVector3* getVoxelPositionsArray() { return m_voxelPositions; }
|
||||
|
||||
protected:
|
||||
btScalar m_floatyness;
|
||||
btScalar m_radius;
|
||||
btScalar m_totalVolume;
|
||||
btScalar m_volumePerVoxel;
|
||||
int m_numVoxels;
|
||||
btVector3 m_voxelPositions[MAX_VOXEL_DIMENSION*MAX_VOXEL_DIMENSION*MAX_VOXEL_DIMENSION];
|
||||
btConvexShape* m_convexShape;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "btHfFluidBuoyantShapeCollisionAlgorithm.h"
|
||||
#include "btHfFluidBuoyantConvexShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btBoxShape.h"
|
||||
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||
#include "btHfFluid.h"
|
||||
|
||||
btHfFluidBuoyantShapeCollisionAlgorithm::btHfFluidBuoyantShapeCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
|
||||
: btCollisionAlgorithm(ci), m_convexConvexAlgorithm(NULL, ci, col0, col1, simplexSolver, pdSolver)
|
||||
{
|
||||
m_collisionObject0 = col0;
|
||||
m_collisionObject1 = col1;
|
||||
}
|
||||
|
||||
btHfFluidBuoyantShapeCollisionAlgorithm::~btHfFluidBuoyantShapeCollisionAlgorithm()
|
||||
{
|
||||
}
|
||||
|
||||
void btHfFluidBuoyantShapeCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
btHfFluidBuoyantConvexShape* tmpShape0 = (btHfFluidBuoyantConvexShape*)body0->getCollisionShape();
|
||||
btHfFluidBuoyantConvexShape* tmpShape1 = (btHfFluidBuoyantConvexShape*)body1->getCollisionShape();
|
||||
btConvexShape* convexShape0 = tmpShape0->getConvexShape();
|
||||
btConvexShape* convexShape1 = tmpShape1->getConvexShape();
|
||||
|
||||
body0->setCollisionShape (convexShape0);
|
||||
body1->setCollisionShape (convexShape1);
|
||||
|
||||
m_convexConvexAlgorithm.processCollision (body0, body1, dispatchInfo,resultOut);
|
||||
|
||||
body0->setCollisionShape (tmpShape0);
|
||||
body1->setCollisionShape (tmpShape1);
|
||||
}
|
||||
|
||||
btScalar btHfFluidBuoyantShapeCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
btHfFluidBuoyantConvexShape* tmpShape0 = (btHfFluidBuoyantConvexShape*)body0->getCollisionShape();
|
||||
btHfFluidBuoyantConvexShape* tmpShape1 = (btHfFluidBuoyantConvexShape*)body1->getCollisionShape();
|
||||
btConvexShape* convexShape0 = tmpShape0->getConvexShape();
|
||||
btConvexShape* convexShape1 = tmpShape1->getConvexShape();
|
||||
|
||||
body0->setCollisionShape (convexShape0);
|
||||
body1->setCollisionShape (convexShape1);
|
||||
|
||||
btScalar toi = btScalar(0.0f);
|
||||
|
||||
toi = m_convexConvexAlgorithm.calculateTimeOfImpact (body0, body1, dispatchInfo, resultOut);
|
||||
|
||||
body0->setCollisionShape (tmpShape0);
|
||||
body1->setCollisionShape (tmpShape1);
|
||||
|
||||
return toi;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef HF_FLUID_BUOYANT_SHAPE_COLLISION_ALGORITHM_H
|
||||
#define HF_FLUID_BUOYANT_SHAPE_COLLISION_ALGORITHM_H
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
|
||||
#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
|
||||
#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
|
||||
|
||||
#include "LinearMath/btVector3.h"
|
||||
class btHfFluid;
|
||||
|
||||
class btConvexConvexAlgorithm;
|
||||
class btConvexPenetrationDepthSolver;
|
||||
class btSimplexSolverInterface;
|
||||
/// btHfFluidBuoyantShapeCollisionAlgorithm provides collision detection between btHfFluidBuoyantConvexShape and btHfFluidBuoyantConvexShape
|
||||
class btHfFluidBuoyantShapeCollisionAlgorithm : public btCollisionAlgorithm
|
||||
{
|
||||
btCollisionObject* m_collisionObject0;
|
||||
btCollisionObject* m_collisionObject1;
|
||||
|
||||
btConvexConvexAlgorithm m_convexConvexAlgorithm;
|
||||
public:
|
||||
|
||||
btHfFluidBuoyantShapeCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
|
||||
|
||||
virtual ~btHfFluidBuoyantShapeCollisionAlgorithm();
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
|
||||
{
|
||||
m_convexConvexAlgorithm.getAllContactManifolds (manifoldArray);
|
||||
}
|
||||
|
||||
|
||||
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
btConvexPenetrationDepthSolver* m_pdSolver;
|
||||
btSimplexSolverInterface* m_simplexSolver;
|
||||
|
||||
CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
|
||||
{
|
||||
m_simplexSolver = simplexSolver;
|
||||
m_pdSolver = pdSolver;
|
||||
}
|
||||
|
||||
virtual ~CreateFunc() {}
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btHfFluidBuoyantShapeCollisionAlgorithm));
|
||||
if (!m_swapped)
|
||||
{
|
||||
return new(mem) btHfFluidBuoyantShapeCollisionAlgorithm(ci,body0,body1, m_simplexSolver, m_pdSolver);
|
||||
} else
|
||||
{
|
||||
return new(mem) btHfFluidBuoyantShapeCollisionAlgorithm(ci,body0,body1, m_simplexSolver, m_pdSolver);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif //HF_FLUID_BUOYANT_SHAPE_COLLISION_ALGORITHM_H
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "btHfFluidCollisionShape.h"
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef BT_HF_FLUID_COLLISION_SHAPE_H
|
||||
#define BT_HF_FLUID_COLLISION_SHAPE_H
|
||||
|
||||
#include "BulletHfFluid/btHfFluid.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btConcaveShape.h"
|
||||
|
||||
class btHfFluidCollisionShape : public btConcaveShape
|
||||
{
|
||||
public:
|
||||
btHfFluid* m_fluid;
|
||||
|
||||
btHfFluidCollisionShape(btHfFluid* backptr) : btConcaveShape ()
|
||||
{
|
||||
m_shapeType = HFFLUID_SHAPE_PROXYTYPE;
|
||||
m_fluid=backptr;
|
||||
}
|
||||
|
||||
virtual ~btHfFluidCollisionShape()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const
|
||||
{
|
||||
//not yet
|
||||
btAssert(0);
|
||||
}
|
||||
|
||||
///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
|
||||
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
|
||||
{
|
||||
/* t should be identity, but better be safe than...fast? */
|
||||
btVector3 mins;
|
||||
btVector3 maxs;
|
||||
|
||||
m_fluid->getAabb (mins, maxs);
|
||||
|
||||
const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()),
|
||||
t*btVector3(maxs.x(),mins.y(),mins.z()),
|
||||
t*btVector3(maxs.x(),maxs.y(),mins.z()),
|
||||
t*btVector3(mins.x(),maxs.y(),mins.z()),
|
||||
t*btVector3(mins.x(),mins.y(),maxs.z()),
|
||||
t*btVector3(maxs.x(),mins.y(),maxs.z()),
|
||||
t*btVector3(maxs.x(),maxs.y(),maxs.z()),
|
||||
t*btVector3(mins.x(),maxs.y(),maxs.z())};
|
||||
aabbMin=aabbMax=crns[0];
|
||||
for(int i=1;i<8;++i)
|
||||
{
|
||||
aabbMin.setMin(crns[i]);
|
||||
aabbMax.setMax(crns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setLocalScaling(const btVector3& /*scaling*/)
|
||||
{
|
||||
///na
|
||||
btAssert(0);
|
||||
}
|
||||
virtual const btVector3& getLocalScaling() const
|
||||
{
|
||||
static const btVector3 dummy(1,1,1);
|
||||
return dummy;
|
||||
}
|
||||
virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const
|
||||
{
|
||||
///not yet
|
||||
btAssert(0);
|
||||
}
|
||||
virtual const char* getName()const
|
||||
{
|
||||
return "HfFluid";
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,116 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "btHfFluidRigidCollisionAlgorithm.h"
|
||||
#include "btHfFluidBuoyantConvexShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/CollisionShapes/btSphereShape.h"
|
||||
#include "BulletCollision/CollisionShapes/btBoxShape.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
|
||||
#include "BulletDynamics/Dynamics/btRigidBody.h"
|
||||
#include "btHfFluid.h"
|
||||
|
||||
btHfFluidRigidCollisionAlgorithm::~btHfFluidRigidCollisionAlgorithm()
|
||||
{
|
||||
}
|
||||
|
||||
btHfFluidRigidCollisionAlgorithm::btHfFluidRigidCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
|
||||
: btCollisionAlgorithm(ci), m_isSwapped(isSwapped),
|
||||
m_convexTrianglecallback(ci.m_dispatcher1, col0, col1, !isSwapped) // we flip the isSwapped because we are hf fluid vs. convex and callback expects convex vs. concave
|
||||
{
|
||||
m_manifoldPtr = m_convexTrianglecallback.m_manifoldPtr;
|
||||
if (m_isSwapped)
|
||||
{
|
||||
m_hfFluid = static_cast<btHfFluid*>(col1);
|
||||
m_rigidCollisionObject = static_cast<btCollisionObject*>(col0);
|
||||
m_manifoldPtr->setBodies(m_hfFluid,m_rigidCollisionObject);
|
||||
} else {
|
||||
m_hfFluid = static_cast<btHfFluid*>(col0);
|
||||
m_rigidCollisionObject = static_cast<btCollisionObject*>(col1);
|
||||
m_manifoldPtr->setBodies(m_rigidCollisionObject,m_hfFluid);
|
||||
}
|
||||
}
|
||||
|
||||
void btHfFluidRigidCollisionAlgorithm::processGround (const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
btScalar triangleMargin = m_rigidCollisionObject->getCollisionShape()->getMargin();
|
||||
resultOut->setPersistentManifold(m_manifoldPtr);
|
||||
// to perform the convex shape vs. ground terrain:
|
||||
// we pull the convex shape out of the buoyant shape and replace it temporarily
|
||||
btHfFluidBuoyantConvexShape* tmpShape = (btHfFluidBuoyantConvexShape*)m_rigidCollisionObject->getCollisionShape();
|
||||
btConvexShape* convexShape = ((btHfFluidBuoyantConvexShape*)tmpShape)->getConvexShape();
|
||||
m_rigidCollisionObject->setCollisionShape (convexShape);
|
||||
m_convexTrianglecallback.setTimeStepAndCounters (triangleMargin, dispatchInfo, resultOut);
|
||||
m_hfFluid->foreachGroundTriangle (&m_convexTrianglecallback, m_convexTrianglecallback.getAabbMin(),m_convexTrianglecallback.getAabbMax());
|
||||
resultOut->refreshContactPoints();
|
||||
// restore the buoyant shape
|
||||
m_rigidCollisionObject->setCollisionShape (tmpShape);
|
||||
}
|
||||
|
||||
btScalar btHfFluidRigidCollisionAlgorithm::processFluid (const btDispatcherInfo& dispatchInfo, btScalar density, btScalar floatyness)
|
||||
{
|
||||
btRigidBody* rb = btRigidBody::upcast(m_rigidCollisionObject);
|
||||
btHfFluidColumnRigidBodyCallback columnCallback (rb, dispatchInfo.m_debugDraw, density, floatyness);
|
||||
m_hfFluid->foreachFluidColumn (&columnCallback, m_convexTrianglecallback.getAabbMin(), m_convexTrianglecallback.getAabbMax());
|
||||
return columnCallback.getVolume ();
|
||||
}
|
||||
|
||||
void btHfFluidRigidCollisionAlgorithm::applyFluidFriction (btScalar mu, btScalar submerged_percentage)
|
||||
{
|
||||
btRigidBody* rb = btRigidBody::upcast(m_rigidCollisionObject);
|
||||
btScalar dt = btScalar(1.0f/60.0f);
|
||||
|
||||
//#define OLD_WAY
|
||||
#ifdef OLD_WAY
|
||||
btScalar radius = btScalar(0.0f);
|
||||
{
|
||||
btVector3 aabbMin, aabbMax;
|
||||
btTransform T;
|
||||
T.setIdentity();
|
||||
rb->getCollisionShape()->getAabb (T, aabbMin, aabbMax);
|
||||
radius = (aabbMax-aabbMin).length()*btScalar(0.5);
|
||||
}
|
||||
btScalar viscosity = btScalar(0.05);
|
||||
btVector3 force = btScalar(6.0f) * SIMD_PI * viscosity * radius * -rb->getLinearVelocity();
|
||||
|
||||
btVector3 impulse = force * dt;
|
||||
rb->applyCentralImpulse (impulse);
|
||||
|
||||
if (true)
|
||||
{
|
||||
btVector3 av = rb->getAngularVelocity();
|
||||
av *= btScalar(0.99);
|
||||
rb->setAngularVelocity (av);
|
||||
}
|
||||
#else
|
||||
btScalar scaled_mu = mu * submerged_percentage * btScalar(0.4f);
|
||||
rb->applyCentralImpulse (dt * scaled_mu * -rb->getLinearVelocity());
|
||||
rb->applyTorqueImpulse (dt * scaled_mu * -rb->getAngularVelocity());
|
||||
#endif
|
||||
}
|
||||
|
||||
void btHfFluidRigidCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
processGround (dispatchInfo, resultOut);
|
||||
btHfFluidBuoyantConvexShape* buoyantShape = (btHfFluidBuoyantConvexShape*)m_rigidCollisionObject->getCollisionShape();
|
||||
btRigidBody* rb = btRigidBody::upcast(m_rigidCollisionObject);
|
||||
if (rb)
|
||||
{
|
||||
btScalar mass = btScalar(1.0f) / rb->getInvMass ();
|
||||
btScalar volume = buoyantShape->getTotalVolume ();
|
||||
btScalar density = mass / volume;
|
||||
btScalar floatyness = buoyantShape->getFloatyness ();
|
||||
btScalar submerged_volume = processFluid (dispatchInfo, density, floatyness);
|
||||
if (submerged_volume > btScalar(0.0))
|
||||
{
|
||||
btScalar submerged_percentage = submerged_volume/buoyantShape->getTotalVolume();
|
||||
//printf("%f\n", submerged_percentage);
|
||||
btScalar mu = btScalar(6.0f);
|
||||
applyFluidFriction (mu, submerged_percentage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
btScalar btHfFluidRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
|
||||
{
|
||||
return btScalar(1.0);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef HF_FLUID_RIGID_COLLISION_ALGORITHM_H
|
||||
#define HF_FLUID_RIGID_COLLISION_ALGORITHM_H
|
||||
|
||||
#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
|
||||
#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
|
||||
#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
|
||||
#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
|
||||
#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
|
||||
#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
|
||||
|
||||
#include "LinearMath/btVector3.h"
|
||||
class btHfFluid;
|
||||
|
||||
/// btHfFluidRigidCollisionAlgorithm provides collision detection between btHfFluid and btRigidBody
|
||||
class btHfFluidRigidCollisionAlgorithm : public btCollisionAlgorithm
|
||||
{
|
||||
btPersistentManifold* m_manifoldPtr;
|
||||
|
||||
btHfFluid* m_hfFluid;
|
||||
btCollisionObject* m_rigidCollisionObject;
|
||||
|
||||
///for rigid versus fluid (instead of fluid versus rigid), we use this swapped boolean
|
||||
bool m_isSwapped;
|
||||
|
||||
btConvexTriangleCallback m_convexTrianglecallback;
|
||||
|
||||
void processGround (const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
void applyFluidFriction (btScalar mu, btScalar submerged_percentage);
|
||||
btScalar processFluid (const btDispatcherInfo& dispatchInfo, btScalar density, btScalar floatyness);
|
||||
public:
|
||||
|
||||
btHfFluidRigidCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
|
||||
|
||||
virtual ~btHfFluidRigidCollisionAlgorithm();
|
||||
|
||||
virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
|
||||
|
||||
virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
|
||||
{
|
||||
manifoldArray.push_back (m_manifoldPtr);
|
||||
}
|
||||
|
||||
|
||||
struct CreateFunc :public btCollisionAlgorithmCreateFunc
|
||||
{
|
||||
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
|
||||
{
|
||||
void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btHfFluidRigidCollisionAlgorithm));
|
||||
if (!m_swapped)
|
||||
{
|
||||
return new(mem) btHfFluidRigidCollisionAlgorithm(ci,body0,body1,false);
|
||||
} else
|
||||
{
|
||||
return new(mem) btHfFluidRigidCollisionAlgorithm(ci,body0,body1,true);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif //HF_FLUID_RIGID_COLLISION_ALGORITHM_H
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "btHfFluidRigidCollisionConfiguration.h"
|
||||
#include "btHfFluidRigidCollisionAlgorithm.h"
|
||||
#include "btHfFluidBuoyantShapeCollisionAlgorithm.h"
|
||||
#include "LinearMath/btPoolAllocator.h"
|
||||
|
||||
btHfFluidRigidCollisionConfiguration::btHfFluidRigidCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
|
||||
:btDefaultCollisionConfiguration(constructionInfo)
|
||||
{
|
||||
void* mem;
|
||||
|
||||
mem = btAlignedAlloc(sizeof(btHfFluidRigidCollisionAlgorithm::CreateFunc),16);
|
||||
m_hfFluidRigidConvexCreateFunc = new(mem) btHfFluidRigidCollisionAlgorithm::CreateFunc;
|
||||
|
||||
mem = btAlignedAlloc(sizeof(btHfFluidRigidCollisionAlgorithm::CreateFunc),16);
|
||||
m_swappedHfFluidRigidConvexCreateFunc = new(mem) btHfFluidRigidCollisionAlgorithm::CreateFunc;
|
||||
m_swappedHfFluidRigidConvexCreateFunc->m_swapped = true;
|
||||
|
||||
mem = btAlignedAlloc(sizeof(btHfFluidBuoyantShapeCollisionAlgorithm::CreateFunc),16);
|
||||
m_hfFluidBuoyantShapeCollisionCreateFunc = new(mem) btHfFluidBuoyantShapeCollisionAlgorithm::CreateFunc(m_simplexSolver, m_pdSolver);
|
||||
|
||||
if (m_ownsCollisionAlgorithmPool && m_collisionAlgorithmPool)
|
||||
{
|
||||
int curElemSize = m_collisionAlgorithmPool->getElementSize();
|
||||
///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
|
||||
|
||||
int maxSize0 = sizeof(btHfFluidRigidCollisionAlgorithm);
|
||||
int maxSize1 = 0;
|
||||
int maxSize2 = 0;
|
||||
|
||||
int collisionAlgorithmMaxElementSize = btMax(maxSize0,maxSize1);
|
||||
collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2);
|
||||
|
||||
if (collisionAlgorithmMaxElementSize > curElemSize)
|
||||
{
|
||||
m_collisionAlgorithmPool->~btPoolAllocator();
|
||||
btAlignedFree(m_collisionAlgorithmPool);
|
||||
void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
|
||||
m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
btHfFluidRigidCollisionConfiguration::~btHfFluidRigidCollisionConfiguration()
|
||||
{
|
||||
m_hfFluidRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
|
||||
m_swappedHfFluidRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
|
||||
btAlignedFree(m_hfFluidRigidConvexCreateFunc);
|
||||
btAlignedFree(m_swappedHfFluidRigidConvexCreateFunc);
|
||||
}
|
||||
|
||||
btCollisionAlgorithmCreateFunc* btHfFluidRigidCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
|
||||
{
|
||||
if ((proxyType0 == HFFLUID_SHAPE_PROXYTYPE) && (proxyType1 == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE))
|
||||
{
|
||||
return m_hfFluidRigidConvexCreateFunc;
|
||||
}
|
||||
|
||||
if ((proxyType0 == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE) && (proxyType1 == HFFLUID_SHAPE_PROXYTYPE))
|
||||
{
|
||||
return m_swappedHfFluidRigidConvexCreateFunc;
|
||||
}
|
||||
|
||||
if ((proxyType0 == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE) && (proxyType1 == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE))
|
||||
{
|
||||
return m_hfFluidBuoyantShapeCollisionCreateFunc;
|
||||
}
|
||||
|
||||
///fallback to the regular rigid collision shape
|
||||
return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef BT_HFFLUID_RIGID_COLLISION_CONFIGURATION
|
||||
#define BT_HFFLUID_RIGID_COLLISION_CONFIGURATION
|
||||
|
||||
#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
|
||||
|
||||
class btVoronoiSimplexSolver;
|
||||
class btGjkEpaPenetrationDepthSolver;
|
||||
|
||||
|
||||
///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration
|
||||
class btHfFluidRigidCollisionConfiguration : public btDefaultCollisionConfiguration
|
||||
{
|
||||
//default CreationFunctions, filling the m_doubleDispatch table
|
||||
btCollisionAlgorithmCreateFunc* m_hfFluidRigidConvexCreateFunc;
|
||||
btCollisionAlgorithmCreateFunc* m_swappedHfFluidRigidConvexCreateFunc;
|
||||
btCollisionAlgorithmCreateFunc* m_hfFluidBuoyantShapeCollisionCreateFunc;
|
||||
|
||||
public:
|
||||
|
||||
btHfFluidRigidCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
|
||||
|
||||
virtual ~btHfFluidRigidCollisionConfiguration();
|
||||
|
||||
///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
|
||||
virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_HFFLUID_RIGID_COLLISION_CONFIGURATION
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "LinearMath/btQuickprof.h"
|
||||
#include "LinearMath/btIDebugDraw.h"
|
||||
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
|
||||
|
||||
// height field fluid
|
||||
#include "btHfFluid.h"
|
||||
#include "btHfFluidBuoyantConvexShape.h"
|
||||
#include "btHfFluidRigidDynamicsWorld.h"
|
||||
|
||||
|
||||
|
||||
|
||||
btHfFluidRigidDynamicsWorld::btHfFluidRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
|
||||
:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
|
||||
{
|
||||
m_drawMode = DRAWMODE_NORMAL;
|
||||
m_bodyDrawMode = BODY_DRAWMODE_NORMAL;
|
||||
}
|
||||
|
||||
btHfFluidRigidDynamicsWorld::~btHfFluidRigidDynamicsWorld()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
|
||||
{
|
||||
btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep);
|
||||
|
||||
for ( int i=0;i<m_hfFluids.size();++i)
|
||||
{
|
||||
btHfFluid* phff = m_hfFluids[i];
|
||||
|
||||
// XXX: phff->predictMotion(timeStep);
|
||||
}
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
|
||||
{
|
||||
btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep );
|
||||
|
||||
updateFluids (timeStep);
|
||||
|
||||
solveFluidConstraints (timeStep);
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::updateFluids(btScalar timeStep)
|
||||
{
|
||||
BT_PROFILE("updateFluids");
|
||||
|
||||
for ( int i=0;i<m_hfFluids.size();i++)
|
||||
{
|
||||
btHfFluid* phff=(btHfFluid*)m_hfFluids[i];
|
||||
phff->predictMotion (timeStep);
|
||||
}
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::solveFluidConstraints(btScalar timeStep)
|
||||
{
|
||||
BT_PROFILE("solve Fluid Contacts");
|
||||
|
||||
#if 0
|
||||
if(m_hfFluids.size())
|
||||
{
|
||||
btHfFluid::solveClusters(m_hfFluids);
|
||||
}
|
||||
|
||||
for(int i=0;i<m_hfFluids.size();++i)
|
||||
{
|
||||
btHfFluid* psb=(btHfFluid*)m_hfFluids[i];
|
||||
psb->solveConstraints();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::addHfFluid(btHfFluid* body)
|
||||
{
|
||||
m_hfFluids.push_back(body);
|
||||
|
||||
btCollisionWorld::addCollisionObject(body,
|
||||
btBroadphaseProxy::DefaultFilter,
|
||||
btBroadphaseProxy::AllFilter);
|
||||
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::removeHfFluid(btHfFluid* body)
|
||||
{
|
||||
m_hfFluids.remove(body);
|
||||
|
||||
btCollisionWorld::removeCollisionObject(body);
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::drawHfFluidGround (btIDebugDraw* debugDraw, btHfFluid* fluid)
|
||||
{
|
||||
const btScalar* ground = fluid->getGroundArray ();
|
||||
btVector3 com = fluid->getWorldTransform().getOrigin();
|
||||
btVector3 color = btVector3(btScalar(0.13f), btScalar(0.13f), btScalar(0.0));
|
||||
for (int i = 1; i < fluid->getNumNodesWidth()-1; i++)
|
||||
{
|
||||
for (int j = 1; j < fluid->getNumNodesLength()-1; j++)
|
||||
{
|
||||
int sw = fluid->arrayIndex (i, j);
|
||||
int se = fluid->arrayIndex (i+1, j);
|
||||
int nw = fluid->arrayIndex (i, j+1);
|
||||
int ne = fluid->arrayIndex (i+1, j+1);
|
||||
btVector3 swV = btVector3 (fluid->widthPos (i), ground[sw], fluid->lengthPos (j));
|
||||
btVector3 seV = btVector3 (fluid->widthPos (i+1), ground[se], fluid->lengthPos (j));
|
||||
btVector3 nwV = btVector3 (fluid->widthPos (i), ground[nw], fluid->lengthPos (j+1));
|
||||
btVector3 neV = btVector3 (fluid->widthPos (i+1), ground[ne], fluid->lengthPos (j+1));
|
||||
debugDraw->drawTriangle (swV+com, seV+com, nwV+com, color, btScalar(1.0f));
|
||||
debugDraw->drawTriangle (seV+com, neV+com, nwV+com, color, btScalar(1.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::drawHfFluidVelocity (btIDebugDraw* debugDraw, btHfFluid* fluid)
|
||||
{
|
||||
btScalar alpha(0.7f);
|
||||
const btScalar* height = fluid->getHeightArray ();
|
||||
btVector3 com = fluid->getWorldTransform().getOrigin();
|
||||
btVector3 red = btVector3(btScalar(1.0f), btScalar(0.0f), btScalar(0.0));
|
||||
btVector3 green = btVector3(btScalar(0.0f), btScalar(1.0f), btScalar(0.0));
|
||||
const bool* flags = fluid->getFlagsArray ();
|
||||
for (int i = 1; i < fluid->getNumNodesWidth()-1; i++)
|
||||
{
|
||||
for (int j = 1; j < fluid->getNumNodesLength()-1; j++)
|
||||
{
|
||||
int index = fluid->arrayIndex (i, j);
|
||||
if (!flags[index])
|
||||
continue;
|
||||
btVector3 from = btVector3 (fluid->widthPos (i), height[index]+btScalar(0.1f), fluid->lengthPos (j));
|
||||
btVector3 velocity;
|
||||
velocity.setX (fluid->getVelocityUArray()[index]);
|
||||
velocity.setY (btScalar(0.0f));
|
||||
velocity.setZ (fluid->getVelocityVArray()[index]);
|
||||
velocity.normalize();
|
||||
btVector3 to = from + velocity;
|
||||
|
||||
debugDraw->drawLine (from+com, to+com, red, green);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::drawHfFluidBuoyantConvexShape (btIDebugDraw* debugDrawer, btCollisionObject* object, btHfFluidBuoyantConvexShape* buoyantShape, int voxelDraw)
|
||||
{
|
||||
if (voxelDraw)
|
||||
{
|
||||
btTransform xform = object->getWorldTransform();
|
||||
for (int i = 0; i < buoyantShape->getNumVoxels(); i++)
|
||||
{
|
||||
btVector3 p = buoyantShape->getVoxelPositionsArray()[i];
|
||||
p = xform.getBasis() * p;
|
||||
p += xform.getOrigin();
|
||||
debugDrawer->drawSphere (p, buoyantShape->getVoxelRadius(), btVector3(1.0, 0.0, 0.0));
|
||||
}
|
||||
} else {
|
||||
btVector3 color(btScalar(255.),btScalar(255.),btScalar(255.));
|
||||
switch(object->getActivationState())
|
||||
{
|
||||
case ACTIVE_TAG:
|
||||
color = btVector3(btScalar(255.),btScalar(255.),btScalar(255.)); break;
|
||||
case ISLAND_SLEEPING:
|
||||
color = btVector3(btScalar(0.),btScalar(255.),btScalar(0.));break;
|
||||
case WANTS_DEACTIVATION:
|
||||
color = btVector3(btScalar(0.),btScalar(255.),btScalar(255.));break;
|
||||
case DISABLE_DEACTIVATION:
|
||||
color = btVector3(btScalar(255.),btScalar(0.),btScalar(0.));break;
|
||||
case DISABLE_SIMULATION:
|
||||
color = btVector3(btScalar(255.),btScalar(255.),btScalar(0.));break;
|
||||
default:
|
||||
{
|
||||
color = btVector3(btScalar(255.),btScalar(0.),btScalar(0.));
|
||||
}
|
||||
};
|
||||
|
||||
btConvexShape* convexShape = ((btHfFluidBuoyantConvexShape*)object->getCollisionShape())->getConvexShape();
|
||||
debugDrawObject(object->getWorldTransform(),(btCollisionShape*)convexShape,color);
|
||||
}
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::drawHfFluidNormal (btIDebugDraw* debugDraw, btHfFluid* fluid)
|
||||
{
|
||||
int colIndex = 0;
|
||||
btVector3 col[2];
|
||||
col[0] = btVector3(btScalar(0.0f), btScalar(0.0f), btScalar(1.0));
|
||||
col[1] = btVector3(btScalar(0.0f), btScalar(0.5f), btScalar(0.5));
|
||||
btScalar alpha(0.7f);
|
||||
const btScalar* height = fluid->getHeightArray ();
|
||||
const btScalar* eta = fluid->getEtaArray ();
|
||||
const btScalar* ground = fluid->getGroundArray ();
|
||||
btVector3 com = fluid->getWorldTransform().getOrigin();
|
||||
const bool* flags = fluid->getFlagsArray ();
|
||||
for (int i = 0; i < fluid->getNumNodesWidth()-1; i++)
|
||||
{
|
||||
for (int j = 0; j < fluid->getNumNodesLength()-1; j++)
|
||||
{
|
||||
int sw = fluid->arrayIndex (i, j);
|
||||
int se = fluid->arrayIndex (i+1, j);
|
||||
int nw = fluid->arrayIndex (i, j+1);
|
||||
int ne = fluid->arrayIndex (i+1, j+1);
|
||||
|
||||
btScalar h = eta[sw];
|
||||
btScalar g = ground[sw];
|
||||
|
||||
if (h < btScalar(0.05f))
|
||||
continue;
|
||||
|
||||
if (h <= btScalar(0.01f))
|
||||
continue;
|
||||
|
||||
btVector3 boxMin = btVector3(fluid->widthPos (i), g, fluid->lengthPos(j));
|
||||
btVector3 boxMax = btVector3(fluid->widthPos(i+1), g+h, fluid->lengthPos(j+1));
|
||||
boxMin += com;
|
||||
boxMax += com;
|
||||
|
||||
debugDraw->drawBox (boxMin, boxMax, btVector3(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f)), btScalar(1.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void btHfFluidRigidDynamicsWorld::debugDrawWorld()
|
||||
{
|
||||
if (getDebugDrawer())
|
||||
{
|
||||
int i;
|
||||
for ( i=0;i<this->m_hfFluids.size();i++)
|
||||
{
|
||||
btHfFluid* phh=(btHfFluid*)this->m_hfFluids[i];
|
||||
switch (m_drawMode)
|
||||
{
|
||||
case DRAWMODE_NORMAL:
|
||||
drawHfFluidGround (m_debugDrawer, phh);
|
||||
//drawHfFluidNormal (m_debugDrawer, phh);
|
||||
break;
|
||||
case DRAWMODE_VELOCITY:
|
||||
drawHfFluidGround (m_debugDrawer, phh);
|
||||
//drawHfFluidNormal (m_debugDrawer, phh);
|
||||
drawHfFluidVelocity (m_debugDrawer, phh);
|
||||
break;
|
||||
default:
|
||||
btAssert (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < this->m_collisionObjects.size(); i++)
|
||||
{
|
||||
btCollisionShape* shape = m_collisionObjects[i]->getCollisionShape();
|
||||
if (shape->getShapeType() == HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE)
|
||||
{
|
||||
btHfFluidBuoyantConvexShape* buoyantShape = (btHfFluidBuoyantConvexShape*)shape;
|
||||
drawHfFluidBuoyantConvexShape (m_debugDrawer, m_collisionObjects[i], buoyantShape, m_bodyDrawMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
btDiscreteDynamicsWorld::debugDrawWorld();
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it freely,
|
||||
subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
|
||||
|
||||
#ifndef BT_HFFLUID_RIGID_DYNAMICS_WORLD_H
|
||||
#define BT_HFFLUID_RIGID_DYNAMICS_WORLD_H
|
||||
|
||||
class btHfFluid;
|
||||
typedef btAlignedObjectArray<btHfFluid*> btHfFluidArray;
|
||||
|
||||
#define DRAWMODE_NORMAL 0
|
||||
#define DRAWMODE_VELOCITY 1
|
||||
#define DRAWMODE_MAX 2
|
||||
|
||||
#define BODY_DRAWMODE_NORMAL 0
|
||||
#define BODY_DRAWMODE_VOXEL 1
|
||||
#define BODY_DRAWMODE_MAX 2
|
||||
|
||||
class btHfFluidBuoyantConvexShape;
|
||||
|
||||
class btHfFluidRigidDynamicsWorld : public btDiscreteDynamicsWorld
|
||||
{
|
||||
|
||||
btHfFluidArray m_hfFluids;
|
||||
int m_drawMode;
|
||||
int m_bodyDrawMode;
|
||||
protected:
|
||||
|
||||
virtual void predictUnconstraintMotion(btScalar timeStep);
|
||||
|
||||
virtual void internalSingleStepSimulation( btScalar timeStep);
|
||||
|
||||
void updateFluids(btScalar timeStep);
|
||||
|
||||
void solveFluidConstraints(btScalar timeStep);
|
||||
|
||||
virtual void debugDrawWorld();
|
||||
|
||||
void drawHfFluidGround (btIDebugDraw* debugDraw, btHfFluid* fluid);
|
||||
void drawHfFluidVelocity (btIDebugDraw* debugDraw, btHfFluid* fluid);
|
||||
void drawHfFluidBuoyantConvexShape (btIDebugDraw* debugDrawer, btCollisionObject* object, btHfFluidBuoyantConvexShape* buoyantShape, int voxelDraw);
|
||||
void drawHfFluidNormal (btIDebugDraw* debugDraw, btHfFluid* fluid);
|
||||
public:
|
||||
|
||||
btHfFluidRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
|
||||
|
||||
virtual ~btHfFluidRigidDynamicsWorld();
|
||||
|
||||
|
||||
void addHfFluid(btHfFluid* fluid);
|
||||
|
||||
void removeHfFluid(btHfFluid* fluid);
|
||||
|
||||
void setDrawMode (int drawMode)
|
||||
{
|
||||
m_drawMode = drawMode;
|
||||
}
|
||||
|
||||
void setBodyDrawMode (int bodyDrawMode)
|
||||
{
|
||||
m_bodyDrawMode = bodyDrawMode;
|
||||
}
|
||||
|
||||
btHfFluidArray& getHfFluidArray()
|
||||
{
|
||||
return m_hfFluids;
|
||||
}
|
||||
|
||||
const btHfFluidArray& getHfFluidArray() const
|
||||
{
|
||||
return m_hfFluids;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //BT_HFFLUID_RIGID_DYNAMICS_WORLD_H
|
||||
Reference in New Issue
Block a user