void AddRadialForceToPxRigidBody_AssumesLocked(PxRigidBody& PRigidBody, const FVector& Origin, float Radius, float Strength, uint8 Falloff, bool bAccelChange) { #if WITH_PHYSX if (!(PRigidBody.getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)) { float Mass = PRigidBody.getMass(); PxTransform PCOMTransform = PRigidBody.getGlobalPose().transform(PRigidBody.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; PRigidBody.addForce(PImpulse, bAccelChange ? PxForceMode::eACCELERATION : PxForceMode::eFORCE); } #endif // WITH_PHYSX }
void AddRadialImpulseToPxRigidBody_AssumesLocked(PxRigidBody& PRigidBody, const FVector& Origin, float Radius, float Strength, uint8 Falloff, bool bVelChange) { #if WITH_PHYSX if (!(PRigidBody.getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)) { float Mass = PRigidBody.getMass(); PxTransform PCOMTransform = PRigidBody.getGlobalPose().transform(PRigidBody.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; PRigidBody.addForce(PImpulse, Mode); } #endif // WITH_PHYSX }
void PhysActor_PhysX::AddForce(vec3f force, PhysForceMode::Enum mode) { if (!impl->physActor) { LOG("Cannot add force to actor because physActor is null!"); return; } PxRigidBody* actor = nullptr; PxVec3 pushDir; pushDir.x = force.x; pushDir.y = force.y; pushDir.z = force.z; PxForceMode::Enum physXMode; switch (mode) { case PhysForceMode::Acceleration: physXMode = PxForceMode::eACCELERATION; break; case PhysForceMode::Force: physXMode = PxForceMode::eFORCE; break; case PhysForceMode::VelocityChange: physXMode = PxForceMode::eVELOCITY_CHANGE; break; case PhysForceMode::Impulse: default: physXMode = PxForceMode::eIMPULSE; break; } if (impl->physActor->isRigidDynamic() || impl->physActor->isRigidBody()) { actor = (PxRigidBody*)impl->physActor; } else { LOG("Cannot add force to actor because actor is not a Rigid Dynamic or Rigid Body actor."); return; } if (actor) actor->addForce(pushDir, physXMode); }
PX_INLINE void addForceAtPosInternal(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup) { if(mode == PxForceMode::eACCELERATION || mode == PxForceMode::eVELOCITY_CHANGE) { Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxRigidBodyExt::addForce methods do not support eACCELERATION or eVELOCITY_CHANGE modes"); return; } const PxTransform globalPose = body.getGlobalPose(); const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p); const PxVec3 torque = (pos - centerOfMass).cross(force); body.addForce(force, mode, wakeup); body.addTorque(torque, mode, wakeup); }
/** Applies forces - Assumes caller has obtained writer lock */ void FPhysSubstepTask::ApplyForces_AssumesLocked(const FPhysTarget& PhysTarget, FBodyInstance* BodyInstance) { #if WITH_PHYSX /** Apply Forces */ PxRigidBody* PRigidBody = BodyInstance->GetPxRigidBody_AssumesLocked(); for (int32 i = 0; i < PhysTarget.Forces.Num(); ++i) { const FForceTarget& ForceTarget = PhysTarget.Forces[i]; if (ForceTarget.bPosition) { PxRigidBodyExt::addForceAtPos(*PRigidBody, U2PVector(ForceTarget.Force), U2PVector(ForceTarget.Position), PxForceMode::eFORCE, true); } else { PRigidBody->addForce(U2PVector(ForceTarget.Force), ForceTarget.bAccelChange ? PxForceMode::eACCELERATION : PxForceMode::eFORCE, true); } } #endif }
// Called every frame for vehicle void Vehicle::update() { resetIfNeeded(); float handBrake = 0; float forwardSpeed = physicsVehicle->computeForwardSpeed(); (input.handBrake) ? handBrake = 1.0f: handBrake = 0.0f; // Force gear change if speed is 0 (works, not sure why) if (forwardSpeed == 0) { if (input.forward > 0) { physicsVehicle->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST); } else if (input.backward > 0) { physicsVehicle->mDriveDynData.forceGearChange(PxVehicleGearsData::eREVERSE); } } // If speed is close to 0 set new target gear else if (forwardSpeed < 5 && input.backward > 0) { physicsVehicle->mDriveDynData.setTargetGear(PxVehicleGearsData::eREVERSE); } else if (forwardSpeed > -5 && input.forward > 0) { physicsVehicle->mDriveDynData.setTargetGear(PxVehicleGearsData::eFIRST); } // Determine how to apply controller input depending on current gear if (physicsVehicle->mDriveDynData.getCurrentGear() == PxVehicleGearsData::eREVERSE) { vehicleInput.setAnalogAccel(input.backward); vehicleInput.setAnalogBrake(input.forward); } else { vehicleInput.setAnalogAccel(input.forward); vehicleInput.setAnalogBrake(input.backward); if(input.forward > 0) gasSignal(this); } if (input.forward == 0 && input.backward == 0) idleSignal(this); if (isSlipping && (forwardSpeed > 5 || forwardSpeed < -5)) brakeSignal(this); // Steer and handbrake vehicleInput.setAnalogSteer(input.steer); vehicleInput.setAnalogHandbrake(handBrake); PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs(smoothingData, steerVsSpeedTable, vehicleInput, stepSizeS, isInAir, *physicsVehicle); if (input.shootPizza) { if (pizzaCount > 0) { shootPizzaSignal(this); pizzaCount--; } else { dryFireSignal(this); } input.shootPizza = false; } if (input.jump && (!isInAir || spaceMode)) { PxRigidBody* rigid = (PxRigidBody*)actor; rigid->addForce(PxVec3(0, 375, 0), PxForceMode::eACCELERATION); input.jump = false; } }