void PhysX3::ApplyActionAtPoint(PintObjectHandle handle, PintActionType action_type, const Point& action, const Point& pos) { PxRigidActor* RigidActor = GetActorFromHandle(handle); if(!RigidActor) { PxShape* Shape = GetShapeFromHandle(handle); ASSERT(Shape); #ifdef SUPPORT_SHARED_SHAPES RigidActor = Shape->getActor(); #else RigidActor = &Shape->getActor(); #endif } if(RigidActor->getConcreteType()==PxConcreteType::eRIGID_DYNAMIC) { PxRigidDynamic* RigidDynamic = static_cast<PxRigidDynamic*>(RigidActor); if(!(RigidDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)) { PxForceMode::Enum mode; if(action_type==PINT_ACTION_FORCE) mode = PxForceMode::eFORCE; else if(action_type==PINT_ACTION_IMPULSE) mode = PxForceMode::eIMPULSE; else ASSERT(0); PxRigidBodyExt::addForceAtPos(*RigidDynamic, ToPxVec3(action), ToPxVec3(pos), mode); } } }
PR PhysX3::GetWorldTransform(PintObjectHandle handle) { PxTransform Pose; PxRigidActor* RigidActor = GetActorFromHandle(handle); if(RigidActor) { Pose = RigidActor->getGlobalPose(); } else { PxShape* Shape = GetShapeFromHandle(handle); ASSERT(Shape); #ifdef SUPPORT_SHARED_SHAPES ASSERT(Shape->getActor()); Pose = PxShapeExt::getGlobalPose(*Shape, *Shape->getActor()); #else Pose = PxShapeExt::getGlobalPose(*Shape); #endif } return PR(ToPoint(Pose.p), ToQuat(Pose.q)); }
void defaultCCTInteraction(const PxControllerShapeHit& hit) { PxRigidDynamic* actor = hit.shape->getActor()->is<PxRigidDynamic>(); if(actor) { if(actor->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC) return; if(0) { const PxVec3 p = actor->getGlobalPose().p + hit.dir * 10.0f; PxShape* shape; actor->getShapes(&shape, 1); PxRaycastHit newHit; PxU32 n = PxShapeExt::raycast(*shape, *shape->getActor(), p, -hit.dir, 20.0f, PxHitFlag::ePOSITION, 1, &newHit, false); if(n) { // We only allow horizontal pushes. Vertical pushes when we stand on dynamic objects creates // useless stress on the solver. It would be possible to enable/disable vertical pushes on // particular objects, if the gameplay requires it. const PxVec3 upVector = hit.controller->getUpDirection(); const PxF32 dp = hit.dir.dot(upVector); // shdfnd::printFormatted("%f\n", fabsf(dp)); if(fabsf(dp)<1e-3f) // if(hit.dir.y==0.0f) { const PxTransform globalPose = actor->getGlobalPose(); const PxVec3 localPos = globalPose.transformInv(newHit.position); ::addForceAtLocalPos(*actor, hit.dir*hit.length*1000.0f, localPos, PxForceMode::eACCELERATION); } } } // We only allow horizontal pushes. Vertical pushes when we stand on dynamic objects creates // useless stress on the solver. It would be possible to enable/disable vertical pushes on // particular objects, if the gameplay requires it. const PxVec3 upVector = hit.controller->getUpDirection(); const PxF32 dp = hit.dir.dot(upVector); // shdfnd::printFormatted("%f\n", fabsf(dp)); if(fabsf(dp)<1e-3f) // if(hit.dir.y==0.0f) { const PxTransform globalPose = actor->getGlobalPose(); const PxVec3 localPos = globalPose.transformInv(toVec3(hit.worldPos)); ::addForceAtLocalPos(*actor, hit.dir*hit.length*1000.0f, localPos, PxForceMode::eACCELERATION); } } }
void PhysX::AddWorldImpulseAtWorldPos(PintObjectHandle handle, const Point& world_impulse, const Point& world_pos) { PxRigidActor* RigidActor = GetActorFromHandle(handle); if(!RigidActor) { PxShape* Shape = GetShapeFromHandle(handle); ASSERT(Shape); RigidActor = &Shape->getActor(); } if(RigidActor->getConcreteType()==PxConcreteType::eRIGID_DYNAMIC) { PxRigidDynamic* RigidDynamic = static_cast<PxRigidDynamic*>(RigidActor); PxRigidBodyExt::addForceAtPos(*RigidDynamic, ToPxVec3(world_impulse), ToPxVec3(world_pos), PxForceMode::eIMPULSE); } }
PxU32 SampleBridges::getBehaviorFlags(const PxShape& shape) { const char* actorName = shape.getActor().getName(); #ifdef PLATFORMS_AS_OBSTACLES PX_ASSERT(actorName!=gPlatformName); // PT: in this mode we should have filtered out those guys already #endif // PT: ride on planks if(actorName==gPlankName) return PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT; // PT: ride & slide on platforms if(actorName==gPlatformName) return PxControllerBehaviorFlag::eCCT_CAN_RIDE_ON_OBJECT|PxControllerBehaviorFlag::eCCT_SLIDE; return 0; }
void PhysX::AddLocalTorque(PintObjectHandle handle, const Point& local_torque) { PxRigidActor* RigidActor = GetActorFromHandle(handle); if(!RigidActor) { PxShape* Shape = GetShapeFromHandle(handle); ASSERT(Shape); RigidActor = &Shape->getActor(); } if(RigidActor->getConcreteType()==PxConcreteType::eRIGID_DYNAMIC) { PxRigidDynamic* RigidDynamic = static_cast<PxRigidDynamic*>(RigidActor); const PxVec3 GlobalTorque = RigidDynamic->getGlobalPose().rotate(ToPxVec3(local_torque)); RigidDynamic->addTorque(GlobalTorque, PxForceMode::eACCELERATION, true); } }
bool ParticleChain::checkPenetration(const Ogre::Vector3 &position, Ogre::Vector3 &closestSurfacePos, Ogre::Vector3 &collisionNormal) { PxShape *hit = nullptr; PxVec3 pxPos = Convert::toPx(position); if (mPhysXScene->getPxScene()->overlapAny(PxSphereGeometry(0.05f), PxTransform(pxPos), hit)) { PxVec3 actorCenter = hit->getActor().getWorldBounds().getCenter(); PxVec3 rayDir = actorCenter - pxPos; rayDir.normalize(); PxVec3 rayOrigin = pxPos - rayDir.multiply(PxVec3(0.2f, 0.2f, 0.2f)); if (mPhysXScene->getPxScene()->overlapAny(PxSphereGeometry(0.05f), PxTransform(rayOrigin), hit)) return false; PxRaycastHit rayHit; if (mPhysXScene->getPxScene()->raycastSingle(rayOrigin, rayDir, 0.2f, PxSceneQueryFlag::eIMPACT|PxSceneQueryFlag::eNORMAL|PxSceneQueryFlag::eDISTANCE, rayHit)) { closestSurfacePos = Convert::toOgre(rayHit.impact); collisionNormal = Convert::toOgre(rayHit.normal); return true; } } return false; }
bool Test::GeometryHelpers::testForOverlap(const PxShape& s0, const PxGeometry& g1, const PxTransform& globalPose1) { return PxGeometryQuery::overlap(g1, globalPose1, s0.getGeometry().any(), PxShapeExt::getGlobalPose(s0, *s0.getActor())); }
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; } }