348 lines
9.0 KiB
C++
348 lines
9.0 KiB
C++
#include <StdAfx.h>
|
|
#include "vtPhysXAll.h"
|
|
|
|
#include "pFluid.h"
|
|
#include "pFluidEmitter.h"
|
|
#include "CK3dPointCloud.h"
|
|
|
|
|
|
#ifdef HAS_FLUIDS
|
|
|
|
pFluidEmitter*pFluid::createEmitter(const pFluidEmitterDesc& desc)
|
|
{
|
|
|
|
NxFluidEmitterDesc eDesc ;
|
|
eDesc.setToDefault();
|
|
|
|
pFactory::Instance()->copyToEmitterDesc(eDesc,desc);
|
|
|
|
int valid = eDesc.isValid();
|
|
if (!valid)
|
|
{
|
|
xLogger::xLog(XL_START,ELOGERROR,E_LI_MANAGER,"Emitter Description not Valid !");
|
|
return NULL;
|
|
}
|
|
|
|
CK3dEntity*entityReference = (CK3dEntity*)ctx()->GetObject(desc.entityReference);
|
|
if (!entityReference)
|
|
{
|
|
xLogger::xLog(XL_START,ELOGERROR,E_LI_MANAGER,"You must set a reference object ID in .referenceEntity");
|
|
return NULL;
|
|
}
|
|
|
|
|
|
eDesc.relPose.M.id();
|
|
eDesc.relPose.M.rotX(-NxHalfPiF32);
|
|
eDesc.relPose.t = NxVec3(0,1.1f,0);
|
|
|
|
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
|
|
|
|
NxFluidEmitter *emitter = getFluid()->createEmitter(eDesc);
|
|
|
|
if (!emitter)
|
|
return NULL;
|
|
|
|
pFluidEmitter * result = new pFluidEmitter();
|
|
result->setEmitter(emitter);
|
|
result->setFluid(this);
|
|
result->setEntityReference(entityReference->GetID());
|
|
VxVector pos;
|
|
if (desc.frameShape)
|
|
{
|
|
desc.frameShape->GetPosition(&pos);
|
|
}
|
|
emitter->setGlobalPosition(getFrom(pos));
|
|
emitter->userData = result;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Render Settings :
|
|
//
|
|
|
|
pFluidRenderSettings *rSettings = new pFluidRenderSettings(ctx(),desc.entityReference,"pFluidEmitter");
|
|
rSettings->setToDefault();
|
|
rSettings->setEmitter(result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
CK3dEntity*pFluid::getParticleObject()
|
|
{
|
|
|
|
CK3dEntity* result = (CK3dEntity*)ctx()->GetObject(entityID);
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
void pFluid::updateVirtoolsMesh()
|
|
{
|
|
|
|
/*
|
|
updateCloud();
|
|
return;*/
|
|
//todo, move this into a small billboard rendering lib.
|
|
if (!mRenderBuffer)
|
|
{
|
|
unsigned sizeFloat = mMaxParticles * 3 * 4;
|
|
mRenderBuffer = new float[sizeFloat];
|
|
|
|
if (mTrackUserData)
|
|
{
|
|
mRenderBufferUserData = new float[mMaxParticles * 4 * 4];
|
|
}
|
|
|
|
}
|
|
|
|
return ;
|
|
|
|
CK3dEntity *dstEnt = getParticleObject();
|
|
CKMesh *mesh = getParticleObject()->GetCurrentMesh();
|
|
|
|
if (!dstEnt || !mesh )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (mParticleBuffer)
|
|
{
|
|
|
|
for (int i = 0 ; i < mesh->GetVertexCount() ; i++)
|
|
{
|
|
|
|
pParticle *p = &mParticleBuffer[i];
|
|
if (p)
|
|
{
|
|
VxVector v = getFrom(p->position);
|
|
VxVector outIV;
|
|
getParticleObject()->InverseTransform(&outIV,&v);
|
|
mesh->SetVertexPosition(i,&outIV);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
mesh->VertexMove();
|
|
}
|
|
|
|
pFluid::pFluid(NxFluidDesc &desc, bool trackUserData, bool provideCollisionNormals, const VxVector& color, float particleSize) :
|
|
|
|
mParticleBufferNum(0),
|
|
mParticleBuffer(NULL),
|
|
mFluid(NULL),
|
|
mTrackUserData(trackUserData),
|
|
mMyParticleBuffer(NULL),
|
|
mCreatedParticleIdsNum(0),
|
|
mCreatedParticleIds(NULL),
|
|
mDeletedParticleIdsNum(0),
|
|
mDeletedParticleIds(NULL),
|
|
mParticleColor(color),
|
|
mParticleSize(particleSize),
|
|
mRenderBuffer(NULL),
|
|
mRenderBufferUserData(NULL)
|
|
{
|
|
|
|
mMaxParticles = desc.maxParticles;
|
|
mParticleBuffer = new pParticle[mMaxParticles];
|
|
desc.userData = this;
|
|
|
|
entityID = 0;
|
|
|
|
|
|
//Setup particle write data.
|
|
NxParticleData particleData;
|
|
particleData.numParticlesPtr = &mParticleBufferNum;
|
|
particleData.bufferPos = &mParticleBuffer[0].position.x;
|
|
particleData.bufferPosByteStride = sizeof(pParticle);
|
|
particleData.bufferVel = &mParticleBuffer[0].velocity.x;
|
|
particleData.bufferVelByteStride = sizeof(pParticle);
|
|
particleData.bufferDensity = &mParticleBuffer[0].density;
|
|
particleData.bufferDensityByteStride = sizeof(pParticle);
|
|
particleData.bufferLife = &mParticleBuffer[0].lifetime;
|
|
particleData.bufferLifeByteStride = sizeof(pParticle);
|
|
particleData.bufferId = &mParticleBuffer[0].id;
|
|
particleData.bufferIdByteStride = sizeof(pParticle);
|
|
|
|
if (provideCollisionNormals)
|
|
{
|
|
particleData.bufferCollisionNormal = &mParticleBuffer[0].collisionNormal.x;
|
|
particleData.bufferCollisionNormalByteStride = sizeof(pParticle);
|
|
}
|
|
|
|
desc.particlesWriteData = particleData;
|
|
|
|
//User data buffers
|
|
if (mTrackUserData)
|
|
{
|
|
//mMyParticleBuffer = new MyParticle[mMaxParticles];
|
|
mCreatedParticleIds = new NxU32[mMaxParticles];
|
|
mDeletedParticleIds = new NxU32[mMaxParticles];
|
|
|
|
//Setup id write data.
|
|
NxParticleIdData idData;
|
|
|
|
//Creation
|
|
idData.numIdsPtr = &mCreatedParticleIdsNum;
|
|
idData.bufferId = mCreatedParticleIds;
|
|
idData.bufferIdByteStride = sizeof(NxU32);
|
|
desc.particleCreationIdWriteData = idData;
|
|
|
|
//Deletion
|
|
idData.numIdsPtr = &mDeletedParticleIdsNum;
|
|
idData.bufferId = mDeletedParticleIds;
|
|
idData.bufferIdByteStride = sizeof(NxU32);
|
|
desc.particleDeletionIdWriteData = idData;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
pFluidDesc::pFluidDesc()
|
|
{
|
|
|
|
setToDefault();
|
|
}
|
|
|
|
void pFluidDesc::setToDefault()
|
|
{
|
|
|
|
maxParticles = 500;
|
|
numReserveParticles = 0;
|
|
restParticlesPerMeter = 50.0f;
|
|
restDensity = 1000.0f;
|
|
kernelRadiusMultiplier = 1.2f;
|
|
motionLimitMultiplier = 3.0f * kernelRadiusMultiplier;
|
|
collisionDistanceMultiplier = 0.1f * kernelRadiusMultiplier;
|
|
packetSizeMultiplier = 16;
|
|
stiffness = 20.0f;
|
|
viscosity = 6.0f;
|
|
surfaceTension = 0.0f;
|
|
damping = 0.0f;
|
|
fadeInTime = 0.0f;
|
|
externalAcceleration.Set(0.0f,0.0f,0.0f);
|
|
projectionPlane.set(NxVec3(0.0f, 0.0f, 1.0f), 0.0f);
|
|
restitutionForStaticShapes = 0.5f;
|
|
dynamicFrictionForStaticShapes = 0.05f;
|
|
staticFrictionForStaticShapes = 0.05f;
|
|
attractionForStaticShapes = 0.0f;
|
|
restitutionForDynamicShapes = 0.5f;
|
|
dynamicFrictionForDynamicShapes = 0.5f;
|
|
staticFrictionForDynamicShapes = 0.5f;
|
|
attractionForDynamicShapes = 0.0f;
|
|
collisionResponseCoefficient = 0.2f;
|
|
|
|
simulationMethod = (pFluidSimulationMethod)(NX_F_SPH);
|
|
collisionMethod =(pFluidCollisionMethod)(NX_F_STATIC|NX_F_DYNAMIC);
|
|
collisionGroup = 0;
|
|
groupsMask.bits0 = 0;
|
|
groupsMask.bits1 = 0;
|
|
groupsMask.bits2 = 0;
|
|
groupsMask.bits3 = 0;
|
|
|
|
|
|
flags = (pFluidFlag)(NX_FF_ENABLED);
|
|
flags &= ~NX_FF_HARDWARE;
|
|
|
|
userData = NULL;
|
|
name = NULL;
|
|
worldReference = 0 ;
|
|
|
|
}
|
|
|
|
bool pFluidDesc::isValid()const
|
|
{
|
|
|
|
if (kernelRadiusMultiplier < 1.0f) return false;
|
|
if (restDensity <= 0.0f) return false;
|
|
if (restParticlesPerMeter <= 0.0f) return false;
|
|
|
|
if (packetSizeMultiplier < 4) return false;
|
|
if (packetSizeMultiplier & ( packetSizeMultiplier - 1 ) ) return false;
|
|
|
|
if (motionLimitMultiplier <= 0.0f) return false;
|
|
if (motionLimitMultiplier > packetSizeMultiplier*kernelRadiusMultiplier) return false;
|
|
|
|
if (collisionDistanceMultiplier <= 0.0f) return false;
|
|
if (collisionDistanceMultiplier > packetSizeMultiplier*kernelRadiusMultiplier) return false;
|
|
|
|
if (stiffness <= 0.0f) return false;
|
|
if (viscosity <= 0.0f) return false;
|
|
if (surfaceTension < 0.0f) return false;
|
|
|
|
bool isNoInteraction = (simulationMethod & NX_F_NO_PARTICLE_INTERACTION) > 0;
|
|
bool isSPH = (simulationMethod & NX_F_SPH) > 0;
|
|
bool isMixed = (simulationMethod & NX_F_MIXED_MODE) > 0;
|
|
if (!(isNoInteraction || isSPH || isMixed)) return false;
|
|
if (isNoInteraction && (isSPH || isMixed)) return false;
|
|
if (isSPH && (isNoInteraction || isMixed)) return false;
|
|
if (isMixed && (isNoInteraction || isSPH)) return false;
|
|
|
|
if (damping < 0.0f) return false;
|
|
if (fadeInTime < 0.0f) return false;
|
|
|
|
if (projectionPlane.normal.isZero()) return false;
|
|
|
|
if (dynamicFrictionForDynamicShapes < 0.0f || dynamicFrictionForDynamicShapes > 1.0f) return false;
|
|
if (staticFrictionForDynamicShapes < 0.0f || staticFrictionForDynamicShapes > 1.0f) return false;
|
|
if (restitutionForDynamicShapes < 0.0f || restitutionForDynamicShapes > 1.0f) return false;
|
|
if (attractionForDynamicShapes < 0.0f) return false;
|
|
if (dynamicFrictionForStaticShapes < 0.0f || dynamicFrictionForStaticShapes > 1.0f) return false;
|
|
if (staticFrictionForStaticShapes < 0.0f || staticFrictionForStaticShapes > 1.0f) return false;
|
|
if (restitutionForStaticShapes < 0.0f || restitutionForStaticShapes > 1.0f) return false;
|
|
if (attractionForStaticShapes < 0.0f) return false;
|
|
if (collisionResponseCoefficient < 0.0f) return false;
|
|
|
|
|
|
if (maxParticles > 32767) return false;
|
|
if (maxParticles < 1) return false;
|
|
|
|
if (numReserveParticles >= maxParticles) return false;
|
|
|
|
if(collisionGroup >= 32) return false; // We only support 32 different collision groups
|
|
|
|
return true;
|
|
}
|
|
|
|
void pFluid::updateCloud()
|
|
{
|
|
|
|
CK3dPointCloud *cloud = getPointCloud();
|
|
if (!cloud)
|
|
return;
|
|
|
|
CKMesh *mesh = getParticleObject()->GetCurrentMesh();
|
|
int count = mesh->GetVertexCount();
|
|
|
|
VxVector *points = new VxVector[count];
|
|
if (mParticleBuffer)
|
|
{
|
|
for (int i = 0 ; i < mesh->GetVertexCount() ; i++)
|
|
{
|
|
|
|
pParticle *p = &mParticleBuffer[i];
|
|
if (p)
|
|
{
|
|
points[i]= getFrom(p->position);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VxVector prec(0.5,0.5,0.5);
|
|
VxVector a[10];
|
|
|
|
|
|
int b = cloud->CreateFromPointList(2,a,NULL,NULL,NULL,prec);
|
|
if (b)
|
|
{
|
|
int op2=2;
|
|
op2++;
|
|
}
|
|
|
|
}
|
|
|
|
#endif // HAS_FLUIDS
|