/** * Method is used to add new dynamic actor to physics scene. * @param entity is pointer to scene entity which will be added to physics simulation. * @param type is enumeration of shape type. * @param filterGroup is actor own id. * @param filterMask is mask to filter pairs that trigger a contact callback. */ void PhysicsManager::addDynamicActor(SceneEntity* entity, ShapeType type, PxU32 filterGroup, PxU32 filterMask) { PxRigidDynamic* actor = nullptr; PxVec3 position = PxVec3(entity->entityState.position[0],entity->entityState.position[1],entity->entityState.position[2]); PxQuat orientation = PxQuat(entity->entityState.orientation[0],entity->entityState.orientation[1],entity->entityState.orientation[2],entity->entityState.orientation[3]); PxReal density = 1.0f; PxTransform transformation = PxTransform(position,orientation); if(type == BOX) { float x = (entity->entityGeometry.geometryBox->max.x() - entity->entityGeometry.geometryBox->min.x())*entity->entityState.scale.x()*0.5f; float y = (entity->entityGeometry.geometryBox->max.y() - entity->entityGeometry.geometryBox->min.y())*entity->entityState.scale.y()*0.5f; float z = (entity->entityGeometry.geometryBox->max.z() - entity->entityGeometry.geometryBox->min.z())*entity->entityState.scale.z()*0.5f; PxVec3 dimensions(x,y,z); actor = PxCreateDynamic(*physicsSDK,transformation,PxBoxGeometry(dimensions),*materials[0].second,density); PxRigidBodyExt::updateMassAndInertia(*actor, density); } else if(type == SPHERE) { float radius = entity->entityGeometry.geometrySphere->sphereRadius; actor = PxCreateDynamic(*physicsSDK,transformation,PxSphereGeometry(radius),*materials[0].second,density); } else if(type == CAPSULE) { float radius = entity->entityGeometry.geometrySphere->sphereRadius; actor = PxCreateDynamic(*physicsSDK,transformation,PxCapsuleGeometry(radius/2, radius),*materials[0].second,density); } else if(type == CONVEX) { /*int vertsCount = entity->entityGeometry.geometryMesh->getVerticesAmount(); AyumiUtils::Vertex<>* verts = entity->entityGeometry.geometryMesh->getVertices(); PxVec3* convexVerts = new PxVec3[vertsCount]; for(int i = 0; i < vertsCount; ++i) convexVerts[i] = PxVec3(verts[i].x,verts[i].y,verts[i].z); PxConvexMeshDesc convexDesc; convexDesc.points.count = entity->entityGeometry.geometryMesh->getVerticesAmount(); convexDesc.points.stride = sizeof(PxVec3); convexDesc.points.data = convexVerts; convexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX; MemoryWriteBuffer buf; if(cooking->cookConvexMesh(convexDesc, buf)) { PxConvexMesh* convexMesh = physicsSDK->createConvexMesh(MemoryReadBuffer(buf.data)); actor = PxCreateDynamic(*physicsSDK,transformation,PxConvexMeshGeometry(convexMesh,PxMeshScale()),*materials[0].second,density); } else { Logger::getInstance()->saveLog(Log<string>("Convex Mesh creation error occurred!")); return; }*/ //delete[] convexVerts; } else { Logger::getInstance()->saveLog(Log<string>("Dynamic Actor shape creation error occurred!")); return; } if(!actor) Logger::getInstance()->saveLog(Log<string>("Static Actor creation error occurred!")); PxRigidBodyExt::updateMassAndInertia(*actor, density); actor->setAngularDamping(0.75); actor->setLinearVelocity(PxVec3(0,0,0)); actor->setName(entity->entityName.c_str()); setupFiltering(actor,filterGroup,filterMask); scene->addActor(*actor); DynamicActor* d = new DynamicActor(); d->entityLogic = entity; d->entityPhysics = actor; d->shapesAmount = actor->getNbShapes(); d->shapes = new PxShape*[d->shapesAmount]; dynamicActors.push_back(d); }
void SampleParticles::Raygun::update(float dtime) { if(!isEnabled()) return; PX_ASSERT(mSample && mForceSmokeCapsule && mForceWaterCapsule && mRenderActor); // access properties from sample PxScene& scene = mSample->getActiveScene(); PxVec3 position = mSample->getCamera().getPos(); PxTransform cameraPose = mSample->getCamera().getViewMatrix(); PxMat33 cameraBase(cameraPose.q); PxVec3 cameraForward = -cameraBase[2]; PxVec3 cameraUp = -cameraBase[1]; // perform raycast here and update impact point PxRaycastHit hit; mIsImpacting = scene.raycastSingle(cameraPose.p, cameraForward, 500.0f, PxSceneQueryFlags(0xffffffff), hit); float impactParam = mIsImpacting ? (hit.impact - position).magnitude() : FLT_MAX; PxTransform rayPose(position + cameraUp * 0.5f, cameraPose.q*PxQuat(PxHalfPi, PxVec3(0,1,0))); updateRayCapsule(mForceSmokeCapsule, rayPose, 1.0f); updateRayCapsule(mForceWaterCapsule, rayPose, 0.3f); mRenderActor->setTransform(rayPose); // if we had an impact if (impactParam < FLT_MAX) { PxVec3 impactPos = position + cameraForward*impactParam; // update emitter with new impact point and direction if(mSmokeEmitter.emitter) mSmokeEmitter.emitter->setLocalPose(PxTransform(impactPos, directionToQuaternion(-cameraForward))); if(mDebrisEmitter.emitter) mDebrisEmitter.emitter->setLocalPose(PxTransform(impactPos, directionToQuaternion(-cameraForward))); // spawn new RB debris if(mRbDebrisTimer < 0.0f && impactParam < FLT_MAX) { mRbDebrisTimer = RAYGUN_RB_DEBRIS_RATE; PxVec3 randDir(getSampleRandom().rand(-1.0f, 1.0f), getSampleRandom().rand(-1.0f, 1.0f), getSampleRandom().rand(-1.0f, 1.0f)); PxVec3 vel = -7.0f * (cameraForward + RAYGUN_RB_DEBRIS_ANGLE_RANDOMNESS * randDir.getNormalized()); PxVec3 dim(getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE), getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE), getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE)); // give spawn position, initial velocity and dimensions, spawn convex // which will not act in scene queries PxConvexMesh* convexMesh = generateConvex(mSample->getPhysics(), mSample->getCooking(), RAYGUN_RB_DEBRIS_SCALE); mSample->runtimeAssert(convexMesh, "Error generating convex for debris.\n"); PxRigidDynamic* debrisActor = PxCreateDynamic( mSample->getPhysics(), PxTransform(impactPos - cameraForward * 0.5f), PxConvexMeshGeometry(convexMesh), mSample->getDefaultMaterial(), 1.f); mSample->getActiveScene().addActor(*debrisActor); PX_ASSERT(debrisActor->getNbShapes() == 1); PxShape* debrisShape; debrisActor->getShapes(&debrisShape, 1); debrisShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false); debrisActor->setLinearVelocity(vel); debrisActor->setActorFlag(PxActorFlag::eVISUALIZATION, true); debrisActor->setAngularDamping(0.5f); // default material is green for debris RenderMaterial* debriMaterial = mSample->getMaterial(MATERIAL_HEIGHTFIELD); if(!debriMaterial) { debriMaterial = mSample->mRenderMaterials[MATERIAL_GREEN]; } mSample->createRenderObjectsFromActor(debrisActor, debriMaterial); mDebrisLifetime[debrisShape] = RAYGUN_RB_DEBRIS_LIFETIME; } } // update debris lifetime, remove if life ends DebrisLifetimeMap::iterator it = mDebrisLifetime.begin(); while(it != mDebrisLifetime.end()) { (*it).second -= dtime; if((*it).second < 0.0f) { PxShape* debrisShape = (*it).first; PX_ASSERT(debrisShape); // remove convex mesh PxConvexMeshGeometry geometry; bool isConvex = debrisShape->getConvexMeshGeometry(geometry); PX_ASSERT(isConvex); PX_UNUSED(isConvex); geometry.convexMesh->release(); // remove render and physics actor PxRigidActor& actorToRemove = debrisShape->getActor(); mSample->removeActor(&actorToRemove); actorToRemove.release(); // remove actor from lifetime map mDebrisLifetime.erase(it); it = mDebrisLifetime.begin(); continue; } ++it; } }
void PxVehicleCopyDynamicsData(const PxVehicleCopyDynamicsMap& wheelMap, const PxVehicleWheels& src, PxVehicleWheels* trg) { PX_CHECK_AND_RETURN(trg, "PxVehicleCopyDynamicsData requires that trg is a valid vehicle pointer"); PX_CHECK_AND_RETURN(src.getVehicleType() == trg->getVehicleType(), "PxVehicleCopyDynamicsData requires that both src and trg are the same type of vehicle"); #ifdef PX_CHECKED { const PxU32 numWheelsSrc = src.mWheelsSimData.getNbWheels(); const PxU32 numWheelsTrg = trg->mWheelsSimData.getNbWheels(); PxU8 copiedWheelsSrc[PX_MAX_NB_WHEELS]; PxMemZero(copiedWheelsSrc, sizeof(PxU8) * PX_MAX_NB_WHEELS); PxU8 setWheelsTrg[PX_MAX_NB_WHEELS]; PxMemZero(setWheelsTrg, sizeof(PxU8) * PX_MAX_NB_WHEELS); for(PxU32 i = 0; i < PxMin(numWheelsSrc, numWheelsTrg); i++) { const PxU32 srcWheelId = wheelMap.sourceWheelIds[i]; PX_CHECK_AND_RETURN(srcWheelId < numWheelsSrc, "PxVehicleCopyDynamicsData - wheelMap contains illegal source wheel id"); PX_CHECK_AND_RETURN(0 == copiedWheelsSrc[srcWheelId], "PxVehicleCopyDynamicsData - wheelMap contains illegal source wheel id"); copiedWheelsSrc[srcWheelId] = 1; const PxU32 trgWheelId = wheelMap.targetWheelIds[i]; PX_CHECK_AND_RETURN(trgWheelId < numWheelsTrg, "PxVehicleCopyDynamicsData - wheelMap contains illegal target wheel id"); PX_CHECK_AND_RETURN(0 == setWheelsTrg[trgWheelId], "PxVehicleCopyDynamicsData - wheelMap contains illegal target wheel id"); setWheelsTrg[trgWheelId]=1; } } #endif const PxU32 numWheelsSrc = src.mWheelsSimData.getNbWheels(); const PxU32 numWheelsTrg = trg->mWheelsSimData.getNbWheels(); //Set all dynamics data on the target to zero. //Be aware that setToRestState sets the rigid body to //rest so set the momentum back after calling setToRestState. PxRigidDynamic* actorTrg = trg->getRigidDynamicActor(); PxVec3 linVel = actorTrg->getLinearVelocity(); PxVec3 angVel = actorTrg->getAngularVelocity(); switch(src.getVehicleType()) { case PxVehicleTypes::eDRIVE4W: ((PxVehicleDrive4W*)trg)->setToRestState(); break; case PxVehicleTypes::eDRIVENW: ((PxVehicleDriveNW*)trg)->setToRestState(); break; case PxVehicleTypes::eDRIVETANK: ((PxVehicleDriveTank*)trg)->setToRestState(); break; case PxVehicleTypes::eNODRIVE: ((PxVehicleNoDrive*)trg)->setToRestState(); break; default: break; } actorTrg->setLinearVelocity(linVel); actorTrg->setAngularVelocity(angVel); //Keep a track of the wheels on trg that have their dynamics data set as a copy from src. PxU8 setWheelsTrg[PX_MAX_NB_WHEELS]; PxMemZero(setWheelsTrg, sizeof(PxU8) * PX_MAX_NB_WHEELS); //Keep a track of the average wheel rotation speed of all enabled wheels on src. PxU32 numEnabledWheelsSrc = 0; PxF32 accumulatedWheelRotationSpeedSrc = 0.0f; //Copy wheel dynamics data from src wheels to trg wheels. //Track the target wheels that have been given dynamics data from src wheels. //Compute the accumulated wheel rotation speed of all enabled src wheels. const PxU32 numMappedWheels = PxMin(numWheelsSrc, numWheelsTrg); for(PxU32 i = 0; i < numMappedWheels; i++) { const PxU32 srcWheelId = wheelMap.sourceWheelIds[i]; const PxU32 trgWheelId = wheelMap.targetWheelIds[i]; trg->mWheelsDynData.copy(src.mWheelsDynData, srcWheelId, trgWheelId); setWheelsTrg[trgWheelId] = 1; if(!src.mWheelsSimData.getIsWheelDisabled(srcWheelId)) { numEnabledWheelsSrc++; accumulatedWheelRotationSpeedSrc += src.mWheelsDynData.getWheelRotationSpeed(srcWheelId); } } //Compute the average wheel rotation speed of src. PxF32 averageWheelRotationSpeedSrc = 0; if(numEnabledWheelsSrc > 0) { averageWheelRotationSpeedSrc = (accumulatedWheelRotationSpeedSrc/ (1.0f * numEnabledWheelsSrc)); } //For wheels on trg that have not had their dynamics data copied from src just set //their wheel rotation speed to the average wheel rotation speed. for(PxU32 i = 0; i < numWheelsTrg; i++) { if(0 == setWheelsTrg[i] && !trg->mWheelsSimData.getIsWheelDisabled(i)) { trg->mWheelsDynData.setWheelRotationSpeed(i, averageWheelRotationSpeedSrc); } } //Copy the engine rotation speed/gear states/autobox states/etc. switch(src.getVehicleType()) { case PxVehicleTypes::eDRIVE4W: case PxVehicleTypes::eDRIVENW: case PxVehicleTypes::eDRIVETANK: { const PxVehicleDriveDynData& driveDynDataSrc = ((const PxVehicleDrive&)src).mDriveDynData; PxVehicleDriveDynData* driveDynDataTrg = &((PxVehicleDrive*)trg)->mDriveDynData; *driveDynDataTrg = driveDynDataSrc; } break; default: break; } }