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
}
Exemple #2
0
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));
}
Exemple #5
0
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;
}