// ----------------------------------------------------------------------- void MyCloth::generateMuscleMeshDesc(NxClothMeshDesc &desc, float height, float radius, int heightDivs, int aroundDivs) { desc.numVertices = aroundDivs*(heightDivs+1); desc.numTriangles = aroundDivs*heightDivs*2; desc.pointStrideBytes = sizeof(NxVec3); desc.triangleStrideBytes = 3*sizeof(NxU32); desc.vertexMassStrideBytes = sizeof(NxReal); desc.vertexFlagStrideBytes = sizeof(NxU32); desc.points = (NxVec3*)malloc(sizeof(NxVec3)*desc.numVertices); desc.triangles = (NxU32*)malloc(sizeof(NxU32)*desc.numTriangles*3); desc.vertexMasses = 0; desc.vertexFlags = 0; desc.flags = 0; desc.flags = NX_CLOTH_MESH_WELD_VERTICES; desc.weldingDistance = 0.0001f; mMaxVertices = desc.numVertices; mMaxIndices = 3 * desc.numTriangles; //points NxVec3* p = (NxVec3*)desc.points; for(int h=0; h<=heightDivs; h++) { for(int i=0; i<aroundDivs; i++) { double hDelta=((double)h)/heightDivs; double theta=((double)i)/aroundDivs*2.0*PI; double r=sin(hDelta*PI)*radius; //find radius of muscle, use sin func for now double x=r*cos(theta); double y=height*hDelta; double z=r*sin(theta); p->set((float)x,(float)y,(float)z); p++; } } //indices NxU32 *ind = (NxU32*)desc.triangles; for(int h=0; h<heightDivs; h++) { for(int i=0; i<aroundDivs; i++) { NxU32 i0 = h*aroundDivs + i; NxU32 i1 = h*aroundDivs + ((i+1)%aroundDivs); //wrap around NxU32 i2 = (h+1)*aroundDivs + i; NxU32 i3 = (h+1)*aroundDivs + ((i+1)%aroundDivs); //wrap around *ind++ = i0; *ind++ = i2; *ind++ = i1; *ind++ = i1; *ind++ = i2; *ind++ = i3; } } //texcoords mNumTempTexCoords = 0; mTempTexCoords = NULL; }
void ViewUnProject(int xi, int yi, float depth, NxVec3 &v) { //We cannot do picking easily on the xbox/PS3 anyway #if defined(_XBOX)||defined(__CELLOS_LV2__) v=NxVec3(0,0,0); #else GLint viewPort[4]; GLdouble modelMatrix[16]; GLdouble projMatrix[16]; glGetIntegerv(GL_VIEWPORT, viewPort); glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); yi = viewPort[3] - yi - 1; GLdouble wx, wy, wz; gluUnProject((GLdouble) xi, (GLdouble) yi, (GLdouble) depth, modelMatrix, projMatrix, viewPort, &wx, &wy, &wz); v.set((NxReal)wx, (NxReal)wy, (NxReal)wz); #endif }
void Cloth::generateRegularMeshDesc(NxClothMeshDesc &desc, NxReal w, NxReal h, NxReal d, bool texCoords) { int numX = (int)(w / d) + 1; int numY = (int)(h / d) + 1; desc.numVertices = (numX+1) * (numY+1); desc.numTriangles = numX*numY*2; desc.pointStrideBytes = sizeof(NxVec3); desc.triangleStrideBytes = 3*sizeof(NxU32); desc.vertexMassStrideBytes = sizeof(NxReal); desc.vertexFlagStrideBytes = sizeof(NxU32); desc.points = (NxVec3*)malloc(sizeof(NxVec3)*desc.numVertices); desc.triangles = (NxU32*)malloc(sizeof(NxU32)*desc.numTriangles*3); desc.vertexMasses = 0; desc.vertexFlags = 0; desc.flags = 0; mMaxVertices = TEAR_MEMORY_FACTOR * desc.numVertices; mMaxIndices = 3 * desc.numTriangles; _geo_cloth = new osg::Geode; int i,j; // create particles - POINTS { osg::Geometry* pointsGeom = new osg::Geometry(); osg::Vec3Array* vertices = new osg::Vec3Array; NxVec3 *p = (NxVec3*)desc.points; for (i = 0; i <= numY; i++) { for (j = 0; j <= numX; j++) { p->set(d*j, 0.0f, d*i); vertices->push_back(osg::Vec3f(d*j, d*i, 0.0f)); p++; } } pointsGeom->setVertexArray(vertices); osg::Vec4Array* colors = new osg::Vec4Array; colors->push_back(osg::Vec4(1.0f,1.0f,0.0f,0.8f)); pointsGeom->setColorArray(colors); pointsGeom->setColorBinding(osg::Geometry::BIND_OVERALL); // set the normal in the same way color. osg::Vec3Array* normals = new osg::Vec3Array; normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f)); pointsGeom->setNormalArray(normals); pointsGeom->setNormalBinding(osg::Geometry::BIND_OVERALL); osg::StateSet* stateSet = new osg::StateSet(); pointsGeom->setStateSet(stateSet); pointsGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS,0,vertices->size())); osg::Point* point = new osg::Point; point->setDistanceAttenuation(osg::Vec3(0.0,0.0000,0.05f)); point->setSize(20.0f); stateSet->setAttribute(point); osg::PointSprite *sprite = new osg::PointSprite(); stateSet->setTextureAttributeAndModes(0, sprite, osg::StateAttribute::ON); // add the points geometry to the geode. _geo_cloth->addDrawable(pointsGeom); } if (texCoords) { mTempTexCoords = (float *)malloc(sizeof(float)*2*TEAR_MEMORY_FACTOR*desc.numVertices); float *f = mTempTexCoords; float dx = 1.0f; if (numX > 0) dx /= numX; float dy = 1.0f; if (numY > 0) dy /= numY; for (i = 0; i <= numY; i++) { for (j = 0; j <= numX; j++) { *f++ = j*dx; *f++ = i*dy; } } mNumTempTexCoords = desc.numVertices; } else { mNumTempTexCoords = 0; mTempTexCoords = NULL; } NxU32 *id = (NxU32*)desc.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; } } } }
// ----------------------------------------------------------------------- void MyCloth::generateRegularMeshDesc(NxClothMeshDesc &desc, NxReal w, NxReal h, NxReal d, bool texCoords) { int numX = (int)(w / d) + 1; int numY = (int)(h / d) + 1; desc.numVertices = (numX+1) * (numY+1); desc.numTriangles = numX*numY*2; desc.pointStrideBytes = sizeof(NxVec3); desc.triangleStrideBytes = 3*sizeof(NxU32); desc.vertexMassStrideBytes = sizeof(NxReal); desc.vertexFlagStrideBytes = sizeof(NxU32); desc.points = (NxVec3*)malloc(sizeof(NxVec3)*desc.numVertices); desc.triangles = (NxU32*)malloc(sizeof(NxU32)*desc.numTriangles*3); desc.vertexMasses = 0; desc.vertexFlags = 0; desc.flags = 0; mMaxVertices = desc.numVertices; mMaxIndices = 3 * desc.numTriangles; int i,j; NxVec3 *p = (NxVec3*)desc.points; for (i = 0; i <= numY; i++) { for (j = 0; j <= numX; j++) { p->set(d*j, 0.0f, d*i); p++; } } if (texCoords) { mTempTexCoords = (GLfloat *)malloc(sizeof(GLfloat)*2*desc.numVertices); GLfloat *f = mTempTexCoords; GLfloat dx = 1.0f; if (numX > 0) dx /= numX; GLfloat dy = 1.0f; if (numY > 0) dy /= numY; for (i = 0; i <= numY; i++) { for (j = 0; j <= numX; j++) { *f++ = j*dx; *f++ = i*dy; } } mNumTempTexCoords = desc.numVertices; } else { mNumTempTexCoords = 0; mTempTexCoords = NULL; } NxU32 *id = (NxU32*)desc.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; } } } }
void PxCloth::_initClothMesh() { // Make sure we can change the world. mWorld->releaseWriteLock(); _releaseMesh(); // Must have at least 2 verts. mPatchVerts.x = getMax( 2, mPatchVerts.x ); mPatchVerts.y = getMax( 2, mPatchVerts.y ); // Generate a uniform cloth patch, // w and h are the width and height, // d is the distance between vertices. mNumVertices = mPatchVerts.x * mPatchVerts.y; mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 2; NxClothMeshDesc desc; desc.numVertices = mNumVertices; desc.numTriangles = mNumIndices; desc.pointStrideBytes = sizeof(NxVec3); desc.triangleStrideBytes = 3*sizeof(NxU32); desc.points = (NxVec3*)dMalloc(sizeof(NxVec3)*desc.numVertices); desc.triangles = (NxU32*)dMalloc(sizeof(NxU32)*desc.numTriangles*3); desc.flags = 0; U32 i,j; NxVec3 *p = (NxVec3*)desc.points; F32 patchWidth = mPatchSize.x / (F32)( mPatchVerts.x - 1 ); F32 patchHeight = mPatchSize.y / (F32)( mPatchVerts.y - 1 ); for (i = 0; i < mPatchVerts.y; i++) { for (j = 0; j < mPatchVerts.x; j++) { p->set( patchWidth * j, 0.0f, patchHeight * i ); p++; } } NxU32 *id = (NxU32*)desc.triangles; for (i = 0; i < mPatchVerts.y-1; i++) { for (j = 0; j < mPatchVerts.x-1; j++) { NxU32 i0 = i * mPatchVerts.x + j; NxU32 i1 = i0 + 1; NxU32 i2 = i0 + mPatchVerts.x; 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; } } } NxCookingInterface *cooker = PxWorld::getCooking(); cooker->NxInitCooking(); // Ok... cook the mesh! NxCookingParams params; params.targetPlatform = PLATFORM_PC; params.skinWidth = 0.01f; params.hintCollisionSpeed = false; cooker->NxSetCookingParams( params ); PxMemStream cooked; if ( cooker->NxCookClothMesh( desc, cooked ) ) { cooked.resetPosition(); mClothMesh = gPhysicsSDK->createClothMesh( cooked ); } cooker->NxCloseCooking(); NxVec3 *ppoints = (NxVec3*)desc.points; NxU32 *triangs = (NxU32*)desc.triangles; dFree( ppoints ); dFree( triangs ); if ( mClothMesh ) _initReceiveBuffers(); }
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; }
static void calculateIntersectionDetails(NxBox& oob1, NxBox& oob2, float& outVolume2, NxVec3& outGlobalIntersectionCenter2) { float step = 0.5f; if( step > oob2.extents.x * 2 ) step = oob2.extents.x * 2; if( step > oob2.extents.y * 2 ) step = oob2.extents.y * 2; if( step > oob2.extents.z * 2 ) step = oob2.extents.z * 2; float x = -oob2.extents.x; float y = -oob2.extents.y; float z = -oob2.extents.z; NxVec3 localPoint; NxVec3 globalPoint; NxVec3 localIntersectionCenter( 0,0,0 ); unsigned int numTotalPoints = 0; unsigned int numIntersectedPoints = 0; NxMat34 matrix2; matrix2.M = oob2.rot; matrix2.t = oob2.center; while( x <= oob2.extents.x ) { while( y <= oob2.extents.y ) { while( z <= oob2.extents.z ) { localPoint.set( x,y,z ); globalPoint = matrix2 * localPoint; if( NxBoxContainsPoint( oob1, globalPoint ) ) { if( numIntersectedPoints ) { localIntersectionCenter = localPoint; } else { localIntersectionCenter += localPoint; } numIntersectedPoints++; } numTotalPoints++; z += step; } z = -oob2.extents.z; y += step; } y = -oob2.extents.y; x += step; } outVolume2 = float( numIntersectedPoints ) / float( numTotalPoints ); if( numIntersectedPoints ) { localIntersectionCenter = localIntersectionCenter / float( numIntersectedPoints ); } outGlobalIntersectionCenter2 = matrix2 * localIntersectionCenter; // getCore()->logMessage( "oobb intersection volume: %3.2f (%d/%d) step: %3.2f", outVolume2, numIntersectedPoints, numTotalPoints, step ); }
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 render() { static Timer t; if(!gMyPhysX.isPaused()) { for (NxU32 i = 0; i < gKinematicActors.size(); i++) { NxActor* actor = gKinematicActors[i].actor; NxVec3 pos = actor->getGlobalPosition(); pos += gKinematicActors[i].vel * 1.f/60.f; actor->moveGlobalPosition(pos); } } gMyPhysX.simulate(t.elapsed_time()); t.reset(); // Clear buffers glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glColor4f(0.5,0.9,0.5,1.0); DrawSkyBox(SKYEXTENTS); drawPlane(SKYEXTENTS); // Keep physics & graphics in sync for (NxU32 pass = 0; pass < 2; pass++) { int nbActors = gMyPhysX.getScene()->getNbActors(); NxActor** actors = gMyPhysX.getScene()->getActors(); actors += nbActors; while(nbActors--) { NxActor* actor = *--actors; float size; bool isTrigger = false; bool isKinematic = actor->isDynamic() && actor->readBodyFlag(NX_BF_KINEMATIC); NxVec3 color; NxF32 alpha = 1; if (actor->isDynamic()) { if (actor->readBodyFlag(NX_BF_KINEMATIC)) { color.set(1,0,0); } else { color.set(0,1,0); } } else { color.set(0.2f,0.2f,0.2f); } if (*(int *)(&actor->userData) < 0) { NxI32 triggerNumber = -(*(NxI32 *)(&actor->userData)); NxI32 triggerIndex = triggerNumber - 1; // This is our trigger isTrigger = true; size = 10.0f; color.z = gNbTouchedBodies[triggerIndex] > 0.5f ? 1.0f:0.0f; alpha = 0.5f; if (pass == 0) continue; } else { // This is a normal object size = float(*(int *)(&actor->userData)); if (pass == 1) continue; } float glmat[16]; glPushMatrix(); actor->getGlobalPose().getColumnMajor44(glmat); glMultMatrixf(glmat); glColor4f(color.x, color.y, color.z, 1.0f); glutSolidCube(size*2.0f); glPopMatrix(); // Handle shadows if( !isTrigger) { glPushMatrix(); const static float ShadowMat[]={ 1,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,1 }; glMultMatrixf(ShadowMat); glMultMatrixf(glmat); glDisable(GL_LIGHTING); glColor4f(0.1f, 0.2f, 0.3f, 1.0f); glutSolidCube(size*2.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glEnable(GL_LIGHTING); glPopMatrix(); } } } }