void AddRadialForceToPxRigidDynamic(PxRigidDynamic& PRigidDynamic, const FVector& Origin, float Radius, float Strength, uint8 Falloff) { #if WITH_PHYSX if (!(PRigidDynamic.getRigidDynamicFlags() & PxRigidDynamicFlag::eKINEMATIC)) { float Mass = PRigidDynamic.getMass(); PxTransform PCOMTransform = PRigidDynamic.getGlobalPose().transform(PRigidDynamic.getCMassLocalPose()); PxVec3 PCOMPos = PCOMTransform.p; // center of mass in world space PxVec3 POrigin = U2PVector(Origin); // origin of radial impulse, in world space PxVec3 PDelta = PCOMPos - POrigin; // vector from float Mag = PDelta.magnitude(); // Distance from COM to origin, in Unreal scale : @todo: do we still need conversion scale? // If COM is outside radius, do nothing. if (Mag > Radius) { return; } PDelta.normalize(); // If using linear falloff, scale with distance. float ForceMag = Strength; if (Falloff == RIF_Linear) { ForceMag *= (1.0f - (Mag / Radius)); } // Apply force PxVec3 PImpulse = PDelta * ForceMag; PRigidDynamic.addForce(PImpulse, PxForceMode::eFORCE); } #endif // WITH_PHYSX }
void PhysXRigidManager::update(const physx::PxActiveTransform * activeTransforms, physx::PxU32 nbActiveTransforms, float timeStep, physx::PxVec3 gravity) { for (PxU32 i = 0; i < nbActiveTransforms; ++i) { if (activeTransforms[i].userData != NULL) { std::string *n = static_cast<std::string*>(activeTransforms[i].userData); if (rigidBodies.find(*n) != rigidBodies.end()) { PxRigidDynamic * actor = rigidBodies[*n].info.actor->is<PxRigidDynamic>(); if (rigidBodies[*n].rollingFriction >= 0.0f) { float mass = actor->getMass(); float force = mass * gravity.magnitude() * rigidBodies[*n].rollingFriction; float actorMotion = (mass * actor->getLinearVelocity().magnitude()) / ((float)rigidBodies[*n].rollingFrictionTimeStamp * timeStep); if (force <= actorMotion) { rigidBodies[*n].rollingFrictionTimeStamp++; PxVec3 forceVec = -(actor->getLinearVelocity().getNormalized() * force); actor->addForce(forceVec); } else { rigidBodies[*n].rollingFrictionTimeStamp = 1; //actor->setLinearVelocity(actor->getLinearVelocity() / 1.5f); //actor->setAngularVelocity(actor->getAngularVelocity() / 1.5f); //actor->setLinearVelocity(PxVec3(0.0f)); //actor->setAngularVelocity(PxVec3(0.0f)); } } PxMat44 mat(activeTransforms[i].actor2World); mat.scale(PxVec4(PxVec3(rigidBodies[*n].scalingFactor), 1.0f)); //getMatFromPhysXTransform(activeTransforms[i].actor2World, rigidBodies[*n].extInfo.transform); getMatFromPhysXTransform(mat, rigidBodies[*n].info.extInfo.transform); } } } }
void AddRadialImpulseToPxRigidDynamic(PxRigidDynamic& PRigidDynamic, const FVector& Origin, float Radius, float Strength, uint8 Falloff, bool bVelChange) { #if WITH_PHYSX if (!(PRigidDynamic.getRigidDynamicFlags() & PxRigidDynamicFlag::eKINEMATIC)) { float Mass = PRigidDynamic.getMass(); PxTransform PCOMTransform = PRigidDynamic.getGlobalPose().transform(PRigidDynamic.getCMassLocalPose()); PxVec3 PCOMPos = PCOMTransform.p; // center of mass in world space PxVec3 POrigin = U2PVector(Origin); // origin of radial impulse, in world space PxVec3 PDelta = PCOMPos - POrigin; // vector from origin to COM float Mag = PDelta.magnitude(); // Distance from COM to origin, in Unreal scale : @todo: do we still need conversion scale? // If COM is outside radius, do nothing. if (Mag > Radius) { return; } PDelta.normalize(); // Scale by U2PScale here, because units are velocity * mass. float ImpulseMag = Strength; if (Falloff == RIF_Linear) { ImpulseMag *= (1.0f - (Mag / Radius)); } PxVec3 PImpulse = PDelta * ImpulseMag; PxForceMode::Enum Mode = bVelChange ? PxForceMode::eVELOCITY_CHANGE : PxForceMode::eIMPULSE; PRigidDynamic.addForce(PImpulse, Mode); } #endif // WITH_PHYSX }
void PxScaleRigidActor(PxRigidActor& actor, PxReal scale, bool scaleMassProps) { PX_CHECK_AND_RETURN(scale > 0, "PxScaleRigidActor requires that the scale parameter is greater than zero"); Ps::InlineArray<PxShape*, 64> shapes; shapes.resize(actor.getNbShapes()); actor.getShapes(shapes.begin(), shapes.size()); for(PxU32 i=0;i<shapes.size();i++) { shapes[i]->setLocalPose(scalePosition(shapes[i]->getLocalPose(), scale)); PxGeometryHolder h = shapes[i]->getGeometry(); switch(h.getType()) { case PxGeometryType::eSPHERE: h.sphere().radius *= scale; break; case PxGeometryType::ePLANE: break; case PxGeometryType::eCAPSULE: h.capsule().halfHeight *= scale; h.capsule().radius *= scale; break; case PxGeometryType::eBOX: h.box().halfExtents *= scale; break; case PxGeometryType::eCONVEXMESH: h.convexMesh().scale.scale *= scale; break; case PxGeometryType::eTRIANGLEMESH: h.triangleMesh().scale.scale *= scale; break; case PxGeometryType::eHEIGHTFIELD: h.heightField().heightScale *= scale; h.heightField().rowScale *= scale; h.heightField().columnScale *= scale; break; case PxGeometryType::eINVALID: case PxGeometryType::eGEOMETRY_COUNT: default: PX_ASSERT(0); } shapes[i]->setGeometry(h.any()); } if(!scaleMassProps) return; PxRigidDynamic* dynamic = (&actor)->is<PxRigidDynamic>(); if(!dynamic) return; PxReal scale3 = scale*scale*scale; dynamic->setMass(dynamic->getMass()*scale3); dynamic->setMassSpaceInertiaTensor(dynamic->getMassSpaceInertiaTensor()*scale3*scale*scale); dynamic->setCMassLocalPose(scalePosition(dynamic->getCMassLocalPose(), scale)); }
Seamine* SampleSubmarine::createSeamine(const PxVec3& inPosition, PxReal inHeight) { static const PxReal chainLinkLength = 2.0f; static const PxReal linkSpacing = 0.05f; static const PxReal mineHeadRadius = 1.5f; const PxVec3 mineStartPos = inPosition; static const PxVec3 linkOffset = PxVec3(0, chainLinkLength + linkSpacing, 0); static const PxVec3 halfLinkOffset = linkOffset * 0.5f; static const PxVec3 linkDim = PxVec3(chainLinkLength*0.125f, chainLinkLength*0.5f, chainLinkLength*0.125f); PxU32 numLinks = PxU32((inHeight - 2.0f*mineHeadRadius) / (chainLinkLength + linkSpacing)); numLinks = numLinks ? numLinks : 1; Seamine* seamine = SAMPLE_NEW(Seamine); mSeamines.push_back(seamine); // create links from floor PxVec3 linkPos = mineStartPos + halfLinkOffset; PxRigidActor* prevActor = NULL; for(PxU32 i = 0; i < numLinks; i++) { // create the link actor PxRigidDynamic* link = createBox(linkPos, linkDim, NULL, mSeamineMaterial, 1.0f)->is<PxRigidDynamic>(); if(!link) fatalError("createBox failed!"); // back reference to mineHead link->userData = seamine; seamine->mLinks.push_back(link); setupFiltering(link, FilterGroup::eMINE_LINK, FilterGroup::eSUBMARINE); link->setLinearDamping(0.5f); link->setAngularDamping(0.5f); link->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true); // create distance joint between link and prevActor PxTransform linkFrameA = prevActor ? PxTransform(halfLinkOffset, PxQuat::createIdentity()) : PxTransform(mineStartPos, PxQuat::createIdentity()); PxTransform linkFrameB = PxTransform(-halfLinkOffset, PxQuat::createIdentity()); PxDistanceJoint *joint = PxDistanceJointCreate(getPhysics(), prevActor, linkFrameA, link, linkFrameB); if(!joint) fatalError("PxDistanceJointCreate failed!"); // set min & max distance to 0 joint->setMaxDistance(0.0f); joint->setMinDistance(0.0f); // setup damping & spring joint->setDamping(1.0f * link->getMass()); joint->setSpring(400.0f * link->getMass()); joint->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED); // add to joints array for cleanup mJoints.push_back(joint); prevActor = link; linkPos += linkOffset; } // create mine head linkPos.y += mineHeadRadius - (chainLinkLength*0.5f); PxRigidDynamic* mineHead = createSphere(linkPos, mineHeadRadius, NULL, mSeamineMaterial, 1.0f)->is<PxRigidDynamic>(); mineHead->userData = seamine; seamine->mMineHead = mineHead; mineHead->setLinearDamping(0.5f); mineHead->setAngularDamping(0.5f); mineHead->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true); // setup filtering to trigger contact reports when submarine touches the minehead setupFiltering(mineHead, FilterGroup::eMINE_HEAD, FilterGroup::eSUBMARINE); // create distance joint between mine head and prevActor PxTransform linkFrameA = PxTransform(halfLinkOffset, PxQuat::createIdentity()); PxTransform linkFrameB = PxTransform(PxVec3(0, -mineHeadRadius - linkSpacing*0.5f, 0), PxQuat::createIdentity()); PxDistanceJoint *joint = PxDistanceJointCreate(getPhysics(), prevActor, linkFrameA, mineHead, linkFrameB); if(!joint) fatalError("PxDistanceJointCreate failed!"); // set min & max distance to 0 joint->setMaxDistance(0.0f); joint->setMinDistance(0.0f); // setup damping & spring joint->setDamping(1.0f * mineHead->getMass()); joint->setSpring(400.0f * mineHead->getMass()); joint->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED); // add to joints array for cleanup mJoints.push_back(joint); return seamine; }