#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