PhysX流体笔记之发射器
发射器用于直接创建流体粒子,可以实现模拟水龙头、喷嘴、流血的伤口等。
它有两种模式:
第一种,常压力(Constant pressure),发射粒子的压力是固定的,水射出一条线可以用这个模拟。
第二种,常流速(Constant flow rate),发射器在每帧保持发射固定数量的粒子。通过操做NxFluidEmitterDesc::rate,可以动态的更改流速,通过NxFluidEmitterDesc的NX_FEF_ENABLED标志,可以开启或者关闭发射器
创建发射器
需要一个NxFluidEmitterDesc,设置参数,然后用这个描述符调用NxFluid::createEmitter()方法来创建。
简单介绍一下几个NxFluidEmitterDesc中笔记重要的参数:
relPose 发射器的姿态,位置和旋转等
type 发射器类型,可以是常压力或常流速,分别对应
NX_PE_CONSTANT- PRESSURE和 NX_PE_CONSTANT_FLOW_RATE
shape 发射器的形状,当前版本中有两中类型,方形(NX_PE_RECTANGULAR)和椭
圆形(NX_PE_ELLIPSE)
particleLifetime 发射器发出的粒子的生存时间,以秒记,如果设为零,粒子将一直存活,直到碰
到drain(这个词暂时没找到合适的翻译)
maxParticles 发射器可以发射的最大的粒子数,当发射的粒子数达到最大值后,发射器停止创
建粒子,然后用已经落地的粒子重新开始发射。设为0,不限制发射的粒子数,
它会一直发射,直到到达Fluid的最大粒子数。
rate 每秒钟发射的粒子数。只在NX_PE_CONSTANT_FLOW_RATE时才有效
dimensionX,dimensionY 发射器的尺寸
示例代码
创建发射器
NxFluidEmitterDesc emitterDesc;
emitterDesc.setToDefault();
emitterDesc.dimensionX = 0.03;
emitterDesc.dimensionY = 0.03;
emitterDesc.relPose.id();
NxReal mat[] = {1,0,0,0, 0,0,1,0, 0,-1,0,0, 0,2,0,1};
emitterDesc.relPose.setColumnMajor44(mat);
emitterDesc.rate = 5.0;
emitterDesc.randomAngle = 0.1f;
emitterDesc.fluidVelocityMagnitude = 6.5f;
emitterDesc.maxParticles = MAX_PARTICLES;
emitterDesc.particleLifetime = 4.0f;
emitterDesc.type = NX_FE_CONSTANT_FLOW_RATE;
emitterDesc.shape = NX_FE_ELLIPSE;
gFluidEmitter = gFluid->createEmitter(emitterDesc);
将PhysX文档按自己的语言组织了一遍。 纯粹随笔性质。
创建粒子的描述符是NxFluidDesc,方法有三种:一是直接指定粒子的初始位置和速度,二是使用发射器创建,三是使用NxParticleData和NxFluidDesc::initialParticleData,传递初始的粒子状态来创建。
如果不希望在一开始就指定粒子的初始状态,简单的将NxFluidDesc的numParticlesPtr置为NULL即可。
为了渲染,需要指定数据输出的缓冲区,particleWriteData。要注意的是,如果你要在一开始时就指定粒子的状态,那么多个Fluid,不允许使用同一个NxParticleData数据结构。
创建时,NxParticleData的下面几个成员比较重要,PhysX SDK会读取这些数据:
bufferPos 保存粒子的位置
bufferVel 保存每个粒子的速度
bufferLife 保存每个粒子的生存时间
如果这些成员都是NULL,PhysX会使用默认值。NxParticleData的其它成员,只在渲染时被实时的更新,这里不用理会。
创建了之后,你可能还希望动态地向其中添加新的粒子,方法addParticles可以实现此功能。这个方法是有条件限制的,具体能添加多少的粒子,取决于创建时参数的设置以及当前Fluid中已存在的粒子数。PhysX默认的最大粒子数是4096。
Fluid的模拟可以有两种模式,软件和硬件模拟,默认是采用硬件加速。如果要指定使用软件模拟,在NxFluidDesc中取消NX_FF_HARDWARE标志。暂时只支持在Windows上使用软件模拟。不过软件模拟的话,效率是很低的。
示例代码:
第一种,指定初始状态的创建方法
//Set structure to pass particles, and receive them after every simulation step
NxParticleData particles;particles.numParticlesPtr = &gParticleBufferNum; particles.bufferPos = &gParticleBuffer[0].x; particles.bufferPosByteStride = sizeof(NxVec3);
//创建描述符
NxFluidDesc fluidDesc;
fluidDesc.kernelRadiusMultiplier = 2.3f; fluidDesc.restParticlesPerMeter = 10.0f; fluidDesc.stiffness = 200.0f; fluidDesc.viscosity = 22.0f; fluidDesc.restDensity = 1000.0f; fluidDesc.damping = 0.0f; fluidDesc.simulationMethod = NX_F_SPH; fluidDesc.initialParticleData = particles; fluidDesc.particlesWriteData = particles;
gFluid = gScene->createFluid(fluidDesc);
第二种,使用发射器创建
//Create fluid
NxFluidDesc fluidDesc;
fluidDesc.setToDefault();fluidDesc.simulationMethod = NX_F_SPH; fluidDesc.maxParticles = MAX_PARTICLES; fluidDesc.restParticlesPerMeter = 50; fluidDesc.stiffness = 1; fluidDesc.viscosity = 6;
gParticles = new NxVec3[fluidDesc.maxParticles]; fluidDesc.particlesWriteData.bufferPos = &gParticles[0].x; fluidDesc.particlesWriteData.bufferPosByteStride = sizeof(NxVec3); fluidDesc.particlesWriteData.numParticlesPtr = &gNumParticles; gScene->createFluid(fluidDesc);