NxFluid* CreateFluid(const NxVec3& pos, NxU32 sideNum, NxReal distance, NxScene* scene) { // Create a set of particles gParticleBufferNum = 0; NxReal rad = sideNum*distance*0.5f; for (NxU32 i = 0; i < sideNum; i++) { for (NxU32 j = 0; j < sideNum; j++) { for (NxU32 k = 0; k < sideNum; k++) { NxVec3 p = NxVec3(i*distance, j*distance, k*distance); if (p.distance(NxVec3(rad, rad, rad)) < rad) { p += pos - NxVec3(rad, rad, rad); gParticleBuffer[gParticleBufferNum++] = p; } } } } // 先需要初始化大量粒子的参数 // Set structure to pass particles, and receive them after every simulation step NxParticleData particles; //particles.maxParticles = gParticleBufferCap; particles.numParticlesPtr = &gParticleBufferNum; particles.bufferPos = &gParticleBuffer[0].x; particles.bufferPosByteStride = sizeof(NxVec3); // 然后初始化流体的各项参数 // Create a fluid descriptor NxFluidDesc fluidDesc; fluidDesc.maxParticles = gParticleBufferCap; fluidDesc.kernelRadiusMultiplier = KERNEL_RADIUS_MULTIPLIER; fluidDesc.restParticlesPerMeter = REST_PARTICLES_PER_METER; fluidDesc.motionLimitMultiplier = MOTION_LIMIT_MULTIPLIER; fluidDesc.packetSizeMultiplier = PACKET_SIZE_MULTIPLIER; fluidDesc.stiffness = 50; fluidDesc.viscosity = 22; fluidDesc.restDensity = 1000; fluidDesc.damping = 0; fluidDesc.restitutionForStaticShapes = 0.4; fluidDesc.dynamicFrictionForStaticShapes = 0.3; fluidDesc.collisionResponseCoefficient = 0.5f; fluidDesc.collisionDistanceMultiplier = 0.1f; fluidDesc.simulationMethod = NX_F_SPH; //NX_F_NO_PARTICLE_INTERACTION; // 将流体需要的粒子与上述初始化的粒子关联起来 fluidDesc.initialParticleData = particles; fluidDesc.particlesWriteData = particles; fluidDesc.flags &= ~NX_FF_HARDWARE; fluidDesc.flags |= NX_FF_COLLISION_TWOWAY; NxFluid* fl = gScene->createFluid(fluidDesc); assert(fl != NULL); return fl; }
NxFluid* CreateFluid(const NxVec3& pos, NxU32 sideNum, NxReal distance, NxScene* scene) { float rad = sideNum*distance*0.5; for (unsigned i=0; i<sideNum; i++) for (unsigned j=0; j<sideNum; j++) for (unsigned k=0; k<sideNum; k++) { NxVec3 p = NxVec3(i*distance,j*distance,k*distance); if (p.distance(NxVec3(rad,rad,rad)) < rad) { p += pos; if(gParticleBufferNum< MAX_PARTICLES) gParticleBuffer[gParticleBufferNum++] = p; } } NxParticleData particles; //particles.maxParticles = gParticleBufferCap; particles.numParticlesPtr = &gParticleBufferNum; particles.bufferPos = &gParticleBuffer[0].x; particles.bufferPosByteStride = sizeof(NxVec3); //Create a fluid descriptor NxFluidDesc fluidDesc; fluidDesc.maxParticles = MAX_PARTICLES; fluidDesc.flags |= NX_FF_COLLISION_TWOWAY; fluidDesc.simulationMethod = NX_F_SPH; fluidDesc.restParticlesPerMeter = 5.0f; fluidDesc.motionLimitMultiplier = 10.0f; fluidDesc.restDensity = 1000.0f; fluidDesc.kernelRadiusMultiplier = 1.6f; fluidDesc.stiffness = 10.0f; fluidDesc.viscosity = 50.0f; fluidDesc.damping = 0.5f; fluidDesc.packetSizeMultiplier = 16; fluidDesc.name = "fluid"; fluidDesc.kernelRadiusMultiplier = KERNEL_RADIUS_MULTIPLIER; fluidDesc.restParticlesPerMeter = REST_PARTICLES_PER_METER; fluidDesc.motionLimitMultiplier = MOTION_LIMIT_MULTIPLIER; fluidDesc.packetSizeMultiplier = PACKET_SIZE_MULTIPLIER; fluidDesc.stiffness = 40; // 50 fluidDesc.viscosity = 22; fluidDesc.restDensity = 1000; fluidDesc.damping = 0; // There are some API changes since 280 version, Fluid collision coefficients have been renamed, // E.g. NxFluidDesc::dynamicCollisionAdhesion is named NxFluidDesc::dynamicFrictionForDynamicShapes. #if NX_SDK_VERSION_NUMBER < 280 fluidDesc.staticCollisionRestitution = 0.162f; fluidDesc.staticCollisionAdhesion = 0.146f; fluidDesc.dynamicCollisionRestitution = 0.5f; fluidDesc.dynamicCollisionAdhesion = 0.5f; #else fluidDesc.restitutionForStaticShapes = 0.162f; fluidDesc.dynamicFrictionForStaticShapes = 0.146f; fluidDesc.restitutionForDynamicShapes = 0.5f; fluidDesc.dynamicFrictionForDynamicShapes = 0.5f; #endif fluidDesc.simulationMethod = NX_F_SPH; //NX_F_NO_PARTICLE_INTERACTION; fluidDesc.initialParticleData = particles; fluidDesc.particlesWriteData = particles; if(!bHardwareFluid) fluidDesc.flags &= ~NX_FF_HARDWARE; fluid = gScene->createFluid(fluidDesc); if(!fluid) { fluidDesc.flags &= ~NX_FF_HARDWARE; bHardwareFluid = false; fluid = gScene->createFluid(fluidDesc); } assert(fluid != NULL); return fluid; }
void SampleCollision::setup() { SetTitleString(getName()); #ifdef __PPCGEKKO__ SetHelpString(" a: create rigid bodies"); #else SetHelpString(" b: create rigid bodies"); #endif gShadows = false; // Create objects in the scene if (!InitCooking(gAllocator, &gErrorStream)) { printf("\nError: Unable to initialize the cooking library, exiting the sample.\n\n"); return; } // Load ASE file CookASE("fluidSample.ase", gScene, NxVec3(1,10,0)); CookASE("coolFlow.ase", gScene, NxVec3(1,6,-0), NxVec3(1,0.2,1)); CloseCooking(); // Add a box shaped drain. NxActorDesc boxDrainActor; NxBoxShapeDesc boxDrainShape; boxDrainActor.shapes.pushBack(&boxDrainShape); boxDrainShape.dimensions.set(40,1,40); boxDrainShape.shapeFlags |= NX_SF_FLUID_DRAIN; boxDrainActor.globalPose.t.set(0, 0, 0); gScene->createActor(boxDrainActor); //Pre cook hotspots NxBounds3 precookAABB; precookAABB.set(NxVec3(-20,-20,-20), NxVec3(20,20,20)); // gScene->cookFluidMeshHotspot(precookAABB, PACKET_SIZE_MULTIPLIER, REST_PARTICLES_PER_METER, KERNEL_RADIUS_MULTIPLIER, MOTION_LIMIT_MULTIPLIER, COLLISION_DISTANCE_MULTIPLIER ); //Create a set of initial particles ParticleSDK* initParticles = new ParticleSDK[MAX_PARTICLES]; unsigned initParticlesNum = 0; NxVec3 fluidPos(0, 11.6, 0); float distance = 0.1f; unsigned sideNum = 16; float rad = sideNum*distance*0.5f; for (unsigned i=0; i<sideNum; i++) for (unsigned j=0; j<sideNum; j++) for (unsigned k=0; k<sideNum; k++) { NxVec3 p = NxVec3(i*distance,j*distance,k*distance); if (p.distance(NxVec3(rad,rad,rad)) < rad) { p += fluidPos; ParticleSDK& newParticle = initParticles[initParticlesNum++]; newParticle.position = p; newParticle.velocity = NxVec3(0,0,0); } } //Setup structure to pass initial particles. NxParticleData initParticleData; initParticleData.numParticlesPtr = &initParticlesNum; initParticleData.bufferPos = &initParticles[0].position.x; initParticleData.bufferPosByteStride = sizeof(ParticleSDK); initParticleData.bufferVel = &initParticles[0].velocity.x; initParticleData.bufferVelByteStride = sizeof(ParticleSDK); //Setup fluid descriptor NxFluidDesc fluidDesc; fluidDesc.maxParticles = initParticlesNum; fluidDesc.kernelRadiusMultiplier = KERNEL_RADIUS_MULTIPLIER; fluidDesc.restParticlesPerMeter = REST_PARTICLES_PER_METER; fluidDesc.collisionDistanceMultiplier = COLLISION_DISTANCE_MULTIPLIER; fluidDesc.stiffness = 50.0f; fluidDesc.viscosity = 22.0f; fluidDesc.damping = 0.0f; fluidDesc.restitutionForStaticShapes = 0.4f; fluidDesc.dynamicFrictionForStaticShapes = 0.03f; fluidDesc.simulationMethod = NX_F_SPH; //NX_F_NO_PARTICLE_INTERACTION; if (!gHardwareSimulation) fluidDesc.flags &= ~NX_FF_HARDWARE; fluidDesc.initialParticleData = initParticleData; //Create user fluid. //- create NxFluid in NxScene //- setup the buffers to read from data from the SDK //- set NxFluid::userData field to MyFluid instance bool trackUserData = false; bool provideCollisionNormals = false; MyFluid* fluid = new MyFluid(gScene, fluidDesc, trackUserData, provideCollisionNormals, NxVec3(0.2f,0.3f,0.7f), 0.03f); assert(fluid); gMyFluids.pushBack(fluid); delete[] initParticles; gCameraPos.set(23, 14, 23); gCameraForward = fluidPos - NxVec3(0, 3, 0) - gCameraPos; gCameraForward.normalize(); }