流体模拟(二)
SPH算法实现2:
在前面一节我们完成了粒子缓存类,网格类和邻接表类。我们现在可以正式的整合在我们的流体系统类中了。
流体系统类
class FluidSystem{
public:
FluidSystem();
void init(unsigned short maxPointCounts,
const glm::vec3& wallBox_min,const glm::vec3& wallBox_max,
const glm::vec3& initFluidBox_min,const glm::vec3& initFluidBox_max,
const glm::vec3& gravity){
_init(maxPointCounts, fBox3(wallBox_min,wallBox_max),
fBox3(initFluidBox_min,initFluidBox_max), gravity);
}
//获取点的尺寸(字节)
unsigned int getPointStride()const {return sizeof(Point);}
//获取点的数量
unsigned int getPointCounts()const{return m_pointBuffer.size();}
//获取流体点缓存
const Point* getPointBuf()const{return m_pointBuffer.get(0);}
//逻辑桢
void tick();
~FluidSystem();
private:
//初始化系统
void _init(unsigned short maxPointCounts,const fBox3& wallBox,
const fBox3& initFluidBox, const glm::vec3& gravity);
//计算密度,压力以及相邻关系
void _computerPressure();
//计算加速度
void _computerForce();
//移动粒子
void _advance();
//创建初始液体块
void _addFluidVolume(const fBox3& fluidBox,float spacing);
//数据成员
PointBuffer m_pointBuffer;
GridContainer m_gridContainer;
NeighborTable m_neighborTable;
//点位置缓存数据(x,y,z)
std::vector<float>posData;
//SPH光滑核
float m_kernelPoly6;
float m_kernelSpiky;
float m_kernelViscosity;
//其他参数
float m_pointDistance;//半径
float m_unitScale;//尺寸单位
float m_viscosity;//粘性
float m_restDensity;//静态密度
float m_pointMass;//质量
float m_smoothRadius;//光滑核半径
float m_gasConstantK;//气体常量k
float m_boundaryStiffness;//边界刚性
float m_boundaryDampening;//边界阻尼
float m_speedLimiting;//速度限制
glm::vec3 m_gravityDir;//重力矢量
int m_rexSize[3];//网格尺寸
fBox3 m_sphWallBox;
};
目前流体系统还是比较简单的,设定我们SPH需要的各种属性,并建立我们上节创建的三种类成员。算法主要在初始化函数_init,密度和压力计算函数_computerPressure,加速度计算函数_computerForce和移动粒子函数_advance。我们的动画在tick帧函数中进行。最后我们计算后的粒子位置在每帧计算后更新posData缓存数据。
然后是我们的实现代码:
FluidSystem::FluidSystem(){
m_unitScale = 0.004f; // 尺寸单位
m_viscosity = 1.0f; // 粘度
m_restDensity = 1000.f; // 密度
m_pointMass = 0.0006f; // 粒子质量
m_gasConstantK = 1.0f; // 理想气体方程常量
m_smoothRadius = 0.01f;