bool CPhysicsManager::ReleasePhysicActor (CPhysicActor* actor) { assert(actor != NULL); assert(m_pScene != NULL); assert(m_pPhysicsSDK != NULL); bool isOk = false; NxActor* nxActor = actor->GetPhXActor(); if( nxActor != 0) { NxArray<NxCCDSkeleton*> skeletons; for (NxU32 i = 0; i < nxActor->getNbShapes(); i++) { NxShape* shape = nxActor->getShapes()[i]; if (shape->getCCDSkeleton() != NULL) { skeletons.pushBack(shape->getCCDSkeleton()); } } for (NxU32 i = 0; i < skeletons.size(); i++) { m_pPhysicsSDK->releaseCCDSkeleton(*skeletons[i]); } m_pScene->releaseActor(*nxActor); nxActor = 0; } return true; }
//---------------------------------------------------------------------------- // ReleaseAllActors : Alliberem tots els actors de l'escena de PhysX //---------------------------------------------------------------------------- bool CPhysicsManager::ReleaseAllActors ( void ) //EUserDataFlag _eFlags ) { assert ( m_pScene != NULL ); assert ( m_pPhysicsSDK != NULL ); bool isOk = true; NxActor** l_ppActorList = m_pScene->getActors(); NxU32 l_TotalActors = m_pScene->getNbActors(); while ( l_TotalActors -- ) { NxActor* nxActor = *l_ppActorList; if ( nxActor != 0) { NxArray<NxCCDSkeleton*> skeletons; for (NxU32 i = 0; i < nxActor->getNbShapes(); i++) { NxShape* shape = nxActor->getShapes()[i]; if (shape->getCCDSkeleton() != NULL) { skeletons.pushBack(shape->getCCDSkeleton()); } } for (NxU32 i = 0; i < skeletons.size(); i++) { m_pPhysicsSDK->releaseCCDSkeleton(*skeletons[i]); } m_pScene->releaseActor(*nxActor); nxActor = 0; } } return isOk; }
// // EPhysXPhysEngine::BuildConvexMesh // NxConvexMesh *ESciVis::BuildConvexMesh( const IPxTriMesh input_mesh ) { //IPxTriMesh mesh = input_mesh->Clone(); //mesh->SetFormat( GE_MESH_POSITION ); //mesh->MergeVertices(); //This command causes convex cook crash NxConvexMeshDesc convex_mesh_desc; NxArray<NxVec3> verts; for (uint i=0; i<input_mesh->GetVertexNum(); i++) { EVertex v; v = input_mesh->GetVertex(i); verts.push_back( NxVec3(v.position.x, v.position.y, v.position.z) ); } convex_mesh_desc.numVertices = input_mesh->GetVertexNum(); convex_mesh_desc.pointStrideBytes = sizeof(NxVec3); convex_mesh_desc.points = &verts[0]; convex_mesh_desc.flags = NX_CF_COMPUTE_CONVEX; ASSERT( convex_mesh_desc.isValid() ); MemoryWriteBuffer buf; bool r = nx_cook->NxCookConvexMesh(convex_mesh_desc, buf); if (!r) { RUNTIME_ERROR("mesh contains to many vertices"); } return nx->createConvexMesh(MemoryReadBuffer(buf.data)); }
// ---------------------------------------------------------------------------------------------------------- void MeshHash::query(const NxBounds3 &bounds, NxArray<int> &itemIndices, int maxIndices) { int x1,y1,z1; int x2,y2,z2; int x,y,z; cellCoordOf(bounds.min, x1,y1,z1); cellCoordOf(bounds.max, x2,y2,z2); itemIndices.clear(); for (x = x1; x <= x2; x++) { for (y = y1; y <= y2; y++) { for (z = z1; z <= z2; z++) { int h = hashFunction(x,y,z); MeshHashRoot &r = mHashIndex[h]; if (r.timeStamp != mTime) continue; int i = r.first; while (i >= 0) { MeshHashEntry &entry = mEntries[i]; itemIndices.push_back(entry.itemIndex); if (maxIndices >= 0 && (int)itemIndices.size() >= maxIndices) return; i = entry.next; } } } } }
void SetupAttachmentScene() { sprintf(gTitleString, "Attachment Demo"); // Create objects in scene groundPlane = CreateGroundPlane(); NxActor* box1 = CreateBox(NxVec3(-7,12.25,0), NxVec3(2.5,1,1), 0); NxActor* box2 = CreateBox(NxVec3(0,12.25,0), NxVec3(2.5,1,1), 0); NxActor* box3 = CreateBox(NxVec3(7,12.25,0), NxVec3(2.5,1,1), 0); NxActor* attachedBox = CreateBox(NxVec3(-7.2,4.5,1.6), NxVec3(1.25,1,1), 1); NxActor* attachedSphere = CreateSphere(NxVec3(-0.25,4.0,2.0), 1.3, 1); NxActor* attachedCapsule = CreateCapsule(NxVec3(9.0,5.5,2.0),2.0, 1, 1); NxReal damping = 0.3; attachedBox->setAngularDamping(damping); attachedBox->setLinearDamping(damping); attachedSphere->setAngularDamping(damping); attachedSphere->setLinearDamping(damping); attachedCapsule->setAngularDamping(damping); attachedCapsule->setLinearDamping(damping); NxQuat q; q.fromAngleAxis(90,NxVec3(0,0,1)); attachedCapsule->setGlobalOrientationQuat(q); // Cloth NxClothDesc clothDesc; clothDesc.globalPose.M.rotX(1.3); clothDesc.thickness = 0.3; clothDesc.attachmentResponseCoefficient = 1; clothDesc.flags |= NX_CLF_BENDING; clothDesc.flags |= NX_CLF_BENDING_ORTHO; clothDesc.flags |= NX_CLF_DAMPING | NX_CLF_VISUALIZATION; if (gHardwareCloth) clothDesc.flags |= NX_CLF_HARDWARE; // Cloth attaching to sphere clothDesc.globalPose.t = NxVec3(0.75,5,2); MyCloth* regularCloth1 = new MyCloth(gScene, clothDesc, 2, 8, 0.4); regularCloth1->getNxCloth()->attachToCollidingShapes(NX_CLOTH_ATTACHMENT_TWOWAY); gCloths.push_back(regularCloth1); // Cloth attaching to box clothDesc.globalPose.t = NxVec3(-6.2,5,2); MyCloth* regularCloth2 = new MyCloth(gScene, clothDesc, 2, 8, 0.4); regularCloth2->getNxCloth()->attachToCollidingShapes(NX_CLOTH_ATTACHMENT_TWOWAY); gCloths.push_back(regularCloth2); // Cloth attaching to capsule clothDesc.globalPose.t = NxVec3(8.0,5,2); clothDesc.attachmentTearFactor = 2.0; MyCloth* regularCloth3 = new MyCloth(gScene, clothDesc, 2, 8, 0.4); regularCloth3->getNxCloth()->attachToShape(box3->getShapes()[0], NX_CLOTH_ATTACHMENT_TEARABLE); regularCloth3->getNxCloth()->attachToShape(attachedCapsule->getShapes()[0], NX_CLOTH_ATTACHMENT_TWOWAY); gCloths.push_back(regularCloth3); }
// Create a static trigger static void CreateTrigger(const NxVec3& pos, NxF32 size = 2, const NxVec3* initial_velocity=NULL, bool kinematic = false) { // Our trigger is a cube NxBodyDesc triggerBody; NxBoxShapeDesc dummyShape; NxBoxShapeDesc BoxDesc; BoxDesc.dimensions = NxVec3(size, size, size); BoxDesc.shapeFlags |= NX_TRIGGER_ENABLE; NxActorDesc ActorDesc; if(initial_velocity || kinematic) { if (initial_velocity) { triggerBody.linearVelocity = *initial_velocity; } if (kinematic) { triggerBody.flags |= NX_BF_KINEMATIC; } triggerBody.mass = 1; ActorDesc.body = &triggerBody; NxF32 sizeinc = 1.01f; dummyShape.dimensions.set(size*sizeinc, size*sizeinc, size*sizeinc); dummyShape.group = 1; ActorDesc.shapes.pushBack(&dummyShape); } ActorDesc.shapes.pushBack(&BoxDesc); ActorDesc.globalPose.t = pos; int thisNb = ++gNbTriggers; gNbTouchedBodies.pushBack(0); NX_ASSERT(gNbTouchedBodies.size() == gNbTriggers); gMyPhysX.getScene()->setGroupCollisionFlag(1,0, false); gMyPhysX.getScene()->setGroupCollisionFlag(1,1, false); gMyPhysX.getScene()->setGroupCollisionFlag(1,2, true); ActorDesc.userData = (void*)(-thisNb); if (!ActorDesc.isValid()) { printf("Invalid ActorDesc\n"); return; } NxActor* actor = gMyPhysX.getScene()->createActor(ActorDesc); // This is just a quick-and-dirty way to identify the trigger for rendering NX_ASSERT(actor != NULL); if (kinematic) { KinematicActor k; k.actor = actor; if (initial_velocity) { k.vel = *initial_velocity; } else { k.vel.set(0,0,0); } gKinematicActors.pushBack(k); } gMyPhysX.getScene()->setUserTriggerReport(&myTriggerCallback); }
void ReleaseNx() { if (gScene) { for (MyCloth** cloth = gCloths.begin(); cloth != gCloths.end(); cloth++) delete *cloth; gCloths.clear(); gPhysicsSDK->releaseScene(*gScene); } if (gPhysicsSDK) NxReleasePhysicsSDK(gPhysicsSDK); NX_DELETE_SINGLE(gAllocator); }
void TickCar() { NxReal steeringAngle = gSteeringValue * gMaxSteeringAngle; NxArray<CarWheelContact>::iterator i = wheelContactPoints.begin(); while(i != wheelContactPoints.end()) { CarWheelContact& cwc = *i; WheelShapeUserData* wheelData = (WheelShapeUserData *)(cwc.wheel->userData); //apply to powered wheels only. if (wheelData->frontWheel) { //steering: NxMat33 wheelOrientation = cwc.wheel->getLocalOrientation(); wheelOrientation.setColumn(0, NxVec3(NxMath::cos(steeringAngle), 0, NxMath::sin(steeringAngle) )); wheelOrientation.setColumn(2, NxVec3(NxMath::sin(steeringAngle), 0, -NxMath::cos(steeringAngle) )); cwc.wheel->setLocalOrientation(wheelOrientation); if (frontWheelIsPowered) { //get the world space orientation: wheelOrientation = cwc.wheel->getGlobalOrientation(); NxVec3 steeringDirection; wheelOrientation.getColumn(0, steeringDirection); //the power direction of the front wheel is the wheel's axis as it is steered. if (gMotorForce) { cwc.car->addForceAtPos(steeringDirection * gMotorForce,cwc.contactPoint); } } } if (!wheelData->frontWheel && rearWheelIsPowered) { //get the orientation of this car: NxMat33 m = cwc.car->getGlobalOrientation(); NxVec3 carForwardAxis; m.getColumn(0, carForwardAxis); //the power direction of the rear wheel is always the car's length axis. cwc.car->addForceAtPos(carForwardAxis * gMotorForce,cwc.contactPoint); } i++; } wheelContactPoints.clear(); }
static void CreateCube(const NxVec3& pos, int size=2, const NxVec3* initial_velocity=NULL, bool kinematic = false, bool Static = false) { // Create body NxBodyDesc BodyDesc; BodyDesc.angularDamping = 0.5f; // BodyDesc.maxAngularVelocity = 10.0f; if(initial_velocity) BodyDesc.linearVelocity = *initial_velocity; NxBoxShapeDesc BoxDesc; BoxDesc.dimensions = NxVec3(float(size), float(size), float(size)); NxActorDesc ActorDesc; // ActorDesc.userData = (void*)size; ActorDesc.shapes.pushBack(&BoxDesc); if (!Static) ActorDesc.body = &BodyDesc; ActorDesc.density = 10.0f; ActorDesc.globalPose.t = pos; ActorDesc.userData = (void*)size; NxActor* actor = gMyPhysX.getScene()->createActor(ActorDesc); if (kinematic) { KinematicActor k; k.actor = actor; actor->raiseBodyFlag(NX_BF_KINEMATIC); if (initial_velocity) { k.vel = *initial_velocity; } else { k.vel.set(0,0,0); } gKinematicActors.pushBack(k); } }
virtual void onContactNotify(NxContactPair& pair, NxU32 events) { // Iterate through contact points NxContactStreamIterator i(pair.stream); //user can call getNumPairs() here while(i.goNextPair()) { //user can also call getShape() and getNumPatches() here while(i.goNextPatch()) { //user can also call getPatchNormal() and getNumPoints() here const NxVec3& contactNormal = i.getPatchNormal(); while(i.goNextPoint()) { //user can also call getPoint() and getSeparation() here if(i.getSeparation()<0.0f) { const NxVec3& contactPoint = i.getPoint(); NxU32 faceIndex = i.getFeatureIndex0(); if(faceIndex==0xffffffff) faceIndex = i.getFeatureIndex1(); if(faceIndex!=0xffffffff) { gTouchedTris.pushBack(faceIndex); //printf("Contack!\n"); } } } } } }
void SetupTearingScene() { sprintf(gTitleString, "Tearing Demo"); // Create the objects in the scene groundPlane = CreateGroundPlane(); NxActor* bar = CreateBox(NxVec3(0,12,0), NxVec3(3,0.5,0.5), 0); NxActor* box = CreateBox(NxVec3(-2.3,4.0,0), NxVec3(0.5,0.5,0.5), 10); // Cloth NxClothDesc clothDesc; clothDesc.globalPose.t = NxVec3(2.5,12,0); clothDesc.globalPose.M.rotX(-NxHalfPiF32); clothDesc.thickness = 0.1; clothDesc.tearFactor = 2; clothDesc.flags |= NX_CLF_BENDING; clothDesc.flags |= NX_CLF_COLLISION_TWOWAY; clothDesc.flags |= NX_CLF_TEARABLE | NX_CLF_VISUALIZATION; // Tearable cloth if (gHardwareCloth) clothDesc.flags |= NX_CLF_HARDWARE; MyCloth* regularCloth = new MyCloth(gScene, clothDesc, 5, 8, 0.1, "rug512.bmp", gTearLines); gCloths.push_back(regularCloth); regularCloth->getNxCloth()->attachToShape(*bar->getShapes(), 0); regularCloth->getNxCloth()->attachToShape(*box->getShapes(), NX_CLOTH_ATTACHMENT_TWOWAY); }
static void RenderTerrain() { if(gTerrainData) { renderTerrainTriangles(*gTerrainData, gTouchedTris.size(), &gTouchedTris[0]); renderTerrain(*gTerrainData); } }
// ---------------------------------------------------------------------------------------------------------- void MeshHash::compressIndices(NxArray<int> &itemIndices) { if (itemIndices.size() == 0) return; // sort results quickSort(itemIndices, 0, itemIndices.size()-1); // mark duplicates int i = 0; while (i < (int)itemIndices.size()) { int j = i+1; while (j < (int)itemIndices.size() && itemIndices[i] == itemIndices[j]) { itemIndices[j] = -1; j++; } i = j; } // remove duplicates i = 0; while (i < (int)itemIndices.size()) { if (itemIndices[i] < 0) { itemIndices[i] = itemIndices[itemIndices.size()-1]; itemIndices.pop_back(); } else i++; } }
// ---------------------------------------------------------------------------------------------------------- void MeshHash::query(const NxVec3 &pos, NxArray<int> &itemIndices, int maxIndices) { int x,y,z; cellCoordOf(pos, x,y,z); itemIndices.clear(); int h = hashFunction(x,y,z); MeshHashRoot &r = mHashIndex[h]; if (r.timeStamp != mTime) return; int i = r.first; while (i >= 0) { MeshHashEntry &entry = mEntries[i]; itemIndices.push_back(entry.itemIndex); if (maxIndices >= 0 && (int)itemIndices.size() >= maxIndices) return; i = entry.next; } }
virtual void onContactNotify(NxContactPair& pair, NxU32 events) { NxU32 carIndex = 0; if (isCar(pair.actors[0])) carIndex = 0; else if (isCar(pair.actors[1])) carIndex = 1; else return; //ignore the 'both are cars' case for now. // Iterate through contact points NxContactStreamIterator i(pair.stream); //user can call getNumPairs() here while (i.goNextPair()) { //user can also call getShape() and getNumPatches() here NxShape * s = i.getShape(carIndex); while (i.goNextPatch()) { //user can also call getPatchNormal() and getNumPoints() here const NxVec3& contactNormal = i.getPatchNormal(); while (i.goNextPoint()) { //user can also call getPoint() and getSeparation() here const NxVec3& contactPoint = i.getPoint(); NxVec3 contactNormalForce = pair.sumNormalForce; NxVec3 contactFrictionForce = pair.sumFrictionForce; //add forces: //assuming front wheel drive we need to apply a force at the wheels. if (s->is(NX_SHAPE_CAPSULE)) //assuming only the wheels of the car are capsules, otherwise we need more checks. //this branch can't be pulled out of loops because we have to do a full iteration through the stream { CarWheelContact cwc; cwc.car = pair.actors[carIndex]; cwc.wheel = s; cwc.contactPoint = contactPoint; cwc.contactNormalForce = contactNormalForce; cwc.contactFrictionForce = contactFrictionForce; wheelContactPoints.pushBack(cwc); //#error too bad this is illegal (reentry) and also technically busted because the accumulators get zeroed after this returns. //pair.actors[carIndex]->addForceAtPos(NxVec3(100,0,0),contactPoint); } } } } }
void RenderCallback() { if (gScene && !bPause) { StartPhysics(); GetPhysicsResults(); } // Clear buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ProcessInputs(); ProcessCameraKeys(); SetupCamera(); RenderActors(bShadows); // Render all the cloths in the scene for (MyCloth **cloth = gCloths.begin(); cloth != gCloths.end(); cloth++) { glColor4f(1.0f, 0.0f, 0.0f,1.0f); (*cloth)->draw(bShadows); } if (bForceMode) DrawForce(gSelectedActor, gForceVec, NxVec3(1,1,0)); else DrawForce(gSelectedActor, gForceVec, NxVec3(0,1,1)); gForceVec = NxVec3(0,0,0); // Render HUD hud.Render(); glFlush(); glutSwapBuffers(); }
void render() { static Timer t; if(gScene && !gPauseSimulation) //start the simulation { gTouchedTris.clear(); gScene->simulate(t.elapsed_time()); //printf("%f\n",t.elapsed_time()); t.reset(); gScene->flushStream(); /*ASYNC: in here we can do computations which depend only on the old state of the scene "actors". Writing to the scene is not allowed. Write calls in here are skipped. */ gScene->fetchResults(NX_RIGID_BODY_FINISHED,true); } // Clear buffers glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glColor4f(0.0,1.0,1.0,1.0); DrawSkyBox(5000.0f); //drawPlane(2000.0); //Render all actors int nbActors = gScene->getNbActors(); NxActor** actors = gScene->getActors(); while(nbActors--) { NxActor* actor = *actors++; if(!actor->userData) continue; // Render actor glPushMatrix(); float glMat[16]; actor->getGlobalPose().getColumnMajor44(glMat); glMultMatrixf(glMat); NxVec3 color = static_cast<UserData*>(actor->userData)->color; glColor4f(color.x,color.y,color.z,1.0f); glutSolidCube((static_cast<UserData*>(actor->userData)->size)*2.0f); glPopMatrix(); } RenderTerrain(); }
void SetHelpString(const char *demoKeyString) { char tempString[512]; sprintf(gHelpString, "\nGeneral:\n"); #ifdef __PPCGEKKO__ sprintf(gHelpString, " +,-: choose scene\n"); strcat(gHelpString, " arrows: move/strafe\n"); strcat(gHelpString, " b: shoot sphere\n"); strcat(gHelpString, " HOME: toggle help\n"); strcat(gHelpString, " 1: Reset scene\n"); if(gSampleIndex == 6) strcat(gHelpString, " 2: toggle debug rendering\n"); #else sprintf(tempString, " 1-%d: choose scene\n", gSamples.size()); strcat(gHelpString, tempString); strcat(gHelpString, " p: pause\n"); strcat(gHelpString, " o: single step\n"); #ifndef NX_DISABLE_HARDWARE strcat(gHelpString, " h: hardware on/off\n"); #endif strcat(gHelpString, " w,a,s,d: move/strafe\n"); strcat(gHelpString, " q,e: move up/down\n"); strcat(gHelpString, " mouse right: pick\n"); strcat(gHelpString, " space: shoot sphere\n"); strcat(gHelpString, " x: toggle shadows\n"); strcat(gHelpString, " n: toggle wireframe\n"); strcat(gHelpString, " F1: toggle help\n"); strcat(gHelpString, " F3,F4: pick push/pull\n"); strcat(gHelpString, " F5: toggle debug rendering\n"); strcat(gHelpString, " F9: toggle vsync\n"); strcat(gHelpString, " F10: Reset scene\n"); #endif if (demoKeyString) { strcat(gHelpString, "\nDemo specific:\n"); strcat(gHelpString, demoKeyString); } }
bool NxuPhysicsExport::Write(NxJoint *j,const char *userProperties,const char *id) { bool ret = false; NxSceneDesc *current = getCurrentScene(); CustomCopy cc(mCollection,current); NxJointDesc *joint = 0; switch ( j->getType() ) { case NX_JOINT_PRISMATIC: if ( 1 ) { ::NxPrismaticJointDesc d1; NxPrismaticJoint *sj = j->isPrismaticJoint(); sj->saveToDesc(d1); addActor( d1.actor[0] ); addActor( d1.actor[1] ); NxPrismaticJointDesc *desc = new NxPrismaticJointDesc; desc->copyFrom(d1,cc); joint = static_cast<NxJointDesc *>(desc); } break; case NX_JOINT_REVOLUTE: if ( 1 ) { ::NxRevoluteJointDesc d1; NxRevoluteJoint *sj = j->isRevoluteJoint(); sj->saveToDesc(d1); addActor( d1.actor[0] ); addActor( d1.actor[1] ); NxRevoluteJointDesc *desc = new NxRevoluteJointDesc; desc->copyFrom(d1,cc); joint = static_cast<NxJointDesc *>(desc); } break; case NX_JOINT_CYLINDRICAL: if ( 1 ) { ::NxCylindricalJointDesc d1; NxCylindricalJoint *sj = j->isCylindricalJoint(); sj->saveToDesc(d1); addActor( d1.actor[0] ); addActor( d1.actor[1] ); NxCylindricalJointDesc *desc = new NxCylindricalJointDesc; desc->copyFrom(d1,cc); joint = static_cast<NxJointDesc *>(desc); } break; case NX_JOINT_SPHERICAL: if ( 1 ) { ::NxSphericalJointDesc d1; NxSphericalJoint *sj = j->isSphericalJoint(); sj->saveToDesc(d1); addActor( d1.actor[0] ); addActor( d1.actor[1] ); NxSphericalJointDesc *desc = new NxSphericalJointDesc; desc->copyFrom(d1,cc); joint = static_cast<NxJointDesc *>(desc); } break; case NX_JOINT_POINT_ON_LINE: if ( 1 ) { ::NxPointOnLineJointDesc d1; NxPointOnLineJoint *sj = j->isPointOnLineJoint(); sj->saveToDesc(d1); addActor( d1.actor[0] ); addActor( d1.actor[1] ); NxPointOnLineJointDesc *desc = new NxPointOnLineJointDesc; desc->copyFrom(d1,cc); joint = static_cast<NxJointDesc *>(desc); } break; case NX_JOINT_POINT_IN_PLANE: if ( 1 ) { ::NxPointInPlaneJointDesc d1; NxPointInPlaneJoint *sj = j->isPointInPlaneJoint(); sj->saveToDesc(d1); addActor( d1.actor[0] ); addActor( d1.actor[1] ); NxPointInPlaneJointDesc *desc = new NxPointInPlaneJointDesc; desc->copyFrom(d1,cc); joint = static_cast<NxJointDesc *>(desc); } break; case NX_JOINT_DISTANCE: if ( 1 ) { ::NxDistanceJointDesc d1; NxDistanceJoint *sj = j->isDistanceJoint(); sj->saveToDesc(d1); addActor( d1.actor[0] ); addActor( d1.actor[1] ); NxDistanceJointDesc *desc = new NxDistanceJointDesc; desc->copyFrom(d1,cc); joint = static_cast<NxJointDesc *>(desc); } break; case NX_JOINT_PULLEY: if ( 1 ) { ::NxPulleyJointDesc d1; NxPulleyJoint *sj = j->isPulleyJoint(); sj->saveToDesc(d1); addActor( d1.actor[0] ); addActor( d1.actor[1] ); NxPulleyJointDesc *desc = new NxPulleyJointDesc; desc->copyFrom(d1,cc); joint = static_cast<NxJointDesc *>(desc); } break; case NX_JOINT_FIXED: if ( 1 ) { ::NxFixedJointDesc d1; NxFixedJoint *sj = j->isFixedJoint(); sj->saveToDesc(d1); addActor( d1.actor[0] ); addActor( d1.actor[1] ); NxFixedJointDesc *desc = new NxFixedJointDesc; desc->copyFrom(d1,cc); joint = static_cast<NxJointDesc *>(desc); } break; case NX_JOINT_D6: if ( 1 ) { ::NxD6JointDesc d1; NxD6Joint *sj = j->isD6Joint(); sj->saveToDesc(d1); addActor( d1.actor[0] ); addActor( d1.actor[1] ); NxD6JointDesc *desc = new NxD6JointDesc; desc->copyFrom(d1,cc); joint = static_cast<NxJointDesc *>(desc); } break; default: break; } //Add Limits // in addition, we also have to write out its limit planes! j->resetLimitPlaneIterator(); if (j->hasMoreLimitPlanes()) { // write limit point joint->mOnActor2 = j->getLimitPoint(joint->mPlaneLimitPoint); NxArray< NxPlaneInfoDesc *> plist; // write the plane normals while (j->hasMoreLimitPlanes()) { NxPlaneInfoDesc *pInfo = new NxPlaneInfoDesc(); #if NX_SDK_VERSION_NUMBER >= 272 j->getNextLimitPlane(pInfo->mPlaneNormal, pInfo->mPlaneD, &pInfo->restitution); #else j->getNextLimitPlane(pInfo->mPlaneNormal, pInfo->mPlaneD); #endif plist.push_back(pInfo); } if ( plist.size() ) { for (int i=plist.size()-1; i>=0; i--) { NxPlaneInfoDesc *p = plist[i]; joint->mPlaneInfo.pushBack(p); } } } if ( joint ) { if ( id ) { joint->mId = id; } else { char scratch[512]; sprintf(scratch,"Joint_%d", current->mJoints.size()); joint->mId = getGlobalString(scratch); joint->mUserProperties = getGlobalString(userProperties); } current->mJoints.push_back(joint); ret = true; } return ret; }
// ----------------------------------------------------------------------- void VertexWelder::initialize(const NxClothMeshDesc& unweldedMesh) { NxArray<NxU32> mapping; NxReal squaredEpsilon = mEpsilon * mEpsilon; for (NxU32 i = 0; i < unweldedMesh.numVertices; i++) { const NxVec3& curVec = *(const NxVec3*)(((const char*)unweldedMesh.points) + (i * unweldedMesh.pointStrideBytes)); // Find Vertex in newVertices NxU32 newIndex = 0; for (newIndex = 0; newIndex < mNewVertices.size(); newIndex++) { NxVec3& newVec = mNewVertices[newIndex]; if ((mEpsilon == 0 && newVec == curVec) || (newVec.distanceSquared(curVec) < squaredEpsilon)) //if (newVec == curVec) { break; } } if (newIndex == mNewVertices.size()) { // Not found in previous list mNewVertices.push_back(curVec); } mapping.push_back(newIndex); } // Store mapping mMappingSize = mapping.size(); mMappingSpace = unweldedMesh.numTriangles * 3; mMappingDomain = mNewVertices.size(); mMapping = (NxU32*)malloc(sizeof(NxU32) * mMappingSpace); memcpy(mMapping, &mapping[0], sizeof(NxU32) * mMappingSize); memset(((NxU32*)mMapping) + mMappingSize, 0, sizeof(NxU32) * (mMappingSpace - mMappingSize)); mapping.clear(); if (mNewVertices.size() < unweldedMesh.numVertices) { mUsed = true; } else { return; } if (unweldedMesh.flags & NX_MF_16_BIT_INDICES) { mNewFaces16 = (NxU16*)malloc(sizeof(NxU16) * unweldedMesh.numTriangles * 3); } else { mNewFaces32 = (NxU32*)malloc(sizeof(NxU32) * unweldedMesh.numTriangles * 3); } for (NxU32 i = 0; i < unweldedMesh.numTriangles; i++) { NxU32 triangles[3]; const char* triangleChar = ((const char*)unweldedMesh.triangles) + (unweldedMesh.triangleStrideBytes * i); if (mNewFaces16) { const NxU16* tris = (const NxU16*)triangleChar; triangles[0] = tris[0]; triangles[1] = tris[1]; triangles[2] = tris[2]; } else { assert(mNewFaces32 != NULL); const NxU32* tris = (const NxU32*)triangleChar; triangles[0] = tris[0]; triangles[1] = tris[1]; triangles[2] = tris[2]; } for (NxU32 j = 0; j < 3; j++) { triangles[j] = getMapping(triangles[j]); } if (mNewFaces16) { for (NxU32 j = 0; j < 3; j++) { mNewFaces16[3*i+j] = (NxU16)(triangles[j] & 0xffff); } } else { for (NxU32 j = 0; j < 3; j++) { mNewFaces32[3*i+j] = triangles[j]; } } } }
void VertexWelder::update(NxMeshData meshData) { assert(mWriteVerticesPtr != NULL); bool updateVertices = (*(meshData.dirtyBufferFlagsPtr) & (NX_MDF_VERTICES_POS_DIRTY | NX_MDF_VERTICES_NORMAL_DIRTY)) > 0; bool updateIndices = (*(meshData.dirtyBufferFlagsPtr) & (NX_MDF_INDICES_DIRTY | NX_MDF_PARENT_INDICES_DIRTY)) > 0; NxU32 numNewVertices = *meshData.numVerticesPtr; NxU32 numTriangles = *meshData.numIndicesPtr / 3; NxU32 oldMappingDomain = mMappingDomain; NxArray<NewVertex> newVertices; NxArray<DifficultVertex> difficultVertices; mMappingDomainAddition = 0; if (updateVertices) { if (mMappingDomain < numNewVertices) { #ifdef DEBUG_WELDER printf("------------------------------------\n"); #endif for (NxU32 i = mMappingDomain; i < numNewVertices; i++) { NewVertex v; v.index = i; v.parent = *(NxU32*)(((char*)meshData.parentIndicesBegin) + meshData.parentIndicesByteStride * i); while (v.parent >= (NxI32)mMappingDomain) { v.parent = *(NxU32*)(((char*)meshData.parentIndicesBegin) + meshData.parentIndicesByteStride * v.parent); } #ifdef DEBUG_WELDER printf("New Vertex: %d %d\n", v.index, v.parent); #endif newVertices.push_back(v); } std::sort(newVertices.begin(), newVertices.end(), sortParent); } for (NxU32 i = 0; i < mMappingSize; i++) { NxU32 mappedIndex = getMapping(i); NewVertex newV; newV.parent = mappedIndex; // Find all vertices that are a parent for a newly created vertex NxArray<NewVertex>::iterator found = std::lower_bound(newVertices.begin(), newVertices.end(), newV, sortParent); while (found != NULL && found->parent == mappedIndex) { found->mappedVertices ++; if (found->mappedVertices == 1) { found->unMapParent = i; #ifdef DEBUG_WELDER printf("New Vertex Update, %d %d %d\n", found->index, found->parent, found->unMapParent); #endif } else { // several unmapped parents DifficultVertex v; v.mappedIndex = found->index; v.unMappedIndex = i; difficultVertices.push_back(v); #ifdef DEBUG_WELDER printf("Difficult Vertex %d %d\n", v.unMappedIndex, v.mappedIndex); #endif if (found->mappedVertices == 2) { v.unMappedIndex = found->unMapParent; difficultVertices.push_back(v); #ifdef DEBUG_WELDER printf("Difficult Vertex %d %d\n", v.unMappedIndex, v.mappedIndex); #endif } found->unMapParent = -2; } found++; } NxVec3& vertex = *(NxVec3*)(((char*)mWriteVerticesPtr) + mWriteVerticesStride * i); NxVec3& normal = *(NxVec3*)(((char*)mWriteNormalsPtr) + mWriteNormalsStride* i); //float* texCoord = (float*)(((char*)texCoords) + texStride * i); const NxVec3& oldVertex = *(NxVec3*)(((char*)meshData.verticesPosBegin) + meshData.verticesPosByteStride * mappedIndex); const NxVec3& oldNormal = *(NxVec3*)(((char*)meshData.verticesNormalBegin) + meshData.verticesNormalByteStride * mappedIndex); vertex = oldVertex; normal = oldNormal; } // Adapt the mapping table std::sort(newVertices.begin(), newVertices.end(), sortIndex); std::sort(difficultVertices.begin(), difficultVertices.end(), sortDifficultExt); } if (updateIndices) { std::vector<bool> bitVector(mMappingSpace, false); #ifdef DEBUG_WELDER printf("updateIndices: Vertices: %d, Indices %d, gfx Vertices: %d\n", *meshData.numVerticesPtr, *meshData.numIndicesPtr, mMappingSize); #endif if (difficultVertices.size() > 0) { #ifdef DEBUG_WELDER printf(" Difficult Vertices:\n"); #endif for (NxU32 i = 0; i < difficultVertices.size(); i++) { DifficultVertex& v = difficultVertices[i]; #ifdef DEBUG_WELDER printf(" V %d %d\n", v.unMappedIndex, v.mappedIndex); #endif } } assert((meshData.flags & NX_MF_16_BIT_INDICES) == 0); assert(meshData.indicesByteStride == 4); for (NxU32 i = 0; i < numTriangles; i++) { const NxU32* simTriangle = (NxU32*)(((char*)meshData.indicesBegin) + meshData.indicesByteStride * (i*3)); NxU32* gfxTriangle = (NxU32*)(((char*)mWriteIndicesPtr) + mWriteIndicesStride* i); if (simTriangle[0] == simTriangle[1] && simTriangle[1] == simTriangle[2]) { // Face was deleted (outside valid bounds probably) gfxTriangle[0] = gfxTriangle[1] = gfxTriangle[2] = 0; continue; } for (NxU32 j = 0; j < 3; j++) { DifficultVertex v; v.mappedIndex = simTriangle[j]; v.unMappedIndex = gfxTriangle[j]; if (std::binary_search(difficultVertices.begin(), difficultVertices.end(), v, sortDifficult)) { NxArray<DifficultVertex>::iterator it = std::lower_bound(difficultVertices.begin(), difficultVertices.end(), v, sortDifficultExt); #ifdef DEBUG_WELDER printf("-- Triangle %d (%d) (%d %d %d) (%d %d %d)", i, j, simTriangle[0], simTriangle[1], simTriangle[2], gfxTriangle[0], gfxTriangle[1], gfxTriangle[2]); printf(" %d %d\n", v.unMappedIndex, v.mappedIndex); #endif if (it == NULL || it->mappedIndex != simTriangle[j]) { // element hasn't been found //insert element #ifdef DEBUG_WELDER printf("Adding Diff %d %d\n", v.unMappedIndex, v.mappedIndex); #endif difficultVertices.push_back(v); // sort now, don't know whether this could be done less often, so far the list is extremely small std::sort(difficultVertices.begin(), difficultVertices.end(), sortDifficultExt); // get the freshly created item it = std::lower_bound(difficultVertices.begin(), difficultVertices.end(), v, sortDifficultExt); // element has to exist assert(it != NULL); } if (it->newUnMappedIndex >= 0) { gfxTriangle[j] = it->newUnMappedIndex; } else if (bitVector[it->unMappedIndex]) { #ifdef DEBUG_WELDER printf("Bit %d is true\n", it->unMappedIndex); #endif // create a new gfx vertex it->newUnMappedIndex = mMappingSize; addNewVertex(gfxTriangle[j]); setMapping(it->newUnMappedIndex, simTriangle[j]); gfxTriangle[j] = it->newUnMappedIndex; bitVector[it->newUnMappedIndex] = true; } else { #ifdef DEBUG_WELDER printf("Set Bit %d to true\n", it->unMappedIndex); #endif bitVector[it->unMappedIndex] = true; it->newUnMappedIndex = it->unMappedIndex; setMapping(it->newUnMappedIndex, simTriangle[j]); } } else if (simTriangle[j] >= oldMappingDomain) // only used when not a difficult vertex { // unamp index and update for (NxU32 k = 0; k < newVertices.size(); k++) { NewVertex& v = newVertices[k]; if (v.index == simTriangle[j] && v.mappedVertices == 1) { #ifdef DEBUG_WELDER printf("- Triangle %d (%d %d %d) (%d %d %d)", i, simTriangle[0], simTriangle[1], simTriangle[2], gfxTriangle[0], gfxTriangle[1], gfxTriangle[2]); printf(" %d %d\n", v.unMapIndex, v.index); #endif if (v.unMapIndex == -1) { #ifdef DEBUG_WELDER printf("Add Simple\n"); #endif v.unMapIndex = mMappingSize; //addNewVertex(vertices, vertexStride, normals, normalStride, texCoords, texStride, v.unMapParent); addNewVertex(gfxTriangle[j]); gfxTriangle[j] = v.unMapIndex; setMapping(v.unMapIndex, v.index); } else { #ifdef DEBUG_WELDER printf("Use Simple\n"); #endif gfxTriangle[j] = v.unMapIndex; } break; // for (k) } } } } } } if (updateVertices) { mMappingDomain = *meshData.numVerticesPtr; #ifdef DEBUG_WELDER static bool sanityCheck = true; if (sanityCheck) { // sanity check NxU32 temp = 0; for (NxU32 i = 0; i < mMappingSize; i++) { temp = NxMath::max(getMapping(i), temp); } if (temp != mMappingDomain - 1) { printf("Mapping Domain not right, is %d, should be %d\n", temp, mMappingDomain-1); assert(0); } for (NxU32 i = 0; i < numTriangles; i++) { const NxU32* simTriangle = (NxU32*)(((char*)meshData.indicesBegin) + meshData.indicesByteStride * (i*3)); NxU32* gfxTriangle = (NxU32*)(((char*)mWriteIndicesPtr) + mWriteIndicesStride * i); for (NxU32 j = 0; j < 3; j++) { if (simTriangle[j] != getMapping(gfxTriangle[j])) { printf("Triangle %d (%d) not correct (%d %d %d) -> (%d %d %d) != (%d %d %d)\n", i, 3*i+j, gfxTriangle[0], gfxTriangle[1], gfxTriangle[2], getMapping(gfxTriangle[0]), getMapping(gfxTriangle[1]), getMapping(gfxTriangle[2]), simTriangle[0], simTriangle[1], simTriangle[2]); assert(0); } } } } #endif } return; }
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(); } } } }
// 增加一辆车 NxVehicle* NxAllVehicle::addVehicle(const NxVec3& pos, VehicleInfo vinfo, std::string name, NxScene* nxScene, NxPhysicsSDK* nxPhysics) { NxVehicleDesc vehicleDesc; NxBoxShapeDesc boxShapes[2]; NxConvexShapeDesc carShape[2]; NxArray<NxVec3> points; NxArray<NxVec3> points2; NxReal halfWidth = vinfo.width / 2;//1.1529f; NxReal halfLength = vinfo.length / 2;//2.5278f; NxReal halfHeight = vinfo.height / 2; //0.6027; points.pushBack().set(halfLength,-halfHeight * 0.1f, 0); points.pushBack().set(halfLength * 0.7f, 0, 0); points.pushBack().set(0.2f * halfLength, halfHeight * 0.2f, 0); points.pushBack().set(-halfLength, halfHeight * 0.2f, 0); points.pushBack().set(0.1*halfLength, halfHeight * 0.2f, halfWidth * 0.9f); points.pushBack().set(0.1*halfLength, halfHeight * 0.2f,-halfWidth * 0.9f); points.pushBack().set(-0.8*halfLength, halfHeight * 0.2f, halfWidth * 0.9f); points.pushBack().set(-0.8*halfLength, halfHeight * 0.2f,-halfWidth * 0.9f); points.pushBack().set(halfLength * 0.9f,-halfHeight * 0.25f, halfWidth * 0.8f); points.pushBack().set(halfLength * 0.9f,-halfHeight * 0.25f,-halfWidth * 0.8f); points.pushBack().set(0,-halfHeight * 0.2f, halfWidth); points.pushBack().set(0,-halfHeight * 0.2f,-halfWidth); points.pushBack().set(-halfLength * 0.9f,-halfHeight * 0.2f, halfWidth * 0.9f); points.pushBack().set(-halfLength * 0.9f,-halfHeight * 0.2f,-halfWidth * 0.9f); points.pushBack().set(halfLength * 0.8f, -halfHeight, halfWidth * 0.79f); points.pushBack().set(halfLength * 0.8f, -halfHeight,-halfWidth * 0.79f); points.pushBack().set(-halfLength * 0.8f, -halfHeight, halfWidth * 0.79f); points.pushBack().set(-halfLength * 0.8f, -halfHeight,-halfWidth * 0.79f); for(NxU32 i = 2; i < 8; i++) { points2.pushBack(points[i]); } points2.pushBack().set(-0.5*halfLength, halfHeight*0.8f, halfWidth*0.7f); points2.pushBack().set(-0.5*halfLength, halfHeight*0.8f,-halfWidth*0.7f); points2.pushBack().set(-0.7*halfLength, halfHeight*0.7f, halfWidth*0.7f); points2.pushBack().set(-0.7*halfLength, halfHeight*0.7f,-halfWidth*0.7f); static NxConvexMeshDesc convexMesh; convexMesh.numVertices = points.size(); convexMesh.points = &(points[0].x); convexMesh.pointStrideBytes = sizeof(NxVec3); convexMesh.flags |= NX_CF_COMPUTE_CONVEX|NX_CF_USE_LEGACY_COOKER; MemoryWriteBuffer buf; bool status = NxCookConvexMesh(convexMesh, buf); if(status) { carShape[0].meshData = nxPhysics->createConvexMesh(MemoryReadBuffer(buf.data)); vehicleDesc.carShapes.pushBack(&carShape[0]); } static NxConvexMeshDesc convexMesh2; convexMesh2.numVertices = points2.size(); convexMesh2.points = (&points2[0].x); convexMesh2.pointStrideBytes = sizeof(NxVec3); convexMesh2.flags = NX_CF_COMPUTE_CONVEX|NX_CF_USE_LEGACY_COOKER; MemoryWriteBuffer buf2; status = NxCookConvexMesh(convexMesh2, buf2); if(status) { carShape[1].meshData = nxPhysics->createConvexMesh(MemoryReadBuffer(buf2.data)); vehicleDesc.carShapes.pushBack(&carShape[1]); } vehicleDesc.position = pos; vehicleDesc.mass = vinfo.mass;//1200;//monsterTruck ? 12000 : vehicleDesc.digitalSteeringDelta = vinfo.steerablity;//0.04f; vehicleDesc.steeringMaxAngle = vinfo.maxSteeringAngle; //30.f; vehicleDesc.motorForce = vinfo.maxAcceleraion * vinfo.mass;//3500.f;//monsterTruck?180.f: NxVehicleMotorDesc motorDesc; NxVehicleGearDesc gearDesc; NxReal wheelRadius = 0.4f; vehicleDesc.maxVelocity = vinfo.maxVelocity; //80.f;//(monsterTruck)?40.f:80.f; motorDesc.setToCorvette(); vehicleDesc.motorDesc = &motorDesc; gearDesc.setToCorvette(); vehicleDesc.gearDesc = &gearDesc; vehicleDesc.differentialRatio = 3.42f; wheelRadius = 0.3622f; vehicleDesc.centerOfMass.set(0,-0.7f,0); NxWheelDesc wheelDesc[4]; for(NxU32 i=0;i<4;i++) { wheelDesc[i].wheelApproximation = 10; //wheelDesc[i].wheelFlags |= NX_WF_BUILD_LOWER_HALF; wheelDesc[i].wheelRadius = wheelRadius;//(monsterTruck)?wheelRadius*3.f:wheelRadius; wheelDesc[i].wheelWidth = 0.1923f;//(monsterTruck)?0.3f:0.1923f; wheelDesc[i].wheelSuspension = 0.2f;//(monsterTruck)?0.6f:0.2f; wheelDesc[i].springRestitution = 7000;//monsterTruck?(crovette?5000:4000):7000; wheelDesc[i].springDamping = 800; wheelDesc[i].springBias = 0.0f; // 设为1.0后居然会出错!!!!!!!! //wheelDesc[i].maxHandBraking = 1.f; //monsterTruck?0.5f:1.f; wheelDesc[i].inverseWheelMass = 4.0f / vinfo.maxAcceleraion; // 换算成动力 wheelDesc[i].frictionToFront = 1.f; wheelDesc[i].frictionToSide = 2.f; vehicleDesc.carWheels.pushBack(&wheelDesc[i]); } NxReal heightPos = -0.3622f; //(monsterTruck)?1.f: wheelDesc[0].position.set( 1.02f, heightPos, 1.26); wheelDesc[1].position.set( 1.12f, heightPos,-1.54); wheelDesc[2].position.set(-1.02f, heightPos, 1.26); wheelDesc[3].position.set(-1.12f, heightPos,-1.54); NxU32 flags = NX_WF_BUILD_LOWER_HALF; wheelDesc[0].wheelFlags |= ((vinfo.driven==FrontDriven)?NX_WF_ACCELERATED:0) | NX_WF_STEERABLE_INPUT | flags; wheelDesc[1].wheelFlags |= ((vinfo.driven==FrontDriven)?NX_WF_ACCELERATED:0) | NX_WF_STEERABLE_INPUT | flags; wheelDesc[2].wheelFlags |= ((vinfo.driven==BackDriven)?NX_WF_ACCELERATED:0) | NX_WF_AFFECTED_BY_HANDBRAKE | flags; wheelDesc[3].wheelFlags |= ((vinfo.driven==BackDriven)?NX_WF_ACCELERATED:0) | NX_WF_AFFECTED_BY_HANDBRAKE | flags; vehicleDesc.steeringSteerPoint.set(1.8, 0, 0); vehicleDesc.steeringTurnPoint.set(-1.5, 0, 0); NxVehicle* vehicle = NxVehicle::createVehicle(nxScene, &vehicleDesc, name); NxQuat q; // 少转过90度,可能会有问题 q.fromAngleAxis(90.0f, NxVec3(0.0f, 1.0f, 0.0f)); vehicle->getActor()->setGlobalOrientationQuat(q); vehicle->mVInfo = vinfo; vehicle->setOilAmount(vinfo.oilAmount); // 加到队列中 mAllVehicle.pushBack(vehicle); mIsLive.pushBack(0); // miUserVehicle = mAllVehicle.size() - 1; return vehicle; }
void TickCar ( void ) { g_iValue = 10; NxReal steeringAngle = gSteeringValue * gMaxSteeringAngle; NxArray<CarWheelContact>::iterator i = wheelContactPoints.begin(); while(i != wheelContactPoints.end()) { CarWheelContact& cwc = *i; WheelShapeUserData* wheelData = (WheelShapeUserData *)(cwc.wheel->userData); /* struct CarWheelContact { NxActor* car; NxShape* wheel; NxVec3 contactPoint; NxVec3 contactNormalForce; NxVec3 contactFrictionForce; }; */ { NxMat34 pose = cwc.wheel->getGlobalPose ( ); NxMat33 orient = pose.M; NxVec3 pos = pose.t; float glmat[16]; orient.getColumnMajorStride4(&(glmat[0])); pos.get(&(glmat[12])); glmat[3] = glmat[7] = glmat[11] = 0.0f; glmat[15] = 1.0f; SetWorldMatrix ( g_iValue, ( D3DXMATRIX* ) &glmat ); sObject* pObject = dbGetObject ( g_iValue ); pObject->position.vecPosition = D3DXVECTOR3 ( glmat [ 12 ], glmat [ 13 ], glmat [ 14 ] ); //dbPositionObject ( g_iValue, glmat [ 12 ], glmat [ 13 ], glmat [ 14 ] ); g_iValue++; } //apply to powered wheels only. if (wheelData->frontWheel) { //steering: NxMat33 wheelOrientation = cwc.wheel->getLocalOrientation(); wheelOrientation.setColumn(0, NxVec3(NxMath::cos(steeringAngle), 0, NxMath::sin(steeringAngle) )); wheelOrientation.setColumn(2, NxVec3(NxMath::sin(steeringAngle), 0, -NxMath::cos(steeringAngle) )); cwc.wheel->setLocalOrientation(wheelOrientation); if (frontWheelIsPowered) { //get the world space orientation: wheelOrientation = cwc.wheel->getGlobalOrientation(); NxVec3 steeringDirection; wheelOrientation.getColumn(0, steeringDirection); //the power direction of the front wheel is the wheel's axis as it is steered. if (gMotorForce) { cwc.car->addForceAtPos(steeringDirection * gMotorForce,cwc.contactPoint); } } } if (!wheelData->frontWheel && rearWheelIsPowered) { //get the orientation of this car: NxMat33 m = cwc.car->getGlobalOrientation(); NxVec3 carForwardAxis; m.getColumn(0, carForwardAxis); //the power direction of the rear wheel is always the car's length axis. cwc.car->addForceAtPos(carForwardAxis * gMotorForce,cwc.contactPoint); } i++; } wheelContactPoints.clear(); }
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(); }