int main(int argc, char **argv) { //init and PVD bool initialized = false; NxPhysicsSDK *physicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION); if (!physicsSDK) return 0; else physicsSDK->getFoundationSDK().getRemoteDebugger()->connect("localhost", 5425); physicsSDK->setParameter(NX_CONTINUOUS_CD, true); initialized = true; //create a scene bool sceneInit = false; NxSceneDesc sceneDesc; sceneDesc.gravity.set(0, -9.81f, 0); gScene = physicsSDK->createScene(sceneDesc); if (gScene != NULL) sceneInit = true; //create a plane { NxActorDesc actorDesc; NxPlaneShapeDesc planeDesc; //planeDesc.normal = NxVec3(0, 0, 1); //planeDesc.d = -10.0f; actorDesc.shapes.pushBack(&planeDesc); gScene->createActor(actorDesc); } //create material NxMaterial *defaultMaterial = gScene->getMaterialFromIndex(0); defaultMaterial->setRestitution(0.3f); defaultMaterial->setStaticFriction(0.5f); defaultMaterial->setDynamicFriction(0.5f); //create a box { NxActorDesc actorDesc; NxBodyDesc bodyDesc; bodyDesc.angularDamping = 0.5; bodyDesc.linearVelocity = NxVec3(1, 0, 0); actorDesc.body = &bodyDesc; NxBoxShapeDesc boxDesc; boxDesc.dimensions = NxVec3(2.0f, 3.0f, 4.0f); actorDesc.shapes.pushBack(&boxDesc); actorDesc.density = 10.0f; actorDesc.globalPose.t = NxVec3(10.0f, 10.0f, 10.0f); gScene->createActor(actorDesc)->userData = NULL; } //create a cloth { // Create the objects in the scene NxActor* sphere1 = CreateSphere(NxVec3(-1, 0, -0.5), 1, 10); NxActor* box1 = CreateBox(NxVec3(1, 0, -1), NxVec3(1, 1, 1), 10); NxActor* box2 = CreateBox(NxVec3(0, 6.5, 0), NxVec3(5, 0.5, 0.5), 10); NxActor* box3 = CreateBox(NxVec3(0, 6.5, -7), NxVec3(5, 0.5, 0.5), 10); box2->setLinearDamping(5); box3->setLinearDamping(5); NxD6JointDesc d6Desc; d6Desc.actor[0] = NULL; d6Desc.actor[1] = box2; NxVec3 globalAnchor(0, 7, 0); d6Desc.localAnchor[0] = globalAnchor; box2->getGlobalPose().multiplyByInverseRT(globalAnchor, d6Desc.localAnchor[1]); box2->raiseBodyFlag(NX_BF_DISABLE_GRAVITY); box3->getGlobalPose().multiplyByInverseRT(globalAnchor, d6Desc.localAnchor[1]); box3->raiseBodyFlag(NX_BF_DISABLE_GRAVITY); d6Desc.localAxis[0] = NxVec3(1, 0, 0); d6Desc.localNormal[0] = NxVec3(0, 1, 0); d6Desc.localAxis[1] = NxVec3(1, 0, 0); d6Desc.localNormal[1] = NxVec3(0, 1, 0); d6Desc.twistMotion = NX_D6JOINT_MOTION_LOCKED; d6Desc.swing1Motion = NX_D6JOINT_MOTION_LOCKED; d6Desc.swing2Motion = NX_D6JOINT_MOTION_LOCKED; d6Desc.xMotion = NX_D6JOINT_MOTION_FREE; d6Desc.yMotion = NX_D6JOINT_MOTION_FREE; d6Desc.zMotion = NX_D6JOINT_MOTION_FREE; NxJoint* d6Joint = gScene->createJoint(d6Desc); NxClothDesc clothDesc; clothDesc.globalPose.t = NxVec3(4, 7, 0); clothDesc.thickness = 0.2; //clothDesc.density = 1; clothDesc.bendingStiffness = 0.5; clothDesc.stretchingStiffness = 1; //clothDesc.dampingCoefficient = 0.5; clothDesc.friction = 0.5; //clothDesc.collisionResponseCoefficient = 1; //clothDesc.attachmentResponseCoefficient = 1; //clothDesc.solverIterations = 5; //clothDesc.flags |= NX_CLF_STATIC; //clothDesc.flags |= NX_CLF_DISABLE_COLLISION; //clothDesc.flags |= NX_CLF_VISUALIZATION; //clothDesc.flags |= NX_CLF_GRAVITY; clothDesc.flags |= NX_CLF_BENDING; //clothDesc.flags |= NX_CLF_BENDING_ORTHO; clothDesc.flags |= NX_CLF_DAMPING; //clothDesc.flags |= NX_CLF_COMDAMPING; clothDesc.flags |= NX_CLF_COLLISION_TWOWAY; clothDesc.flags &= ~NX_CLF_HARDWARE; clothDesc.flags |= NX_CLF_FLUID_COLLISION; clothDesc.selfCollisionThickness = 10.0f; NxReal w = 8; NxReal h = 7; NxReal d = 0.05; NxClothMeshDesc meshDesc; bool mInitDone = false; int numX = (int)(w / d) + 1; int numY = (int)(h / d) + 1; meshDesc.numVertices = (numX + 1) * (numY + 1); meshDesc.numTriangles = numX*numY * 2; meshDesc.pointStrideBytes = sizeof(NxVec3); meshDesc.triangleStrideBytes = 3 * sizeof(NxU32); meshDesc.vertexMassStrideBytes = sizeof(NxReal); meshDesc.vertexFlagStrideBytes = sizeof(NxU32); meshDesc.points = (NxVec3*)malloc(sizeof(NxVec3)*meshDesc.numVertices); meshDesc.triangles = (NxU32*)malloc(sizeof(NxU32)*meshDesc.numTriangles * 3); meshDesc.vertexMasses = 0; meshDesc.vertexFlags = 0; meshDesc.flags = 0; int i, j; NxVec3 *p = (NxVec3*)meshDesc.points; for (i = 0; i <= numY; i++) { for (j = 0; j <= numX; j++) { p->set(-d*j, 0.0f, -d*i); p++; } } NxU32 *id = (NxU32*)meshDesc.triangles; for (i = 0; i < numY; i++) { for (j = 0; j < numX; j++) { NxU32 i0 = i * (numX + 1) + j; NxU32 i1 = i0 + 1; NxU32 i2 = i0 + (numX + 1); NxU32 i3 = i2 + 1; if ((j + i) % 2) { *id++ = i0; *id++ = i2; *id++ = i1; *id++ = i1; *id++ = i2; *id++ = i3; } else { *id++ = i0; *id++ = i2; *id++ = i3; *id++ = i0; *id++ = i3; *id++ = i1; } } } // if we want tearing we must tell the cooker // this way it will generate some space for particles that will be generated during tearing if (meshDesc.flags & NX_CLF_TEARABLE) meshDesc.flags |= NX_CLOTH_MESH_TEARABLE; //cooking static NxCookingInterface *gCooking = 0; gCooking = NxGetCookingLib(NX_PHYSICS_SDK_VERSION); gCooking->NxInitCooking(); gCooking->NxCookClothMesh(meshDesc, UserStream("e:\\cooked.bin", false)); //Meshdata Buffers NxMeshData mReceiveBuffers; // here we setup the buffers through which the SDK returns the dynamic cloth data // we reserve more memory for vertices than the initial mesh takes // because tearing creates new vertices // the SDK only tears cloth as long as there is room in these buffers NxU32 numVertices = meshDesc.numVertices; NxU32 numTriangles = meshDesc.numTriangles; NxU32 maxVertices = 2 * numVertices; mReceiveBuffers.verticesPosBegin = (NxVec3*)malloc(sizeof(NxVec3)*maxVertices); mReceiveBuffers.verticesNormalBegin = (NxVec3*)malloc(sizeof(NxVec3)*maxVertices); mReceiveBuffers.verticesPosByteStride = sizeof(NxVec3); mReceiveBuffers.verticesNormalByteStride = sizeof(NxVec3); mReceiveBuffers.maxVertices = maxVertices; mReceiveBuffers.numVerticesPtr = (NxU32*)malloc(sizeof(NxU32)); // the number of triangles is constant, even if the cloth is torn NxU32 maxIndices = 3 * numTriangles; mReceiveBuffers.indicesBegin = (NxU32*)malloc(sizeof(NxU32)*maxIndices); mReceiveBuffers.indicesByteStride = sizeof(NxU32); mReceiveBuffers.maxIndices = maxIndices; mReceiveBuffers.numIndicesPtr = (NxU32*)malloc(sizeof(NxU32)); // the parent index information would be needed if we used textured cloth NxU32 maxParentIndices = maxVertices; mReceiveBuffers.parentIndicesBegin = (NxU32*)malloc(sizeof(NxU32)*maxParentIndices); mReceiveBuffers.parentIndicesByteStride = sizeof(NxU32); mReceiveBuffers.maxParentIndices = maxParentIndices; mReceiveBuffers.numParentIndicesPtr = (NxU32*)malloc(sizeof(NxU32)); // init the buffers in case we want to draw the mesh // before the SDK as filled in the correct values *mReceiveBuffers.numVerticesPtr = 0; *mReceiveBuffers.numIndicesPtr = 0; clothDesc.clothMesh = physicsSDK->createClothMesh(UserStream("e:\\cooked.bin", true)); clothDesc.meshData = mReceiveBuffers; NxCloth *mCloth; mCloth = gScene->createCloth(clothDesc); mCloth->attachToShape(*box2->getShapes(), NX_CLOTH_ATTACHMENT_TWOWAY); mCloth->attachToShape(*box3->getShapes(), NX_CLOTH_ATTACHMENT_TWOWAY); } //create fluid 1 { //fluid = CreateFluid(NxVec3(0, 12, -3.5), 15, 0.1, gScene); } //create fluid 2 { //Create a set of initial particles ParticleSDK* initParticles = new ParticleSDK[max_particles]; unsigned initParticlesNum = 0; //Create particle filled sphere in buffer. NxVec3 fluidPos(0, 2, 0); NxVec3 offsetPos(0, 12, -3.5); float distance = 0.1f; //#ifdef __PPCGEKKO__ // unsigned sideNum = 12; //#else unsigned sideNum = 16; //#endif //Setup structure to pass initial particles. NxParticleData initParticleData; initParticlesNum = 0; initParticleData.numParticlesPtr = &initParticlesNum; initParticleData.bufferPos = &initParticles[0].position.x; initParticleData.bufferPosByteStride = sizeof(ParticleSDK); initParticleData.bufferVel = &initParticles[0].velocity.x; initParticleData.bufferVelByteStride = sizeof(ParticleSDK); CreateParticleSphere(initParticleData, max_particles, false, offsetPos, NxVec3(0, 0, 0), 0.0f, distance, sideNum); //Setup fluid descriptor NxFluidDesc fluidDesc; fluidDesc.maxParticles = max_particles; fluidDesc.kernelRadiusMultiplier = 2.0f; fluidDesc.restParticlesPerMeter = 10.0f; fluidDesc.motionLimitMultiplier = 3.0f; fluidDesc.packetSizeMultiplier = 8; fluidDesc.collisionDistanceMultiplier = 0.1; fluidDesc.stiffness = 50.0f; fluidDesc.viscosity = 40.0f; fluidDesc.restDensity = 1000.0f; fluidDesc.damping = 0.0f; fluidDesc.restitutionForStaticShapes = 0.0f; fluidDesc.dynamicFrictionForStaticShapes = 0.05f; fluidDesc.simulationMethod = NX_F_SPH; fluidDesc.flags &= ~NX_FF_HARDWARE; //Add initial particles to fluid creation. 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.4f, 0.5f, 0.9f), 0.03f); assert(fluid); gMyFluids.pushBack(fluid); } //simulate for (int i = 0; i < 3000; i++) { gScene->simulate(1.0f / 60.f); gScene->flushStream(); //GetPhysicsResults gScene->fetchResults(NX_RIGID_BODY_FINISHED, true); // update fluid status if (i == 400) { MyFluid* fluid = gMyFluids[0]; const ParticleSDK* particles = fluid->getParticles(); unsigned particlesNum = fluid->getParticlesNum(); if (!gUpdates) { gUpdates = new ParticleUpdateSDK[max_particles]; } for (unsigned i = 0; i < particlesNum; i++) { ParticleUpdateSDK& update = gUpdates[i]; NxVec3& force = update.force; force.set(0, 0, 0); NxU32& flags = update.flags; if (i >= particlesNum/2) { flags = 0; flags |= NX_FP_DELETE; } else { flags = 0; } } //在这里更改粒子的属性 NxParticleUpdateData updateData; updateData.bufferFlag = &gUpdates[0].flags; updateData.bufferFlagByteStride = sizeof(ParticleUpdateSDK); fluid->getNxFluid()->updateParticles(updateData); } } //release if (physicsSDK != NULL) { if (gScene != NULL) physicsSDK->releaseScene(*gScene); gScene = NULL; NxReleasePhysicsSDK(physicsSDK); physicsSDK = NULL; } return 1; }
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(); }
void GR_Fluid::renderWire(GU_Detail *gdp, RE_Render &ren, const GR_AttribOffset & /*ptinfo*/, const GR_DisplayOption *dopt, float /*lod*/, const GU_PrimGroupClosure * /*hidden_geometry*/) { GEO_AttributeHandle fluidAh= gdp->getDetailAttribute("cudaFluidPreview"); fluidAh.setElement(gdp); GEO_AttributeHandle fluid3DAh= gdp->getDetailAttribute("cudaFluid3DPreview"); fluid3DAh.setElement(gdp); GEO_AttributeHandle fluid3DSliceAh= gdp->getDetailAttribute("sliceDisplay"); fluid3DSliceAh.setElement(gdp); GEO_AttributeHandle fluidAh= gdp->getDetailAttribute("cudaFluidPreview"); fluidAh.setElement(gdp); GEO_AttributeHandle fluidIdAh= gdp->getDetailAttribute("solverId"); fluidIdAh.setElement(gdp); if (fluidAh.getI()== 1) { VHFluidSolver* currSolver = VHFluidSolver::solverList[fluidIdAh.getI()]; UT_Vector4 fluidPos(0,0,0); UT_Vector3D fluidRot(0,0,0); if(gdp->volumeCount() == 1) { GEO_Primitive* pprim = gdp->primitives().head(); GU_PrimVolume* volume = (GU_PrimVolume *)pprim; UT_Matrix4 fluidRotMat; volume->getTransform4(fluidRotMat); UT_XformOrder rotOrder; UT_Vector3D scale, trans; fluidRotMat.explode(rotOrder, fluidRot, scale, trans); fluidRot.radToDeg(); fluidPos = volume->getVertex().getPt()->getPos(); } float sizeX = currSolver->fluidSize.x*0.5; float sizeY = currSolver->fluidSize.y*0.5; int newResX = currSolver->res.x; int newResY = currSolver->res.y; if(displayX != newResX || displayY != newResY) { displayX = newResX; displayY = newResY; initPixelBuffer(true); } cu::cutilSafeCall(cu::cudaGraphicsMapResources(1, &cuda_pbo_resource, 0)); cu::float4 *d_output; size_t num_bytes; cu::cutilSafeCall(cu::cudaGraphicsResourceGetMappedPointer((void **)&d_output, &num_bytes, cuda_pbo_resource)); cu::cudaMemset(d_output, 0, displayX*displayY*sizeof(cu::float4)); currSolver->renderFluid(d_output); cu::cutilSafeCall(cu::cudaGraphicsUnmapResources(1, &cuda_pbo_resource, 0)); //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo); glBindTexture(GL_TEXTURE_2D, gl_Tex); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, displayX, displayY, GL_RGBA, GL_FLOAT, 0); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glEnable(GL_TEXTURE_2D); glPushMatrix(); glTranslatef(fluidPos.x(),fluidPos.y(),fluidPos.z()); glRotatef(fluidRot.z(),0,0,1); glRotatef(fluidRot.y(),0,1,0); glRotatef(fluidRot.x(),1,0,0); //glColor3f(1.0,1.0,1.0); //glDisable(GL_BLEND); //glDisable(GL_LIGHTING); //glBegin( GL_QUADS ); //glTexCoord2f(0.0f, 0.0f); glVertex3f(-sizeX,-sizeY,0.0f); //glTexCoord2f(0.0f, 1.0f); glVertex3f(-sizeX,sizeY,0.0f); //glTexCoord2f(1.0f, 1.0f); glVertex3f(sizeX,sizeY,0.0f); //glTexCoord2f(1.0f, 0.0f); glVertex3f(sizeX,-sizeY,0.0f); //glEnd(); ren.setColor(1,1,1,1); ren.blend(0); ren.toggleLighting(0); const float t0[] = {0,0}; const float t1[] = {0,1}; const float t2[] = {1,1}; const float t3[] = {1,0}; ren.beginQuads(); ren.t2DW(t0); ren.vertex3DW(-sizeX,-sizeY,0.0f); ren.t2DW(t1); ren.vertex3DW(-sizeX,sizeY,0.0f); ren.t2DW(t2); ren.vertex3DW(sizeX,sizeY,0.0f); ren.t2DW(t3); ren.vertex3DW(sizeX,-sizeY,0.0f); ren.endQuads(); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); ren.beginClosedLine(); ren.vertex3DW(-sizeX,-sizeY,0.0f); ren.vertex3DW(-sizeX,sizeY,0.0f); ren.vertex3DW(sizeX,sizeY,0.0f); ren.vertex3DW(sizeX,-sizeY,0.0f); ren.endClosedLine(); ren.toggleLighting(1); glPopMatrix(); } if (fluid3DAh.getI() == 1 || fluid3DSliceAh.getI()== 1) { ren.toggleLighting(0); VHFluidSolver3D* curr3DSolver = VHFluidSolver3D::solverList[fluidIdAh.getI()]; UT_Vector4 fluidPos(0,0,0); UT_Vector3D fluidRot(0,0,0); if(gdp->volumeCount() == 1) { GEO_Primitive* pprim = gdp->primitives().head(); GU_PrimVolume* volume = (GU_PrimVolume *)pprim; UT_Matrix4 fluidRotMat; volume->getTransform4(fluidRotMat); UT_XformOrder rotOrder; UT_Vector3D scale, trans; fluidRotMat.explode(rotOrder, fluidRot, scale, trans); fluidRot.radToDeg(); fluidPos = volume->getVertex().getPt()->getPos(); } float sizeX = curr3DSolver->fluidSize.x*0.5; float sizeY = curr3DSolver->fluidSize.y*0.5; float sizeZ = curr3DSolver->fluidSize.z*0.5; if(curr3DSolver->drawCube) { glPushMatrix(); glTranslatef(fluidPos.x(),fluidPos.y(),fluidPos.z()); glRotatef(fluidRot.z(),0,0,1); glRotatef(fluidRot.y(),0,1,0); glRotatef(fluidRot.x(),1,0,0); drawWireCube(sizeX,sizeY,sizeZ, ren); glPopMatrix(); } if (fluid3DAh.getI()== 1) { curr3DSolver->drawFluid(); } if (fluid3DSliceAh.getI()== 1) { curr3DSolver->drawFluidSlice(); } ren.toggleLighting(1); } }
void GR_CudaHardware::renderWire(GU_Detail *gdp, RE_Render &ren, const GR_AttribOffset & /*ptinfo*/, const GR_DisplayOption *dopt, float /*lod*/, const GU_PrimGroupClosure * /*hidden_geometry*/) { GEO_AttributeHandle fluidAh= gdp->getDetailAttribute("cudaFluidPreview"); fluidAh.setElement(gdp); if (fluidAh.getI()== 1) { GEO_AttributeHandle fluidIdAh= gdp->getDetailAttribute("solverId"); fluidIdAh.setElement(gdp); VHFluidSolver* currSolver = VHFluidSolver::solverList[fluidIdAh.getI()]; UT_Vector4 fluidPos(0,0,0); UT_Vector3D fluidRot(0,0,0); if(gdp->volumeCount() == 1) { GEO_Primitive* pprim = gdp->primitives().head(); GU_PrimVolume* volume = (GU_PrimVolume *)pprim; UT_Matrix4 fluidRotMat; volume->getTransform4(fluidRotMat); UT_XformOrder rotOrder; UT_Vector3D scale, trans; fluidRotMat.explode(rotOrder, fluidRot, scale, trans); fluidRot.radToDeg(); fluidPos = volume->getVertex().getPt()->getPos(); } currSolver->drawFluid(fluidRot.x(), fluidRot.y(), fluidRot.z(), fluidPos.x(), fluidPos.y(), fluidPos.z()); } GEO_AttributeHandle partsAh= gdp->getDetailAttribute("cudaParticlesPreview"); partsAh.setElement(gdp); if (partsAh.getI()== 1) { GEO_AttributeHandle partsIdAh= gdp->getDetailAttribute("systemId"); partsIdAh.setElement(gdp); ren.toggleLighting(0); VHParticlesSystem* currSystem = VHParticlesSystem::systemsList[partsIdAh.getI()]; glClear(GL_COLOR_BUFFER_BIT); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE ); currSystem->draw(); glDisable( GL_BLEND ); ren.toggleLighting(1); } GEO_AttributeHandle fluid3DAh= gdp->getDetailAttribute("cudaFluid3DPreview"); fluid3DAh.setElement(gdp); GEO_AttributeHandle fluid3DSliceAh= gdp->getDetailAttribute("sliceDisplay"); fluid3DSliceAh.setElement(gdp); if (fluid3DAh.getI() == 1 || fluid3DSliceAh.getI()== 1) { GEO_AttributeHandle fluidIdAh= gdp->getDetailAttribute("solverId"); fluidIdAh.setElement(gdp); ren.toggleLighting(0); VHFluidSolver3D* curr3DSolver = VHFluidSolver3D::solverList[fluidIdAh.getI()]; UT_Vector4 fluidPos(0,0,0); UT_Vector3D fluidRot(0,0,0); if(gdp->volumeCount() > 0) { GEO_Primitive* pprim = gdp->primitives().head(); GU_PrimVolume* volume = (GU_PrimVolume *)pprim; UT_Matrix4 fluidRotMat; volume->getTransform4(fluidRotMat); UT_XformOrder rotOrder; UT_Vector3D scale, trans; fluidRotMat.explode(rotOrder, fluidRot, scale, trans); fluidRot.radToDeg(); fluidPos = volume->getVertex().getPt()->getPos(); } float sizeX = curr3DSolver->fluidSize.x*0.5; float sizeY = curr3DSolver->fluidSize.y*0.5; float sizeZ = curr3DSolver->fluidSize.z*0.5; if(curr3DSolver->drawCube) { glPushMatrix(); glTranslatef(fluidPos.x(),fluidPos.y(),fluidPos.z()); glRotatef(fluidRot.z(),0,0,1); glRotatef(fluidRot.y(),0,1,0); glRotatef(fluidRot.x(),1,0,0); drawWireCube(sizeX,sizeY,sizeZ, ren); glPopMatrix(); } if (fluid3DAh.getI()== 1) { curr3DSolver->drawFluid(fluidRot.x(), fluidRot.y(), fluidRot.z(), fluidPos.x(), fluidPos.y(), fluidPos.z()); } if (fluid3DSliceAh.getI()== 1) { curr3DSolver->drawFluidSlice(fluidRot.x(), fluidRot.y(), fluidRot.z(), fluidPos.x(), fluidPos.y(), fluidPos.z()); } ren.toggleLighting(1); } }
OP_ERROR SOP_FluidSolver2D::cookMySop(OP_Context &context) { oldf = f; double t = context.getTime(); int f = context.getFrame(); UT_Interrupt *boss; GU_PrimVolume *volume; OP_Node::flags().timeDep = 1; fluidSolver->fps = OPgetDirector()->getChannelManager()->getSamplesPerSec(); int newResX = RESX(t); int newResY = RESY(t); if ( newResX != fluidSolver->res.x || newResY != fluidSolver->res.y) { fluidSolver->changeFluidRes(newResX,newResY); } UT_Vector3 fluidPos(POSX(t), POSY(t), POSZ(t)); UT_Vector3 fluidRot(ROTX(t), ROTY(t), ROTZ(t)); fluidRot.degToRad(); fluidSolver->fluidSize.x = FLUIDSIZEX(t); fluidSolver->fluidSize.y = FLUIDSIZEY(t); fluidSolver->borderNegX = BORDERNEGX(t); fluidSolver->borderPosX = BORDERPOSX(t); fluidSolver->borderNegY = BORDERNEGY(t); fluidSolver->borderPosY = BORDERPOSY(t); fluidSolver->preview = PREVIEW(t); fluidSolver->previewType = PREVIEWTYPE(t); fluidSolver->bounds = BOUNDS(t); fluidSolver->substeps = SUBSTEPS(t); fluidSolver->jacIter = JACITER(t); fluidSolver->densDis = DENSDIS(t); fluidSolver->densBuoyStrength = DENSBUOYSTRENGTH(t); float ddirX = DENSBUOYDIRX(t); float ddirY = DENSBUOYDIRY(t); fluidSolver->densBuoyDir = cu::make_float2(ddirX,ddirY); fluidSolver->velDamp = VELDAMP(t); fluidSolver->vortConf = VORTCONF(t); fluidSolver->noiseStr = NOISESTR(t); fluidSolver->noiseFreq = NOISEFREQ(t); fluidSolver->noiseOct = NOISEOCT(t); fluidSolver->noiseLacun = NOISELACUN(t); fluidSolver->noiseSpeed = NOISESPEED(t); fluidSolver->noiseAmp = NOISEAMP(t); if (error() < UT_ERROR_ABORT) { boss = UTgetInterrupt(); gdp->clearAndDestroy(); // Start the interrupt server if (boss->opStart("Building Volume")){ static float zero = 0.0; #ifdef HOUDINI_11 GB_AttributeRef fluidAtt = gdp->addAttrib("cudaFluidPreview", sizeof(int), GB_ATTRIB_INT, &zero); gdp->attribs().getElement().setValue<int>(fluidAtt, fluidSolver->preview); GB_AttributeRef solverIdAtt = gdp->addAttrib("solverId", sizeof(int), GB_ATTRIB_INT, &zero); gdp->attribs().getElement().setValue<int>(solverIdAtt, fluidSolver->id); #else GA_WOAttributeRef fluidAtt = gdp->addIntTuple(GA_ATTRIB_DETAIL, "cudaFluidPreview", 1); gdp->element().setValue<int>(fluidAtt, fluidSolver->preview); GA_WOAttributeRef solverIdAtt = gdp->addIntTuple(GA_ATTRIB_DETAIL, "solverId", 1); gdp->element().setValue<int>(solverIdAtt, fluidSolver->id); #endif UT_Matrix3 xform; const UT_XformOrder volXFormOrder; volume = (GU_PrimVolume *)GU_PrimVolume::build(gdp); #ifdef HOUDINI_11 volume->getVertex().getPt()->getPos() = fluidPos; #else volume->getVertexElement(0).getPt()->setPos(fluidPos); #endif xform.identity(); xform.scale(fluidSolver->fluidSize.x*0.5, fluidSolver->fluidSize.y*0.5, 0.25); xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder); volume->setTransform(xform); xform.identity(); xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder); xform.invert(); if(lockInputs(context) >= UT_ERROR_ABORT) return error(); if(getInput(0)){ GU_Detail* emittersInput = (GU_Detail*)inputGeo(0, context); GEO_PointList emittersList = emittersInput->points(); int numEmitters = emittersList.entries(); if (numEmitters != fluidSolver->nEmit) { delete fluidSolver->emitters; fluidSolver->nEmit = numEmitters; fluidSolver->emitters = new FluidEmitter[numEmitters]; } GEO_AttributeHandle radAh, amountAh; radAh = emittersInput->getPointAttribute("radius"); amountAh = emittersInput->getPointAttribute("amount"); for (int i = 0; i < numEmitters; i++) { UT_Vector4 emitPos = emittersList[i]->getPos(); UT_Vector3 emitPos3(emitPos); emitPos3 -= fluidPos; emitPos3 = emitPos3*xform; fluidSolver->emitters[i].posX = emitPos3.x(); fluidSolver->emitters[i].posY = emitPos3.y(); radAh.setElement(emittersList[i]); amountAh.setElement(emittersList[i]); fluidSolver->emitters[i].radius = radAh.getF(0); fluidSolver->emitters[i].amount = amountAh.getF(0); } } else { fluidSolver->nEmit = 0; } if(getInput(1)) { GU_Detail* collidersInput = (GU_Detail*)inputGeo(1, context); GEO_PointList collidersList = collidersInput->points(); int numColliders = collidersList.entries(); if (numColliders != fluidSolver->nColliders) { delete fluidSolver->colliders; fluidSolver->nColliders = numColliders; fluidSolver->colliders = new Collider[numColliders]; } GEO_AttributeHandle colRadAh; colRadAh = collidersInput->getPointAttribute("radius"); for (int i = 0; i < numColliders; i++) { UT_Vector4 colPos = collidersList[i]->getPos(); UT_Vector3 colPos3(colPos); colPos3 -= fluidPos; colPos3 = colPos3*xform; if (f > STARTFRAME(t)) { fluidSolver->colliders[i].oldPosX = fluidSolver->colliders[i].posX; fluidSolver->colliders[i].oldPosY = fluidSolver->colliders[i].posY; } else { fluidSolver->colliders[i].oldPosX = colPos3.x(); fluidSolver->colliders[i].oldPosY = colPos3.y(); } fluidSolver->colliders[i].posX = colPos3.x(); fluidSolver->colliders[i].posY = colPos3.y(); colRadAh.setElement(collidersList[i]); fluidSolver->colliders[i].radius = colRadAh.getF(0); } } else { fluidSolver->nColliders = 0; } unlockInputs(); if (f <= STARTFRAME(t)) { fluidSolver->resetFluid(); if (fluidSolver->preview != 1) { { UT_VoxelArrayWriteHandleF handle = volume->getVoxelWriteHandle(); handle->constant(0); } } } else { if (f!=oldf) { fluidSolver->solveFluid(); } if (fluidSolver->preview != 1) { cu::cudaMemcpy( fluidSolver->host_dens, fluidSolver->dev_dens, fluidSolver->res.x*fluidSolver->res.y*sizeof(float), cu::cudaMemcpyDeviceToHost ); { UT_VoxelArrayWriteHandleF handle = volume->getVoxelWriteHandle(); handle->size(fluidSolver->res.x, fluidSolver->res.y, 1); for (int i = 0; i < fluidSolver->res.x; i++) { for (int j = 0; j < fluidSolver->res.y; j++) { handle->setValue(i, j, 0, fluidSolver->host_dens[(j*fluidSolver->res.x + i)]); } } } } } select(GU_SPrimitive); } // Tell the interrupt server that we've completed. Must do this // regardless of what opStart() returns. boss->opEnd(); } gdp->notifyCache(GU_CACHE_ALL); return error(); }
OP_ERROR SOP_FluidSolver3D::cookMySop(OP_Context &context) { oldf = f; f = context.getFrame(); double t = context.getTime(); fluidSolver->fps = OPgetDirector()->getChannelManager()->getSamplesPerSec(); UT_Interrupt *boss; GU_PrimVolume *volume; GU_PrimVolume *velXVolume; GU_PrimVolume *velYVolume; GU_PrimVolume *velZVolume; OP_Node::flags().timeDep = 1; int newResX = RESX(t); int newResY = RESY(t); int newResZ = RESZ(t); if ( newResX != fluidSolver->res.width || newResY != fluidSolver->res.height || newResZ != fluidSolver->res.depth) { fluidSolver->changeFluidRes(newResX,newResY,newResZ); } UT_Vector3 fluidPos(POSX(t), POSY(t), POSZ(t)); UT_Vector3 fluidRot(ROTX(t), ROTY(t), ROTZ(t)); fluidRot.degToRad(); fluidSolver->fluidSize.x = FLUIDSIZEX(t); fluidSolver->fluidSize.y = FLUIDSIZEY(t); fluidSolver->fluidSize.z = FLUIDSIZEZ(t); fluidSolver->borderNegX = BORDERNEGX(t); fluidSolver->borderPosX = BORDERPOSX(t); fluidSolver->borderNegY = BORDERNEGY(t); fluidSolver->borderPosY = BORDERPOSY(t); fluidSolver->borderNegZ = BORDERNEGZ(t); fluidSolver->borderPosZ = BORDERPOSZ(t); fluidSolver->substeps = SUBSTEPS(t); fluidSolver->jacIter = JACITER(t); fluidSolver->densDis = DENSDIS(t); fluidSolver->densBuoyStrength = DENSBUOYSTRENGTH(t); float ddirX = DENSBUOYDIRX(t); float ddirY = DENSBUOYDIRY(t); float ddirZ = DENSBUOYDIRZ(t); fluidSolver->densBuoyDir = cu::make_float3(ddirX,ddirY,ddirZ); fluidSolver->velDamp = VELDAMP(t); fluidSolver->vortConf = VORTCONF(t); fluidSolver->noiseStr = NOISESTR(t); fluidSolver->noiseFreq = NOISEFREQ(t); fluidSolver->noiseOct = NOISEOCT(t); fluidSolver->noiseLacun = NOISELACUN(t); fluidSolver->noiseSpeed = NOISESPEED(t); fluidSolver->noiseAmp = NOISEAMP(t); fluidSolver->preview = PREVIEW(t); fluidSolver->drawCube = DRAWCUBE(t); fluidSolver->opaScale = OPASCALE(t); fluidSolver->stepMul = STEPMUL(t); fluidSolver->displayRes = DISPLAYRES(t); fluidSolver->doShadows = DOSHADOWS(t); float lightPosX = LIGHTPOSX(t); float lightPosY = LIGHTPOSY(t); float lightPosZ = LIGHTPOSZ(t); fluidSolver->lightPos = cu::make_float3(lightPosX,lightPosY,lightPosZ); fluidSolver->shadowDens = SHADOWDENS(t); fluidSolver->shadowStepMul = SHADOWSTEPMUL(t); fluidSolver->shadowThres = SHADOWTHRES(t); fluidSolver->displaySlice = DISPLAYSLICE(t); fluidSolver->sliceType = SLICETYPE(t); fluidSolver->sliceAxis = SLICEAXIS(t); fluidSolver->slicePos = SLICEPOS(t); fluidSolver->sliceBounds = SLICEBOUNDS(t); if (error() < UT_ERROR_ABORT) { boss = UTgetInterrupt(); gdp->clearAndDestroy(); // Start the interrupt server if (boss->opStart("Building Volume")){ static float zero = 0.0; GB_AttributeRef fluidAtt = gdp->addAttrib("cudaFluid3DPreview", sizeof(int), GB_ATTRIB_INT, &zero); gdp->attribs().getElement().setValue<int>(fluidAtt, fluidSolver->preview); GB_AttributeRef fluidSliceAtt = gdp->addAttrib("sliceDisplay", sizeof(int), GB_ATTRIB_INT, &zero); gdp->attribs().getElement().setValue<int>(fluidSliceAtt, fluidSolver->displaySlice); GB_AttributeRef solverIdAtt = gdp->addAttrib("solverId", sizeof(int), GB_ATTRIB_INT, &zero); gdp->attribs().getElement().setValue<int>(solverIdAtt, fluidSolver->id); GEO_AttributeHandle name_gah; int def = -1; gdp->addPrimAttrib("name", sizeof(int), GB_ATTRIB_INDEX, &def); name_gah = gdp->getPrimAttribute("name"); UT_Matrix3 xform; const UT_XformOrder volXFormOrder; volume = (GU_PrimVolume *)GU_PrimVolume::build(gdp); volume->getVertex().getPt()->getPos() = fluidPos; xform.identity(); xform.scale(fluidSolver->fluidSize.x*0.5, fluidSolver->fluidSize.y*0.5, fluidSolver->fluidSize.z*0.5); xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder); volume->setTransform(xform); name_gah.setElement(volume); name_gah.setString("density"); velXVolume = (GU_PrimVolume *)GU_PrimVolume::build(gdp); velXVolume->getVertex().getPt()->getPos() = fluidPos; velXVolume->setTransform(xform); name_gah.setElement(velXVolume); name_gah.setString("vel.x"); velYVolume = (GU_PrimVolume *)GU_PrimVolume::build(gdp); velYVolume->getVertex().getPt()->getPos() = fluidPos; velYVolume->setTransform(xform); name_gah.setElement(velYVolume); name_gah.setString("vel.y"); velZVolume = (GU_PrimVolume *)GU_PrimVolume::build(gdp); velZVolume->getVertex().getPt()->getPos() = fluidPos; velZVolume->setTransform(xform); name_gah.setElement(velZVolume); name_gah.setString("vel.z"); xform.identity(); xform.rotate(fluidRot.x(), fluidRot.y(), fluidRot.z(), volXFormOrder); xform.invert(); if(lockInputs(context) >= UT_ERROR_ABORT) return error(); if(getInput(0)){ GU_Detail* emittersInput = (GU_Detail*)inputGeo(0, context); GEO_PointList emittersList = emittersInput->points(); int numEmitters = emittersList.entries(); if (numEmitters != fluidSolver->nEmit) { delete fluidSolver->emitters; fluidSolver->nEmit = numEmitters; fluidSolver->emitters = new VHFluidEmitter[numEmitters]; } GEO_AttributeHandle radAh, amountAh; radAh = emittersInput->getPointAttribute("radius"); amountAh = emittersInput->getPointAttribute("amount"); for (int i = 0; i < numEmitters; i++) { UT_Vector4 emitPos = emittersList[i]->getPos(); UT_Vector3 emitPos3(emitPos); emitPos3 -= fluidPos; emitPos3 = emitPos3*xform; fluidSolver->emitters[i].posX = emitPos3.x(); fluidSolver->emitters[i].posY = emitPos3.y(); fluidSolver->emitters[i].posZ = emitPos3.z(); radAh.setElement(emittersList[i]); amountAh.setElement(emittersList[i]); fluidSolver->emitters[i].radius = radAh.getF(0); fluidSolver->emitters[i].amount = amountAh.getF(0); } } else { fluidSolver->nEmit = 0; } if(getInput(1)) { GU_Detail* collidersInput = (GU_Detail*)inputGeo(1, context); GEO_PointList collidersList = collidersInput->points(); int numColliders = collidersList.entries(); if (numColliders != fluidSolver->nColliders) { delete fluidSolver->colliders; fluidSolver->nColliders = numColliders; fluidSolver->colliders = new VHFluidCollider[numColliders]; } GEO_AttributeHandle colRadAh; colRadAh = collidersInput->getPointAttribute("radius"); for (int i = 0; i < numColliders; i++) { UT_Vector4 colPos = collidersList[i]->getPos(); UT_Vector3 colPos3(colPos); colPos3 -= fluidPos; colPos3 = colPos3*xform; if (f > STARTFRAME(t)) { fluidSolver->colliders[i].oldPosX = fluidSolver->colliders[i].posX; fluidSolver->colliders[i].oldPosY = fluidSolver->colliders[i].posY; fluidSolver->colliders[i].oldPosZ = fluidSolver->colliders[i].posZ; } else { fluidSolver->colliders[i].oldPosX = colPos3.x(); fluidSolver->colliders[i].oldPosY = colPos3.y(); fluidSolver->colliders[i].oldPosZ = colPos3.z(); } fluidSolver->colliders[i].posX = colPos3.x(); fluidSolver->colliders[i].posY = colPos3.y(); fluidSolver->colliders[i].posZ = colPos3.z(); colRadAh.setElement(collidersList[i]); fluidSolver->colliders[i].radius = colRadAh.getF(0); } } else { fluidSolver->nColliders = 0; } unlockInputs(); if (f <= STARTFRAME(t)) { fluidSolver->resetFluid(); if (COPYDENS(t)) { { UT_VoxelArrayWriteHandleF handle = volume->getVoxelWriteHandle(); handle->constant(0); UT_VoxelArrayWriteHandleF velXHandle = velXVolume->getVoxelWriteHandle(); velXHandle->constant(0); UT_VoxelArrayWriteHandleF velYHandle = velYVolume->getVoxelWriteHandle(); velYHandle->constant(0); UT_VoxelArrayWriteHandleF velZHandle = velZVolume->getVoxelWriteHandle(); velZHandle->constant(0); } } } else { if (f!=oldf) { fluidSolver->solveFluid(); } if (COPYDENS(t)) { cu::cudaMemcpy( fluidSolver->host_dens, fluidSolver->dev_dens, fluidSolver->res.width*fluidSolver->res.height*fluidSolver->res.depth*sizeof(float), cu::cudaMemcpyDeviceToHost ); { UT_VoxelArrayWriteHandleF handle = volume->getVoxelWriteHandle(); handle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth); for (int i = 0; i < fluidSolver->res.width; i++) { for (int j = 0; j < fluidSolver->res.height; j++) { for (int k = 0; k < fluidSolver->res.depth; k++) { handle->setValue(i, j, k, fluidSolver->host_dens[k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i]); } } } } if (COPYVEL(t)) { cu::cudaMemcpy( fluidSolver->host_vel, fluidSolver->dev_vel, fluidSolver->res.width*fluidSolver->res.height*fluidSolver->res.depth*sizeof(cu::float4), cu::cudaMemcpyDeviceToHost ); { UT_VoxelArrayWriteHandleF velXHandle = velXVolume->getVoxelWriteHandle(); velXHandle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth); UT_VoxelArrayWriteHandleF velYHandle = velYVolume->getVoxelWriteHandle(); velYHandle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth); UT_VoxelArrayWriteHandleF velZHandle = velZVolume->getVoxelWriteHandle(); velZHandle->size(fluidSolver->res.width, fluidSolver->res.height, fluidSolver->res.depth); for (int i = 0; i < fluidSolver->res.width; i++) { for (int j = 0; j < fluidSolver->res.height; j++) { for (int k = 0; k < fluidSolver->res.depth; k++) { velXHandle->setValue(i, j, k, fluidSolver->host_vel[4*(k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i)]); velYHandle->setValue(i, j, k, fluidSolver->host_vel[4*(k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i)+1]); velZHandle->setValue(i, j, k, fluidSolver->host_vel[4*(k*fluidSolver->res.width*fluidSolver->res.height + j*fluidSolver->res.width + i)+2]); } } } } } } } select(GU_SPrimitive); } // Tell the interrupt server that we've completed. Must do this // regardless of what opStart() returns. boss->opEnd(); } gdp->notifyCache(GU_CACHE_ALL); return error(); }