void UDestructibleComponent::SetChunkVisible( int32 ChunkIndex, bool bVisible ) { #if WITH_APEX // Bone 0 is a dummy root bone const int32 BoneIndex = ChunkIdxToBoneIdx(ChunkIndex); if( bVisible ) { UnHideBone(BoneIndex); if (NULL != ApexDestructibleActor) { physx::PxShape** PShapes; const physx::PxU32 PShapeCount = ApexDestructibleActor->getChunkPhysXShapes(PShapes, ChunkIndex); if (PShapeCount > 0) { const physx::PxMat44 ChunkPoseRT = ApexDestructibleActor->getChunkPose(ChunkIndex); // Unscaled const physx::PxTransform Transform(ChunkPoseRT); SetChunkWorldRT(ChunkIndex, P2UQuat(Transform.q), P2UVector(Transform.p)); } } } else { HideBone(BoneIndex, PBO_None); } // Mark the transform as dirty, so the bounds are updated and sent to the render thread MarkRenderTransformDirty(); // New bone positions need to be sent to render thread MarkRenderDynamicDataDirty(); #endif }
FTransform P2UTransform(const PxTransform& PTM) { FQuat UQuat = P2UQuat(PTM.q); FVector UPos = P2UVector(PTM.p); FTransform Result = FTransform(UQuat, UPos); return Result; }
FMatrix PTransform2UMatrix(const PxTransform& PTM) { FQuat UQuat = P2UQuat(PTM.q); FVector UPos = P2UVector(PTM.p); FMatrix Result = FQuatRotationTranslationMatrix(UQuat, UPos); return Result; }
void UDestructibleComponent::RefreshBoneTransforms() { #if WITH_APEX if(ApexDestructibleActor != NULL && SkeletalMesh) { UDestructibleMesh* TheDestructibleMesh = GetDestructibleMesh(); // Save a pointer to the APEX NxDestructibleAsset physx::NxDestructibleAsset* ApexDestructibleAsset = TheDestructibleMesh->ApexDestructibleAsset; check(ApexDestructibleAsset); { // Lock here so we don't encounter race conditions with the destruction processing FPhysScene* PhysScene = World->GetPhysicsScene(); check(PhysScene); const uint32 SceneType = (BodyInstance.bUseAsyncScene && PhysScene->HasAsyncScene()) ? PST_Async : PST_Sync; PxScene* PScene = PhysScene->GetPhysXScene(SceneType); check(PScene); SCOPED_SCENE_WRITE_LOCK(PScene); SCOPED_SCENE_READ_LOCK(PScene); // Try to acquire event buffer const physx::NxDestructibleChunkEvent* EventBuffer; physx::PxU32 EventBufferSize; if (ApexDestructibleActor->acquireChunkEventBuffer(EventBuffer, EventBufferSize)) { // Buffer acquired while (EventBufferSize--) { const physx::NxDestructibleChunkEvent& Event = *EventBuffer++; // Right now the only events are visibility changes. So as an optimization we won't check for the event type. // if (Event.event & physx::NxDestructibleChunkEvent::VisibilityChanged) const bool bVisible = (Event.event & physx::NxDestructibleChunkEvent::ChunkVisible) != 0; SetChunkVisible(Event.chunkIndex, bVisible); } // Release buffer (will be cleared) ApexDestructibleActor->releaseChunkEventBuffer(); } } // Update poses for visible chunks const physx::PxU16* VisibleChunks = ApexDestructibleActor->getVisibleChunks(); physx::PxU16 VisibleChunkCount = ApexDestructibleActor->getNumVisibleChunks(); while (VisibleChunkCount--) { const physx::PxU16 ChunkIndex = *VisibleChunks++; // BRGTODO : Make a direct method to access the Px objects' quats const physx::PxMat44 ChunkPoseRT = ApexDestructibleActor->getChunkPose(ChunkIndex); // Unscaled const physx::PxTransform Transform(ChunkPoseRT); SetChunkWorldRT(ChunkIndex, P2UQuat(Transform.q), P2UVector(Transform.p)); } // Send bones to render thread at end of frame MarkRenderDynamicDataDirty(); } #endif // #if WITH_APEX }