本文整理汇总了C++中PxTransform::isValid方法的典型用法代码示例。如果您正苦于以下问题:C++ PxTransform::isValid方法的具体用法?C++ PxTransform::isValid怎么用?C++ PxTransform::isValid使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类PxTransform
的用法示例。
在下文中一共展示了PxTransform::isValid方法的14个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: SetKinematicTarget
void FPhysScene::SetKinematicTarget(FBodyInstance * BodyInstance, const FTransform & TargetTransform)
{
TargetTransform.DiagnosticCheckNaN_All();
#if WITH_PHYSX
if (PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic())
{
#if WITH_SUBSTEPPING
if (IsSubstepping())
{
FPhysSubstepTask * PhysSubStepper = PhysSubSteppers[SceneType(BodyInstance)];
PhysSubStepper->SetKinematicTarget(BodyInstance, TargetTransform);
}
else
#endif
{
const PxTransform PNewPose = U2PTransform(TargetTransform);
check(PNewPose.isValid());
SCOPED_SCENE_WRITE_LOCK(PRigidDynamic->getScene());
PRigidDynamic->setKinematicTarget(PNewPose);
}
}
#endif
}
示例2: InterpolateKinematicActor_AssumesLocked
/** Interpolates kinematic actor transform - Assumes caller has obtained writer lock */
void FPhysSubstepTask::InterpolateKinematicActor_AssumesLocked(const FPhysTarget& PhysTarget, FBodyInstance* BodyInstance, float InAlpha)
{
#if WITH_PHYSX
PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic_AssumesLocked();
InAlpha = FMath::Clamp(InAlpha, 0.f, 1.f);
/** Interpolate kinematic actors */
if (PhysTarget.bKinematicTarget)
{
//It's possible that the actor is no longer kinematic and is now simulating. In that case do nothing
if (!BodyInstance->IsNonKinematic())
{
const FKinematicTarget& KinematicTarget = PhysTarget.KinematicTarget;
const FTransform& TargetTM = KinematicTarget.TargetTM;
const FTransform& StartTM = KinematicTarget.OriginalTM;
FTransform InterTM = FTransform::Identity;
InterTM.SetLocation(FMath::Lerp(StartTM.GetLocation(), TargetTM.GetLocation(), InAlpha));
InterTM.SetRotation(FMath::Lerp(StartTM.GetRotation(), TargetTM.GetRotation(), InAlpha));
const PxTransform PNewPose = U2PTransform(InterTM);
check(PNewPose.isValid());
PRigidDynamic->setKinematicTarget(PNewPose);
}
}
#endif
}
示例3: InterpolateKinematicActor
/** Interpolates kinematic actor transform - Assumes caller has obtained writer lock */
void FPhysSubstepTask::InterpolateKinematicActor(const FPhysTarget & PhysTarget, FBodyInstance * BodyInstance, float Alpha)
{
#if WITH_PHYSX
PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic();
Alpha = FMath::Clamp(Alpha, 0.f, 1.f);
/** Interpolate kinematic actors */
if (PhysTarget.bKinematicTarget)
{
//We should only be interpolating kinematic actors
check(!IsRigidDynamicNonKinematic(PRigidDynamic));
const FKinematicTarget & KinematicTarget = PhysTarget.KinematicTarget;
const FTransform & TargetTM = KinematicTarget.TargetTM;
const FTransform & StartTM = KinematicTarget.OriginalTM;
FTransform InterTM = FTransform::Identity;
InterTM.SetLocation(FMath::Lerp(StartTM.GetLocation(), TargetTM.GetLocation(), Alpha));
InterTM.SetRotation(FMath::Lerp(StartTM.GetRotation(), TargetTM.GetRotation(), Alpha));
const PxTransform PNewPose = U2PTransform(InterTM);
check(PNewPose.isValid());
PRigidDynamic->setKinematicTarget(PNewPose);
}
#endif
}
示例4: AddConvexElemsToRigidActor_AssumesLocked
void AddConvexElemsToRigidActor_AssumesLocked() const
{
float ContactOffsetFactor, MaxContactOffset;
GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset);
for (int32 i = 0; i < BodySetup->AggGeom.ConvexElems.Num(); i++)
{
const FKConvexElem& ConvexElem = BodySetup->AggGeom.ConvexElems[i];
if (ConvexElem.ConvexMesh)
{
PxTransform PLocalPose;
bool bUseNegX = CalcMeshNegScaleCompensation(Scale3D, PLocalPose);
PxConvexMeshGeometry PConvexGeom;
PConvexGeom.convexMesh = bUseNegX ? ConvexElem.ConvexMeshNegX : ConvexElem.ConvexMesh;
PConvexGeom.scale.scale = U2PVector(Scale3DAbs * ConvexElem.GetTransform().GetScale3D().GetAbs());
FTransform ConvexTransform = ConvexElem.GetTransform();
if (ConvexTransform.GetScale3D().X < 0 || ConvexTransform.GetScale3D().Y < 0 || ConvexTransform.GetScale3D().Z < 0)
{
UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has negative scale. Not currently supported"), *GetPathNameSafe(BodySetup->GetOuter()), i);
}
if (ConvexTransform.IsValid())
{
PxTransform PElementTransform = U2PTransform(ConvexTransform * RelativeTM);
PLocalPose.q *= PElementTransform.q;
PLocalPose.p = PElementTransform.p;
PLocalPose.p.x *= Scale3D.X;
PLocalPose.p.y *= Scale3D.Y;
PLocalPose.p.z *= Scale3D.Z;
if (PConvexGeom.isValid())
{
PxVec3 PBoundsExtents = PConvexGeom.convexMesh->getLocalBounds().getExtents();
ensure(PLocalPose.isValid());
{
const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PBoundsExtents.minElement());
AttachShape_AssumesLocked(PConvexGeom, PLocalPose, ContactOffset);
}
}
else
{
UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] invalid"), *GetPathNameSafe(BodySetup->GetOuter()), i);
}
}
else
{
UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has invalid transform"), *GetPathNameSafe(BodySetup->GetOuter()), i);
}
}
else
{
UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: ConvexElem is missing ConvexMesh (%d: %s)"), i, *BodySetup->GetPathName());
}
}
}
示例5: AddTriMeshToRigidActor
void UBodySetup::AddTriMeshToRigidActor(PxRigidActor* PDestActor, const FVector& Scale3D, const FVector& Scale3DAbs) const
{
float ContactOffsetFactor, MaxContactOffset;
GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset);
PxMaterial* PDefaultMat = GetDefaultPhysMaterial();
if(TriMesh || TriMeshNegX)
{
PxTransform PLocalPose;
bool bUseNegX = CalcMeshNegScaleCompensation(Scale3D, PLocalPose);
// Only case where TriMeshNegX should be null is BSP, which should not require negX version
if (bUseNegX && TriMeshNegX == NULL)
{
UE_LOG(LogPhysics, Log, TEXT("AddTriMeshToRigidActor: Want to use NegX but it doesn't exist! %s"), *GetPathName());
}
PxTriangleMesh* UseTriMesh = bUseNegX ? TriMeshNegX : TriMesh;
if (UseTriMesh != NULL)
{
PxTriangleMeshGeometry PTriMeshGeom;
PTriMeshGeom.triangleMesh = bUseNegX ? TriMeshNegX : TriMesh;
PTriMeshGeom.scale.scale = U2PVector(Scale3DAbs);
if (bDoubleSidedGeometry)
{
PTriMeshGeom.meshFlags |= PxMeshGeometryFlag::eDOUBLE_SIDED;
}
if (PTriMeshGeom.isValid())
{
ensure(PLocalPose.isValid());
// Create without 'sim shape' flag, problematic if it's kinematic, and it gets set later anyway.
PxShape* NewShape = PDestActor->createShape(PTriMeshGeom, *PDefaultMat, PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eVISUALIZATION);
if (NewShape)
{
NewShape->setLocalPose(PLocalPose);
NewShape->setContactOffset(MaxContactOffset);
}
else
{
UE_LOG(LogPhysics, Log, TEXT("Can't create new mesh shape in AddShapesToRigidActor"));
}
}
else
{
UE_LOG(LogPhysics, Log, TEXT("AddTriMeshToRigidActor: TriMesh invalid"));
}
}
}
}
示例6: sweep
void NpBatchQuery::sweep(
const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, PxU16 maxTouchHits,
PxHitFlags hitFlags, const PxQueryFilterData& fd, void* userData, const PxQueryCache* cache, const PxReal inflation)
{
PX_CHECK_AND_RETURN(pose.isValid(), "Batch sweep input check: pose is not valid.");
PX_CHECK_AND_RETURN(unitDir.isFinite(), "Batch sweep input check: unitDir is not valid.");
PX_CHECK_AND_RETURN(unitDir.isNormalized(), "Batch sweep input check: direction must be normalized");
PX_CHECK_AND_RETURN(distance >= 0.0f, "Batch sweep input check: distance cannot be negative");
PX_CHECK_AND_RETURN(distance != 0.0f || !(hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP),
"Batch sweep input check: zero-length sweep only valid without the PxHitFlag::eASSUME_NO_INITIAL_OVERLAP flag");
if (mNbSweeps >= mDesc.queryMemory.getMaxSweepsPerExecute())
{
PX_CHECK_AND_RETURN(mNbSweeps < mDesc.queryMemory.getMaxSweepsPerExecute(),
"PxBatchQuery: number of sweep() calls exceeds PxBatchQueryMemory::sweepResultBufferSize, query discarded");
return;
}
CHECK_RUNNING("PxBatchQuery::sweep: This batch is still executing, skipping query.")
mNbSweeps++;
writeBatchHeader(BatchStreamHeader(hitFlags, cache, fd, userData, maxTouchHits, QTypeROS::eSWEEP));
//set the MTD flag
mHasMtdSweep |= !!(hitFlags & PxHitFlag::eMTD);
if((hitFlags & PxHitFlag::ePRECISE_SWEEP) && (hitFlags & PxHitFlag::eMTD))
{
Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " Precise sweep doesn't support MTD. Perform MTD with default sweep");
hitFlags &= ~PxHitFlag::ePRECISE_SWEEP;
}
if((hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP) && (hitFlags & PxHitFlag::eMTD))
{
Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " eMTD cannot be used in conjunction with eASSUME_NO_INITIAL_OVERLAP. eASSUME_NO_INITIAL_OVERLAP will be ignored");
hitFlags &= ~PxHitFlag::eASSUME_NO_INITIAL_OVERLAP;
}
PxReal realInflation = inflation;
if((hitFlags & PxHitFlag::ePRECISE_SWEEP)&& inflation > 0.f)
{
realInflation = 0.f;
Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " Precise sweep doesn't support inflation, inflation will be overwritten to be zero");
}
writeQueryInput(mStream, MultiQueryInput(&geometry, &pose, unitDir, distance, realInflation));
Ps::atomicExchange(&mBatchQueryIsRunning, 0);
}
示例7: AddTriMeshToRigidActor_AssumesLocked
void AddTriMeshToRigidActor_AssumesLocked() const
{
float ContactOffsetFactor, MaxContactOffset;
GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset);
if (BodySetup->TriMesh || BodySetup->TriMeshNegX)
{
PxTransform PLocalPose;
bool bUseNegX = CalcMeshNegScaleCompensation(Scale3D, PLocalPose);
// Only case where TriMeshNegX should be null is BSP, which should not require negX version
if (bUseNegX && BodySetup->TriMeshNegX == NULL)
{
UE_LOG(LogPhysics, Log, TEXT("AddTriMeshToRigidActor: Want to use NegX but it doesn't exist! %s"), *BodySetup->GetPathName());
}
PxTriangleMesh* UseTriMesh = bUseNegX ? BodySetup->TriMeshNegX : BodySetup->TriMesh;
if (UseTriMesh != NULL)
{
PxTriangleMeshGeometry PTriMeshGeom;
PTriMeshGeom.triangleMesh = bUseNegX ? BodySetup->TriMeshNegX : BodySetup->TriMesh;
PTriMeshGeom.scale.scale = U2PVector(Scale3DAbs);
if (BodySetup->bDoubleSidedGeometry)
{
PTriMeshGeom.meshFlags |= PxMeshGeometryFlag::eDOUBLE_SIDED;
}
if (PTriMeshGeom.isValid())
{
ensure(PLocalPose.isValid());
// Create without 'sim shape' flag, problematic if it's kinematic, and it gets set later anyway.
{
if (!AttachShape_AssumesLocked(PTriMeshGeom, PLocalPose, MaxContactOffset, PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eVISUALIZATION))
{
UE_LOG(LogPhysics, Log, TEXT("Can't create new mesh shape in AddShapesToRigidActor"));
}
}
}
else
{
UE_LOG(LogPhysics, Log, TEXT("AddTriMeshToRigidActor: TriMesh invalid"));
}
}
}
}
示例8: setGlobalPose
void NpArticulationLink::setGlobalPose(const PxTransform& pose, bool autowake)
{
NpScene* scene = NpActor::getOwnerScene(*this);
PX_CHECK_AND_RETURN(pose.isValid(), "NpArticulationLink::setGlobalPose pose is not valid.");
NP_WRITE_CHECK(scene);
#if PX_CHECKED
if(scene)
scene->checkPositionSanity(*this, pose, "PxArticulationLink::setGlobalPose");
#endif
PxTransform body2World = pose * getScbBodyFast().getBody2Actor();
getScbBodyFast().setBody2World(body2World, false);
if (scene && autowake)
mRoot->wakeUpInternal(false, true);
}
示例9: overlap
void NpBatchQuery::overlap(
const PxGeometry& geometry, const PxTransform& pose, PxU16 maxTouchHits,
const PxQueryFilterData& fd, void* userData, const PxQueryCache* cache)
{
PX_CHECK_AND_RETURN(pose.isValid(), "NpBatchQuery::overlapMultiple pose is not valid.");
if (mNbOverlaps >= mDesc.queryMemory.getMaxOverlapsPerExecute())
{
PX_CHECK_AND_RETURN(mNbOverlaps < mDesc.queryMemory.getMaxOverlapsPerExecute(),
"PxBatchQuery: number of overlap() calls exceeds PxBatchQueryMemory::overlapResultBufferSize, query discarded");
return;
}
CHECK_RUNNING("PxBatchQuery::overlap: This batch is still executing, skipping query.")
mNbOverlaps++;
writeBatchHeader(BatchStreamHeader(PxHitFlags(), cache, fd, userData, maxTouchHits, QTypeROS::eOVERLAP));
writeQueryInput(mStream, MultiQueryInput(&geometry, &pose));
Ps::atomicExchange(&mBatchQueryIsRunning, 0);
}
示例10: SetKinematicTarget_AssumesLocked
void FPhysScene::SetKinematicTarget_AssumesLocked(FBodyInstance* BodyInstance, const FTransform& TargetTransform, bool bAllowSubstepping)
{
TargetTransform.DiagnosticCheckNaN_All();
#if WITH_PHYSX
if (PxRigidDynamic * PRigidDynamic = BodyInstance->GetPxRigidDynamic_AssumesLocked())
{
#if WITH_SUBSTEPPING
uint32 BodySceneType = SceneType_AssumesLocked(BodyInstance);
if (bAllowSubstepping && IsSubstepping(BodySceneType))
{
FPhysSubstepTask * PhysSubStepper = PhysSubSteppers[BodySceneType];
PhysSubStepper->SetKinematicTarget_AssumesLocked(BodyInstance, TargetTransform);
}
else
#endif
{
const PxTransform PNewPose = U2PTransform(TargetTransform);
check(PNewPose.isValid());
PRigidDynamic->setKinematicTarget(PNewPose);
}
}
#endif
}
示例11: capsuleGeom
bool physx::PxMeshQuery::sweep( const PxVec3& unitDir, const PxReal maxDistance,
const PxGeometry& geom, const PxTransform& pose,
PxU32 triangleCount, const PxTriangle* triangles,
PxSweepHit& sweepHit, PxHitFlags hintFlags_,
const PxU32* cachedIndex, const PxReal inflation, bool doubleSided)
{
PX_SIMD_GUARD;
PX_CHECK_AND_RETURN_VAL(pose.isValid(), "Gu::GeometryQuery::sweep(): pose is not valid.", false);
PX_CHECK_AND_RETURN_VAL(unitDir.isFinite(), "Gu::GeometryQuery::sweep(): unitDir is not valid.", false);
PX_CHECK_AND_RETURN_VAL(PxIsFinite(maxDistance), "Gu::GeometryQuery::sweep(): distance is not valid.", false);
PX_CHECK_AND_RETURN_VAL(maxDistance > 0, "Gu::GeometryQuery::sweep(): sweep distance must be greater than 0.", false);
const PxReal distance = PxMin(maxDistance, PX_MAX_SWEEP_DISTANCE);
// PT: the doc says that validity flags are not used, but internally some functions still check them. So
// to make sure the code works even when no validity flags are passed, we set them all here.
const PxHitFlags hintFlags = hintFlags_ | PxHitFlag::ePOSITION|PxHitFlag::eNORMAL|PxHitFlag::eDISTANCE;
switch(geom.getType())
{
case PxGeometryType::eSPHERE:
{
const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom);
// PT: TODO: technically this capsule with 0.0 half-height is invalid ("isValid" returns false)
const PxCapsuleGeometry capsuleGeom(sphereGeom.radius, 0.0f);
return SweepCapsuleTriangles( triangleCount, triangles, doubleSided, capsuleGeom, pose, unitDir, distance,
cachedIndex, sweepHit.position, sweepHit.normal, sweepHit.distance, sweepHit.faceIndex, inflation, hintFlags);
}
case PxGeometryType::eCAPSULE:
{
const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom);
return SweepCapsuleTriangles( triangleCount, triangles, doubleSided, capsuleGeom, pose, unitDir, distance,
cachedIndex, sweepHit.position, sweepHit.normal, sweepHit.distance, sweepHit.faceIndex, inflation, hintFlags);
}
case PxGeometryType::eBOX:
{
const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom);
if(!PX_IS_SPU && (hintFlags & PxHitFlag::ePRECISE_SWEEP))
{
return sweepCCTBoxTriangles(triangleCount, triangles, doubleSided, boxGeom, pose,
unitDir, distance, sweepHit.position, sweepHit.normal, sweepHit.distance,
sweepHit.faceIndex, cachedIndex, inflation, hintFlags);
}
else
{
return SweepBoxTriangles( triangleCount, triangles, doubleSided, boxGeom, pose,
unitDir, distance, sweepHit.position, sweepHit.normal, sweepHit.distance,
sweepHit.faceIndex, cachedIndex, inflation, hintFlags);
}
}
case PxGeometryType::ePLANE:
case PxGeometryType::eCONVEXMESH:
case PxGeometryType::eTRIANGLEMESH:
case PxGeometryType::eHEIGHTFIELD:
case PxGeometryType::eGEOMETRY_COUNT:
case PxGeometryType::eINVALID:
default :
PX_CHECK_MSG(false, "Gu::GeometryQuery::sweep(): geometry object parameter must be sphere, capsule or box geometry.");
}
return false;
}
示例12:
void D6Joint::setDrivePosition(const PxTransform& pose)
{
PX_CHECK_AND_RETURN(pose.isValid(), "PxD6Joint::setDrivePosition: pose invalid");
data().drivePosition = pose;
markDirty();
}
示例13: AddConvexElemsToRigidActor
void UBodySetup::AddConvexElemsToRigidActor(PxRigidActor* PDestActor, const FTransform& RelativeTM, const FVector& Scale3D, const FVector& Scale3DAbs, TArray<PxShape*>* NewShapes) const
{
float ContactOffsetFactor, MaxContactOffset;
GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset);
PxMaterial* PDefaultMat = GetDefaultPhysMaterial();
for (int32 i = 0; i < AggGeom.ConvexElems.Num(); i++)
{
const FKConvexElem& ConvexElem = AggGeom.ConvexElems[i];
if (ConvexElem.ConvexMesh)
{
PxTransform PLocalPose;
bool bUseNegX = CalcMeshNegScaleCompensation(Scale3D, PLocalPose);
PxConvexMeshGeometry PConvexGeom;
PConvexGeom.convexMesh = bUseNegX ? ConvexElem.ConvexMeshNegX : ConvexElem.ConvexMesh;
PConvexGeom.scale.scale = U2PVector(Scale3DAbs * ConvexElem.GetTransform().GetScale3D().GetAbs());
FTransform ConvexTransform = ConvexElem.GetTransform();
if (ConvexTransform.GetScale3D().X < 0 || ConvexTransform.GetScale3D().Y < 0 || ConvexTransform.GetScale3D().Z < 0)
{
UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has negative scale. Not currently supported"), *GetPathNameSafe(GetOuter()), i);
}
if (ConvexTransform.IsValid())
{
PxTransform PElementTransform = U2PTransform(ConvexTransform * RelativeTM);
PLocalPose.q *= PElementTransform.q;
PLocalPose.p = PElementTransform.p;
PLocalPose.p.x *= Scale3D.X;
PLocalPose.p.y *= Scale3D.Y;
PLocalPose.p.z *= Scale3D.Z;
if (PConvexGeom.isValid())
{
PxVec3 PBoundsExtents = PConvexGeom.convexMesh->getLocalBounds().getExtents();
ensure(PLocalPose.isValid());
PxShape* NewShape = PDestActor->createShape(PConvexGeom, *PDefaultMat, PLocalPose);
if (NewShapes)
{
NewShapes->Add(NewShape);
}
const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PBoundsExtents.minElement());
NewShape->setContactOffset(ContactOffset);
}
else
{
UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] invalid"), *GetPathNameSafe(GetOuter()), i);
}
}
else
{
UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has invalid transform"), *GetPathNameSafe(GetOuter()), i);
}
}
else
{
UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: ConvexElem is missing ConvexMesh (%d: %s)"), i, *GetPathName());
}
}
}
示例14: UpdateKinematicBonesToAnim
//.........这里部分代码省略.........
if (bHasBodiesInAsyncScene)
{
SCENE_LOCK_WRITE(PhysScene->GetPhysXScene(PST_Async))
}
#endif
// Iterate over each body
for (int32 i = 0; i < Bodies.Num(); i++)
{
// If we have a physics body, and its kinematic...
FBodyInstance* BodyInst = Bodies[i];
check(BodyInst);
if (bTeleport || (BodyInst->IsValidBodyInstance() && !BodyInst->IsInstanceSimulatingPhysics()))
{
const int32 BoneIndex = BodyInst->InstanceBoneIndex;
// If we could not find it - warn.
if (BoneIndex == INDEX_NONE || BoneIndex >= GetNumSpaceBases())
{
const FName BodyName = PhysicsAsset->BodySetup[i]->BoneName;
UE_LOG(LogPhysics, Log, TEXT("UpdateRBBones: WARNING: Failed to find bone '%s' need by PhysicsAsset '%s' in SkeletalMesh '%s'."), *BodyName.ToString(), *PhysicsAsset->GetName(), *SkeletalMesh->GetName());
}
else
{
#if WITH_PHYSX
// update bone transform to world
const FTransform BoneTransform = InSpaceBases[BoneIndex] * CurrentLocalToWorld;
if(BoneTransform.ContainsNaN())
{
const FName BodyName = PhysicsAsset->BodySetup[i]->BoneName;
UE_LOG(LogPhysics, Warning, TEXT("UpdateKinematicBonesToAnim: Trying to set transform with bad data %s on PhysicsAsset '%s' in SkeletalMesh '%s' for bone '%s'"), *BoneTransform.ToHumanReadableString(), *PhysicsAsset->GetName(), *SkeletalMesh->GetName(), *BodyName.ToString());
continue;
}
// If kinematic and not teleporting, set kinematic target
PxRigidDynamic* PRigidDynamic = BodyInst->GetPxRigidDynamic_AssumesLocked();
if (!IsRigidBodyNonKinematic_AssumesLocked(PRigidDynamic) && !bTeleport)
{
PhysScene->SetKinematicTarget_AssumesLocked(BodyInst, BoneTransform, true);
}
// Otherwise, set global pose
else
{
const PxTransform PNewPose = U2PTransform(BoneTransform);
ensure(PNewPose.isValid());
PRigidDynamic->setGlobalPose(PNewPose);
}
#endif
// now update scale
// if uniform, we'll use BoneTranform
if (MeshScale3D.IsUniform())
{
// @todo UE4 should we update scale when it's simulated?
BodyInst->UpdateBodyScale(BoneTransform.GetScale3D());
}
else
{
// @note When you have non-uniform scale on mesh base,
// hierarchical bone transform can update scale too often causing performance issue
// So we just use mesh scale for all bodies when non-uniform
// This means physics representation won't be accurate, but
// it is performance friendly by preventing too frequent physics update
BodyInst->UpdateBodyScale(MeshScale3D);
}
}
}
else
{
//make sure you have physics weight or blendphysics on, otherwise, you'll have inconsistent representation of bodies
// @todo make this to be kismet log? But can be too intrusive
if (!bBlendPhysics && BodyInst->PhysicsBlendWeight <= 0.f && BodyInst->BodySetup.IsValid())
{
UE_LOG(LogPhysics, Warning, TEXT("%s(Mesh %s, PhysicsAsset %s, Bone %s) is simulating, but no blending. "),
*GetName(), *GetNameSafe(SkeletalMesh), *GetNameSafe(PhysicsAsset), *BodyInst->BodySetup.Get()->BoneName.ToString());
}
}
}
#if WITH_PHYSX
// Unlock the scenes
if (bHasBodiesInSyncScene)
{
SCENE_UNLOCK_WRITE(PhysScene->GetPhysXScene(PST_Sync))
}
if (bHasBodiesInAsyncScene)
{
SCENE_UNLOCK_WRITE(PhysScene->GetPhysXScene(PST_Async))
}
#endif
}
}
else
{
//per poly update requires us to update all vertex positions
if (MeshObject)