void UDestructibleComponent::AddImpulse( FVector Impulse, FName BoneName /*= NAME_None*/, bool bVelChange /*= false*/ )
{
#if WITH_APEX
	int32 ChunkIdx = BoneIdxToChunkIdx(GetBoneIndex(BoneName));
	PxRigidDynamic* PActor = ApexDestructibleActor->getChunkPhysXActor(ChunkIdx);

	if (PActor != NULL)
	{
		SCOPED_SCENE_WRITE_LOCK(PActor->getScene());

		PActor->addForce(U2PVector(Impulse), bVelChange ? PxForceMode::eVELOCITY_CHANGE : PxForceMode::eIMPULSE);
	}
#endif
}
void FPhysSubstepTask::AddTorque(FBodyInstance * Body, const FVector & Torque)
{
    check(Body);

    PxRigidDynamic * PRigidDynamic = Body->GetPxRigidDynamic();
    SCOPED_SCENE_READ_LOCK(PRigidDynamic->getScene());
    //We should only apply torque on non kinematic actors
    if (IsRigidDynamicNonKinematic(PRigidDynamic))
    {
        FTorqueTarget TorqueTarget;
        TorqueTarget.Torque = Torque;

        FPhysTarget & TargetState = PhysTargetBuffers[External].FindOrAdd(Body);
        TargetState.Torques.Add(TorqueTarget);
    }
}
Example #3
0
void UDestructibleComponent::AddRadialForce(FVector Origin, float Radius, float Strength, ERadialImpulseFalloff Falloff, bool bAccelChange /* = false */)
{
#if WITH_APEX
	if(bIgnoreRadialForce)
	{
		return;
	}

	if (ApexDestructibleActor == NULL)
	{
		return;
	}

	PxRigidDynamic** PActorBuffer = NULL;
	PxU32 PActorCount = 0;
	if (ApexDestructibleActor->acquirePhysXActorBuffer(PActorBuffer, PActorCount, NxDestructiblePhysXActorQueryFlags::Dynamic))
	{
		PxScene* LockedScene = NULL;
		

		while (PActorCount--)
		{
			PxRigidDynamic* PActor = *PActorBuffer++;
			if (PActor != NULL)
			{
				if (!LockedScene)
				{
					LockedScene = PActor->getScene();
					LockedScene->lockWrite();
					LockedScene->lockRead();
				}

				AddRadialForceToPxRigidBody_AssumesLocked(*PActor, Origin, Radius, Strength, Falloff, bAccelChange);
			}

			if (LockedScene)
			{
				LockedScene->unlockRead();
				LockedScene->unlockWrite();
				LockedScene = NULL;
			}
		}
		ApexDestructibleActor->releasePhysXActorBuffer();
	}
#endif	// #if WITH_APEX
}
Example #4
0
void UDestructibleComponent::OnUpdateTransform(bool bSkipPhysicsMove)
{
	// We are handling the physics move below, so don't handle it at higher levels
	Super::OnUpdateTransform(true);

	if (SkeletalMesh == NULL)
	{
		return;
	}

	if (!bPhysicsStateCreated || bSkipPhysicsMove)
	{
		return;
	}

	const FTransform& CurrentLocalToWorld = ComponentToWorld;

	if(CurrentLocalToWorld.ContainsNaN())
	{
		return;
	}

	// warn if it has non-uniform scale
	const FVector& MeshScale3D = CurrentLocalToWorld.GetScale3D();
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if( !MeshScale3D.IsUniform() )
	{
		UE_LOG(LogPhysics, Log, TEXT("UDestructibleComponent::SendPhysicsTransform : Non-uniform scale factor (%s) can cause physics to mismatch for %s  SkelMesh: %s"), *MeshScale3D.ToString(), *GetFullName(), SkeletalMesh ? *SkeletalMesh->GetFullName() : TEXT("NULL"));
	}
#endif

#if WITH_APEX
	if (ApexDestructibleActor)
	{
		PxRigidDynamic* PRootActor = ApexDestructibleActor->getChunkPhysXActor(0);
		PxMat44 GlobalPose(PxMat33(U2PQuat(CurrentLocalToWorld.GetRotation())), U2PVector(CurrentLocalToWorld.GetTranslation()));
		if(!PRootActor || PRootActor->getScene())	//either root chunk is null meaning fractured (so there's a scene), or the root has a scene
		{
			ApexDestructibleActor->setGlobalPose(GlobalPose);
		}else
		{
			PRootActor->setGlobalPose(PxTransform(GlobalPose));	//we're not in a scene yet, so place the root actor in this new position
		}
	}
#endif // #if WITH_APEX
}
void FPhysSubstepTask::AddForce(FBodyInstance * Body, const FVector & Force)
{
    check(Body);
    PxRigidDynamic * PRigidDynamic = Body->GetPxRigidDynamic();
    SCOPED_SCENE_READ_LOCK(PRigidDynamic->getScene());
    //We should only apply forces on non kinematic actors
    if (IsRigidDynamicNonKinematic(PRigidDynamic))
    {

        FForceTarget ForceTarget;
        ForceTarget.bPosition = false;
        ForceTarget.Force = Force;

        FPhysTarget & TargetState = PhysTargetBuffers[External].FindOrAdd(Body);
        TargetState.Forces.Add(ForceTarget);
    }
}
void FPhysSubstepTask::SetKinematicTarget(FBodyInstance * Body, const FTransform & TM)
{
    check(Body);
    TM.DiagnosticCheckNaN_All();

    PxRigidDynamic * PRigidDynamic = Body->GetPxRigidDynamic();
    SCOPED_SCENE_READ_LOCK(PRigidDynamic->getScene());
    //We only interpolate kinematic actors
    if (!IsRigidDynamicNonKinematic(PRigidDynamic))
    {
        FKinematicTarget KinmaticTarget(Body, TM);
        FPhysTarget & TargetState = PhysTargetBuffers[External].FindOrAdd(Body);
        TargetState.bKinematicTarget = true;
        TargetState.KinematicTarget = KinmaticTarget;
    }

}
Example #7
0
void UDestructibleComponent::SetCollisionResponseForAllActors(const FCollisionResponseContainer& ResponseOverride)
{
#if WITH_APEX
	if (ApexDestructibleActor == NULL)
	{
		return;
	}

	PxRigidDynamic** PActorBuffer = NULL;
	PxU32 PActorCount = 0;
	if (ApexDestructibleActor->acquirePhysXActorBuffer(PActorBuffer, PActorCount))
	{
		PxScene* LockedScene = NULL;

		while (PActorCount--)
		{
			PxRigidDynamic* PActor = *PActorBuffer++;
			if (PActor != NULL)
			{
				FDestructibleChunkInfo* ChunkInfo = FPhysxUserData::Get<FDestructibleChunkInfo>(PActor->userData);
				if (ChunkInfo != NULL)
				{
					if (!LockedScene)
					{
						LockedScene = PActor->getScene();
						LockedScene->lockWrite();
						LockedScene->lockRead();
					}
					SetCollisionResponseForActor(PActor, ChunkInfo->ChunkIndex, &ResponseOverride);	// ChunkIndex is the last chunk made visible.  But SetCollisionResponseForActor already doesn't respect per-chunk collision properties.
				}
			}
		}

		if (LockedScene)
		{
			LockedScene->unlockRead();
			LockedScene->unlockWrite();
			LockedScene = NULL;
		}

		ApexDestructibleActor->releasePhysXActorBuffer();
	}
#endif
}
void FPhysSubstepTask::SubstepInterpolation(float InAlpha)
{
#if WITH_PHYSX
#if WITH_APEX
	PxScene * PScene = PAScene->getPhysXScene();
#else
	PxScene * PScene = PAScene;
#endif

	PhysTargetMap & Targets = PhysTargetBuffers[!External];

	/** Note: We lock the entire scene before iterating. The assumption is that removing an FBodyInstance from the map will also be wrapped by this lock */
	SCENE_LOCK_WRITE(PScene);

	for (PhysTargetMap::TIterator Itr = Targets.CreateIterator(); Itr; ++Itr)
	{
		FPhysTarget & PhysTarget = Itr.Value();
		FBodyInstance* BodyInstance = Itr.Key();
		PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic();

		if (PRigidDynamic == NULL)
		{
			continue;
		}

		//We should only be iterating over actors that belong to this scene
		check(PRigidDynamic->getScene() == PScene);

		ApplyForces(PhysTarget, BodyInstance);
		ApplyTorques(PhysTarget, BodyInstance);
		InterpolateKinematicActor(PhysTarget, BodyInstance, InAlpha);
	}

	/** Final substep */
	if (InAlpha >= 1.f)
	{
		Targets.Empty(Targets.Num());
	}

	SCENE_UNLOCK_WRITE(PScene);
#endif
}
DestructibleActorJointImpl::DestructibleActorJointImpl(const DestructibleActorJointDesc& desc, DestructibleScene& dscene) :
    joint(NULL)
{
    if (desc.destructible[0] == NULL && desc.destructible[1] == NULL)
    {
        APEX_DEBUG_WARNING("Both destructible actors in DestructibleActorJoint are NULL.");
        return;
    }

    PxRigidActor*	actor[2]		= {desc.actor[0], desc.actor[1]};
    PxVec3			localAxis[2]	= {desc.localAxis[0], desc.localAxis[1]};
    PxVec3			localAnchor[2]	= {desc.localAnchor[0], desc.localAnchor[1]};
    PxVec3			localNormal[2]	= {desc.localNormal[0], desc.localNormal[1]};

    PxTransform		localFrame[2];

    for (int i = 0; i < 2; ++i)
    {
        if (desc.destructible[i] == NULL)
        {
            structure[i] = NULL;
            attachmentChunkIndex[i] = ModuleDestructibleConst::INVALID_CHUNK_INDEX;

            if(NULL == actor[i])
            {
                // World constrained
                PxMat33	rot(desc.globalAxis[i],desc.globalNormal[i],desc.globalAxis[i].cross(desc.globalNormal[i]));

                localFrame[i].p	= desc.globalAnchor[i];
                localFrame[i].q	= PxQuat(rot);
                localFrame[i].q.normalize();
            }
            else
            {
                // Constrained to physics object
                PxMat33	rot(localAxis[i], localNormal[i], localAxis[i].cross(localNormal[i]));

                localFrame[i].p	= localAnchor[i];
                localFrame[i].q	= PxQuat(rot);
                localFrame[i].q.normalize();
            }
            continue;
        }

        PxRigidDynamic* attachActor = NULL;
        DestructibleActorImpl& destructible = ((DestructibleActorProxy*)desc.destructible[i])->impl;
        structure[i] = destructible.getStructure();

        attachmentChunkIndex[i] = desc.attachmentChunkIndex[i];

        if (attachmentChunkIndex[i] >= 0 && attachmentChunkIndex[i] < (int32_t)destructible.getDestructibleAsset()->getChunkCount())
        {
            DestructibleStructure::Chunk& chunk = structure[i]->chunks[destructible.getFirstChunkIndex() + attachmentChunkIndex[i]];
            attachActor = structure[i]->dscene->chunkIntact(chunk);
        }

        SCOPED_PHYSX_LOCK_READ(dscene.getModulePhysXScene());

        if (attachActor == NULL)
        {
            float minDistance = PX_MAX_F32;
            for (uint32_t j = 0; j < destructible.getDestructibleAsset()->getChunkCount(); ++j)
            {
                DestructibleAssetParametersNS::Chunk_Type& source = destructible.getDestructibleAsset()->mParams->chunks.buf[j];
                const bool hasChildren = source.numChildren != 0;
                if (!hasChildren)	// Only attaching to lowest-level chunks, initially
                {
                    DestructibleStructure::Chunk& chunk = structure[i]->chunks[destructible.getFirstChunkIndex() + j];
                    PxRigidDynamic* actor = structure[i]->dscene->chunkIntact(chunk);
                    if (actor)
                    {
                        const float distance = (actor->getGlobalPose().transform(chunk.localSphereCenter) - desc.globalAnchor[i]).magnitude();
                        if (distance < minDistance)
                        {
                            attachActor = actor;
                            attachmentChunkIndex[i] = (int32_t)(destructible.getFirstChunkIndex() + j);
                            minDistance = distance;
                        }
                    }
                }
            }
        }

        if (attachActor == NULL)
        {
            APEX_DEBUG_WARNING("No physx actor could be found in destructible actor %p to attach the joint.", desc.destructible[i]);
            return;
        }

        actor[i] = (PxRigidActor*)attachActor;

        if (attachActor->getScene() != NULL && dscene.getModulePhysXScene() != attachActor->getScene())
        {
            APEX_DEBUG_WARNING("Trying to joint actors from a scene different from the joint scene.");
            return;
        }

        localAnchor[i] = attachActor->getGlobalPose().transformInv(desc.globalAnchor[i]);
        localAxis[i] = attachActor->getGlobalPose().rotateInv(desc.globalAxis[i]);
        localNormal[i] = attachActor->getGlobalPose().rotateInv(desc.globalNormal[i]);

        PxMat33	rot(localAxis[i], localNormal[i], localAxis[i].cross(localNormal[i]));

        localFrame[i].p	= localAnchor[i];
        localFrame[i].q	= PxQuat(rot);
        localFrame[i].q.normalize();
    }

    dscene.getModulePhysXScene()->lockRead();
    switch (desc.type)
    {
    case PxJointConcreteType::eD6:
        joint	= PxD6JointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]);
        break;
    case PxJointConcreteType::eDISTANCE:
        joint	= PxDistanceJointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]);
        break;
    case PxJointConcreteType::eFIXED:
        joint	= PxFixedJointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]);
        break;
    case PxJointConcreteType::ePRISMATIC:
        joint	= PxPrismaticJointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]);
        break;
    case PxJointConcreteType::eREVOLUTE:
        joint	= PxRevoluteJointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]);
        break;
    case PxJointConcreteType::eSPHERICAL:
        joint	= PxSphericalJointCreate(dscene.getModulePhysXScene()->getPhysics(), actor[0], localFrame[0], actor[1], localFrame[1]);
        break;
    default:
        PX_ALWAYS_ASSERT();
        break;
    }
    dscene.getModulePhysXScene()->unlockRead();

    PX_ASSERT(joint != NULL);
}
void UPhysicsHandleComponent::GrabComponent(UPrimitiveComponent* InComponent, FName InBoneName, FVector Location, bool bConstrainRotation)
{
	// If we are already holding something - drop it first.
	if(GrabbedComponent != NULL)
	{
		ReleaseComponent();
	}

	if(!InComponent)
	{
		return;
	}

#if WITH_PHYSX
	// Get the PxRigidDynamic that we want to grab.
	FBodyInstance* BodyInstance = InComponent->GetBodyInstance(InBoneName);
	if (!BodyInstance)
	{
		return;
	}

	PxRigidDynamic* Actor = BodyInstance->GetPxRigidDynamic();
	if (!Actor)
		return;

	// Get the scene the PxRigidDynamic we want to grab is in.
	PxScene* Scene = Actor->getScene();
	check(Scene);

	// Get transform of actor we are grabbing
	PxVec3 KinLocation = U2PVector(Location);
	PxTransform GrabbedActorPose = Actor->getGlobalPose();
	PxTransform KinPose(KinLocation, GrabbedActorPose.q);

	// set target and current, so we don't need another "Tick" call to have it right
	TargetTransform = CurrentTransform = P2UTransform(KinPose);

	// If we don't already have a handle - make one now.
	if (!HandleData)
	{
		// Create kinematic actor we are going to create joint with. This will be moved around with calls to SetLocation/SetRotation.
		PxRigidDynamic* KinActor = Scene->getPhysics().createRigidDynamic(KinPose);
		KinActor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);
		KinActor->setMass(1.0f);
		KinActor->setMassSpaceInertiaTensor(PxVec3(1.0f, 1.0f, 1.0f));

		// No bodyinstance
		KinActor->userData = NULL;

		// Add to Scene
		Scene->addActor(*KinActor);

		// Save reference to the kinematic actor.
		KinActorData = KinActor;
		
		// Create the joint
		PxVec3 LocalHandlePos = GrabbedActorPose.transformInv(KinLocation);
		PxD6Joint* NewJoint = PxD6JointCreate(Scene->getPhysics(), KinActor, PxTransform::createIdentity(), Actor, PxTransform(LocalHandlePos));

		if(!NewJoint)
		{
			HandleData = 0;
		}
		else
		{
			// No constraint instance
			NewJoint->userData = NULL;
			HandleData = NewJoint;

			// Remember the scene index that the handle joint/actor are in.
			FPhysScene* RBScene = FPhysxUserData::Get<FPhysScene>(Scene->userData);
			const uint32 SceneType = InComponent->BodyInstance.UseAsyncScene() ? PST_Async : PST_Sync;
			SceneIndex = RBScene->PhysXSceneIndex[SceneType];

			// Setting up the joint
			NewJoint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
			NewJoint->setMotion(PxD6Axis::eY, PxD6Motion::eFREE);
			NewJoint->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE);

			NewJoint->setDrive(PxD6Drive::eX, PxD6JointDrive(LinearStiffness, LinearDamping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION));
			NewJoint->setDrive(PxD6Drive::eY, PxD6JointDrive(LinearStiffness, LinearDamping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION));
			NewJoint->setDrive(PxD6Drive::eZ, PxD6JointDrive(LinearStiffness, LinearDamping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION));
			NewJoint->setDrivePosition(PxTransform(PxVec3(0,0,0)));


			NewJoint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
			NewJoint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
			NewJoint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
			
			bRotationConstrained = bConstrainRotation;
			
			if (bRotationConstrained)
			{
				NewJoint->setDrive(PxD6Drive::eSLERP, PxD6JointDrive(AngularStiffness, AngularDamping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION));

				//NewJoint->setDrive(PxD6Drive::eTWIST, PxD6JointDrive(AngularStiffness, AngularDamping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION));
				//NewJoint->setDrive(PxD6Drive::eSWING, PxD6JointDrive(AngularStiffness, AngularDamping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION));
				
				//PosJointDesc.setGlobalAxis(NxVec3(0,0,1));
			}

		}
	
	}
#endif // WITH_PHYSX


	GrabbedComponent = InComponent;
	GrabbedBoneName = InBoneName;
}
void UDestructibleComponent::CreatePhysicsState()
{
	// to avoid calling PrimitiveComponent, I'm just calling ActorComponent::CreatePhysicsState
	// @todo lh - fix me based on the discussion with Bryan G
 	UActorComponent::CreatePhysicsState();
	bPhysicsStateCreated = true;

	// What we want to do with BodySetup is simply use it to store a PhysicalMaterial, and possibly some other relevant fields.  Set up pointers from the BodyInstance to the BodySetup and this component
	UBodySetup* BodySetup = GetBodySetup();
	BodyInstance.OwnerComponent	= this;
	BodyInstance.BodySetup = BodySetup;
	BodyInstance.InstanceBodyIndex = 0;

#if WITH_APEX
	if( SkeletalMesh == NULL )
	{
		return;
	}

	FPhysScene* PhysScene = World->GetPhysicsScene();
	check(PhysScene);

	if( GApexModuleDestructible == NULL )
	{
		UE_LOG(LogPhysics, Log, TEXT("UDestructibleComponent::CreatePhysicsState(): APEX must be enabled to init UDestructibleComponent physics.") );
		return;
	}

	if( ApexDestructibleActor != NULL )
	{
		UE_LOG(LogPhysics, Log, TEXT("UDestructibleComponent::CreatePhysicsState(): NxDestructibleActor already created.") );
		return;
	}

	UDestructibleMesh* TheDestructibleMesh = GetDestructibleMesh();
	if( TheDestructibleMesh == NULL || TheDestructibleMesh->ApexDestructibleAsset == NULL)
	{
		UE_LOG(LogPhysics, Log, TEXT("UDestructibleComponent::CreatePhysicsState(): No DestructibleMesh or missing ApexDestructibleAsset.") );
		return;
	}

	int32 ChunkCount = TheDestructibleMesh->ApexDestructibleAsset->getChunkCount();
	// Ensure the chunks start off invisible.  RefreshBoneTransforms should make them visible.
	for (int32 ChunkIndex = 0; ChunkIndex < ChunkCount; ++ChunkIndex)
	{
		SetChunkVisible(ChunkIndex, false);
	}

#if WITH_EDITOR
	if (GIsEditor && !World->IsGameWorld())
	{
		// In the editor, only set the 0 chunk to be visible.
		if (TheDestructibleMesh->ApexDestructibleAsset->getChunkCount() > 0)
		{
			SetChunkVisible(0, true);
		}
		return;
	}
#endif	// WITH_EDITOR

	// Only create physics in the game
	if( !World->IsGameWorld() )
	{
		return;
	}

	// Set template actor/body/shape properties

	// Find the PhysicalMaterial we need to apply to the physics bodies.
	UPhysicalMaterial* PhysMat = BodyInstance.GetSimplePhysicalMaterial();

	// Get the default actor descriptor NxParameterized data from the asset
	NxParameterized::Interface* ActorParams = TheDestructibleMesh->GetDestructibleActorDesc(PhysMat);

	// Create PhysX transforms from ComponentToWorld
	const PxMat44 GlobalPose(PxMat33(U2PQuat(ComponentToWorld.GetRotation())), U2PVector(ComponentToWorld.GetTranslation()));
	const PxVec3 Scale = U2PVector(ComponentToWorld.GetScale3D());

	// Set the transform in the actor descriptor
	verify( NxParameterized::setParamMat44(*ActorParams,"globalPose",GlobalPose) );
	verify( NxParameterized::setParamVec3(*ActorParams,"scale",Scale) );

	// Set the (initially) dynamic flag in the actor descriptor
	// See if we are 'static'
	verify( NxParameterized::setParamBool(*ActorParams,"dynamic", BodyInstance.bSimulatePhysics != false) );

	// Set the sleep velocity frame decay constant (was sleepVelocitySmoothingFactor) - a new feature that should help sleeping in large piles
	verify( NxParameterized::setParamF32(*ActorParams,"sleepVelocityFrameDecayConstant", 20.0f) );

	// Set up the shape desc template

	// Get collision channel and response
	PxFilterData PQueryFilterData, PSimFilterData;
	uint8 MoveChannel = GetCollisionObjectType();
	FCollisionResponseContainer CollResponse;
	if(IsCollisionEnabled())
	{
		// Only enable a collision response if collision is enabled
		CollResponse = GetCollisionResponseToChannels();

		ChunkCollisionResponse.SetCollisionResponseContainer(CollResponse);
		ChunkCollisionResponse.SetResponse(ECC_Pawn, ECR_Overlap);
	}
	else
	{
		// now since by default it will all block, if collision is disabled, we need to set to ignore
		MoveChannel = ECC_WorldStatic;
		CollResponse.SetAllChannels(ECR_Ignore);
		ChunkCollisionResponse.SetAllChannels(ECR_Ignore);
	}

	// Passing AssetInstanceID = 0 so we'll have self-collision
	AActor* Owner = GetOwner();
	CreateShapeFilterData(MoveChannel, (Owner ? Owner->GetUniqueID() : 0), CollResponse, 0, 0, PQueryFilterData, PSimFilterData, BodyInstance.bUseCCD, BodyInstance.bNotifyRigidBodyCollision, false);

	// Build filterData variations for complex and simple
	PSimFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision;
	PQueryFilterData.word3 |= EPDF_SimpleCollision | EPDF_ComplexCollision;

	// Set the filterData in the shape descriptor
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word0", PSimFilterData.word0 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word1", PSimFilterData.word1 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word2", PSimFilterData.word2 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.simulationFilterData.word3", PSimFilterData.word3 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word0", PQueryFilterData.word0 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word1", PQueryFilterData.word1 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word2", PQueryFilterData.word2 ) );
	verify( NxParameterized::setParamU32(*ActorParams,"p3ShapeDescTemplate.queryFilterData.word3", PQueryFilterData.word3 ) );

	// Set the PhysX material in the shape descriptor
	PxMaterial* PMaterial = PhysMat->GetPhysXMaterial();
	verify( NxParameterized::setParamU64(*ActorParams,"p3ShapeDescTemplate.material", (physx::PxU64)PMaterial) );

	// Set the rest depth to match the skin width in the shape descriptor
	const physx::PxCookingParams& CookingParams = GApexSDK->getCookingInterface()->getParams();
	verify( NxParameterized::setParamF32(*ActorParams,"p3ShapeDescTemplate.restOffset", -CookingParams.skinWidth) );

	// Set the PhysX material in the actor descriptor
	verify( NxParameterized::setParamBool(*ActorParams,"p3ActorDescTemplate.flags.eDISABLE_GRAVITY",false) );
	verify( NxParameterized::setParamBool(*ActorParams,"p3ActorDescTemplate.flags.eVISUALIZATION",true) );

	// Set the PxActor's and PxShape's userData fields to this component's body instance
	verify( NxParameterized::setParamU64(*ActorParams,"p3ActorDescTemplate.userData", 0 ) );

	// All shapes created by this DestructibleActor will have the userdata of the owning component.
	// We need this, as in some cases APEX is moving shapes accross actors ( ex. FormExtended structures )
	verify( NxParameterized::setParamU64(*ActorParams,"p3ShapeDescTemplate.userData", (PxU64)&PhysxUserData ) );

	// Set up the body desc template in the actor descriptor
	verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.angularDamping", BodyInstance.AngularDamping ) );
	verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.linearDamping", BodyInstance.LinearDamping ) );
	const PxTolerancesScale& PScale = GPhysXSDK->getTolerancesScale();
	PxF32 SleepEnergyThreshold = 0.00005f*PScale.speed*PScale.speed;	// 1/1000 Default, since the speed scale is quite high
	if (BodyInstance.SleepFamily == SF_Sensitive)
	{
		SleepEnergyThreshold /= 20.0f;
	}
	verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.sleepThreshold", SleepEnergyThreshold) );
//	NxParameterized::setParamF32(*ActorParams,"bodyDescTemplate.sleepDamping", SleepDamping );
	verify( NxParameterized::setParamF32(*ActorParams,"p3BodyDescTemplate.density", 0.001f*PhysMat->Density) );	// Convert from g/cm^3 to kg/cm^3
	// Enable CCD if requested
	verify( NxParameterized::setParamBool(*ActorParams,"p3BodyDescTemplate.flags.eENABLE_CCD", BodyInstance.bUseCCD != 0) );
	// Ask the actor to create chunk events, for more efficient visibility updates
	verify( NxParameterized::setParamBool(*ActorParams,"createChunkEvents", true) );

	// Enable hard sleeping if requested
	verify( NxParameterized::setParamBool(*ActorParams,"useHardSleeping", bEnableHardSleeping) );

	// Destructibles are always dynamic or kinematic, and therefore only go into one of the scenes
	const uint32 SceneType = BodyInstance.UseAsyncScene() ? PST_Async : PST_Sync;
	NxApexScene* ApexScene = PhysScene->GetApexScene(SceneType);
	check(ApexScene);

	// Create an APEX NxDestructibleActor from the Destructible asset and actor descriptor
	ApexDestructibleActor = static_cast<NxDestructibleActor*>(TheDestructibleMesh->ApexDestructibleAsset->createApexActor(*ActorParams, *ApexScene));
	check(ApexDestructibleActor);

	// Make a backpointer to this component
	PhysxUserData = FPhysxUserData(this);
	ApexDestructibleActor->userData = &PhysxUserData;

	// Setup chunk user data arrays. We have to make sure PhysxChunkUserData will not be reallocated when growing, so we 
	// reserver ChunkCount here already
	ChunkInfos.Empty(ChunkCount);
	PhysxChunkUserData.Empty(ChunkCount);

	// Cache cooked collision data
	// BRGTODO : cook in asset
	ApexDestructibleActor->cacheModuleData();

	// BRGTODO : Per-actor LOD setting
//	ApexDestructibleActor->forcePhysicalLod( DestructibleActor->LOD );

	// Start asleep if requested
	PxRigidDynamic* PRootActor = ApexDestructibleActor->getChunkPhysXActor(0);
	//  Put to sleep or wake up only if the component is physics-simulated
	if (PRootActor != NULL && BodyInstance.bSimulatePhysics)
	{
		SCOPED_SCENE_WRITE_LOCK(PRootActor->getScene());

		// Sleep/wake up as appropriate
		if (BodyInstance.bStartAwake)
		{
			PRootActor->wakeUp();
		}
		else
		{
			PRootActor->putToSleep();
		}
	}

	UpdateBounds();
#endif	// #if WITH_APEX
}