fixed joint crash when no lead entity is selected (#2867)
Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com>
This commit is contained in:
@@ -46,11 +46,26 @@ namespace PhysX
|
||||
|
||||
JointComponent::LeadFollowerInfo leadFollowerInfo;
|
||||
ObtainLeadFollowerInfo(leadFollowerInfo);
|
||||
if (!leadFollowerInfo.m_followerActor)
|
||||
if (leadFollowerInfo.m_followerActor == nullptr ||
|
||||
leadFollowerInfo.m_followerBody == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is no lead body, this will be a constraint of the follower's global position, so use invalid body handle.
|
||||
AzPhysics::SimulatedBodyHandle parentHandle = AzPhysics::InvalidSimulatedBodyHandle;
|
||||
if (leadFollowerInfo.m_leadBody != nullptr)
|
||||
{
|
||||
parentHandle = leadFollowerInfo.m_leadBody->m_bodyHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf(
|
||||
"PhysX", "Entity [%s] Ball Joint component missing lead entity. This joint will be a global constraint on the follower's global position.",
|
||||
GetEntity()->GetName().c_str());
|
||||
}
|
||||
|
||||
|
||||
BallJointConfiguration configuration;
|
||||
configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation();
|
||||
configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation();
|
||||
@@ -65,7 +80,7 @@ namespace PhysX
|
||||
m_jointHandle = sceneInterface->AddJoint(
|
||||
leadFollowerInfo.m_followerBody->m_sceneOwner,
|
||||
&configuration,
|
||||
leadFollowerInfo.m_leadBody->m_bodyHandle,
|
||||
parentHandle,
|
||||
leadFollowerInfo.m_followerBody->m_bodyHandle);
|
||||
m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner;
|
||||
}
|
||||
|
||||
@@ -54,11 +54,25 @@ namespace PhysX
|
||||
|
||||
JointComponent::LeadFollowerInfo leadFollowerInfo;
|
||||
ObtainLeadFollowerInfo(leadFollowerInfo);
|
||||
if (!leadFollowerInfo.m_followerActor)
|
||||
if (leadFollowerInfo.m_followerActor == nullptr ||
|
||||
leadFollowerInfo.m_followerBody == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is no lead body, this will be a constraint of the follower's global position, so use invalid body handle.
|
||||
AzPhysics::SimulatedBodyHandle parentHandle = AzPhysics::InvalidSimulatedBodyHandle;
|
||||
if (leadFollowerInfo.m_leadBody != nullptr)
|
||||
{
|
||||
parentHandle = leadFollowerInfo.m_leadBody->m_bodyHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf("PhysX",
|
||||
"Entity [%s] Fixed Joint component missing lead entity. This joint will be a global constraint on the follower's global position.",
|
||||
GetEntity()->GetName().c_str());
|
||||
}
|
||||
|
||||
FixedJointConfiguration configuration;
|
||||
configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation();
|
||||
configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation();
|
||||
@@ -72,7 +86,7 @@ namespace PhysX
|
||||
m_jointHandle = sceneInterface->AddJoint(
|
||||
leadFollowerInfo.m_followerBody->m_sceneOwner,
|
||||
&configuration,
|
||||
leadFollowerInfo.m_leadBody->m_bodyHandle,
|
||||
parentHandle,
|
||||
leadFollowerInfo.m_followerBody->m_bodyHandle);
|
||||
m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner;
|
||||
}
|
||||
|
||||
@@ -48,12 +48,24 @@ namespace PhysX
|
||||
JointComponent::LeadFollowerInfo leadFollowerInfo;
|
||||
ObtainLeadFollowerInfo(leadFollowerInfo);
|
||||
if (leadFollowerInfo.m_followerActor == nullptr ||
|
||||
leadFollowerInfo.m_leadBody == nullptr ||
|
||||
leadFollowerInfo.m_followerBody == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is no lead body, this will be a constraint of the follower's global position, so use invalid body handle.
|
||||
AzPhysics::SimulatedBodyHandle parentHandle = AzPhysics::InvalidSimulatedBodyHandle;
|
||||
if (leadFollowerInfo.m_leadBody != nullptr)
|
||||
{
|
||||
parentHandle = leadFollowerInfo.m_leadBody->m_bodyHandle;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf(
|
||||
"PhysX", "Entity [%s] Hinge Joint component missing lead entity. This joint will be a global constraint on the follower's global position.",
|
||||
GetEntity()->GetName().c_str());
|
||||
}
|
||||
|
||||
HingeJointConfiguration configuration;
|
||||
configuration.m_parentLocalPosition = leadFollowerInfo.m_leadLocal.GetTranslation();
|
||||
configuration.m_parentLocalRotation = leadFollowerInfo.m_leadLocal.GetRotation();
|
||||
@@ -66,7 +78,9 @@ namespace PhysX
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
m_jointHandle = sceneInterface->AddJoint(
|
||||
leadFollowerInfo.m_followerBody->m_sceneOwner, &configuration, leadFollowerInfo.m_leadBody->m_bodyHandle,
|
||||
leadFollowerInfo.m_followerBody->m_sceneOwner,
|
||||
&configuration,
|
||||
parentHandle,
|
||||
leadFollowerInfo.m_followerBody->m_bodyHandle);
|
||||
m_jointSceneOwner = leadFollowerInfo.m_followerBody->m_sceneOwner;
|
||||
}
|
||||
|
||||
@@ -190,8 +190,9 @@ namespace PhysX {
|
||||
{
|
||||
PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
|
||||
if (!actorData.parentActor || !actorData.childActor)
|
||||
if (actorData.parentActor == nullptr && actorData.childActor == nullptr)
|
||||
{
|
||||
AZ_Warning("PhysX Joint", false, "CreateJoint failed - at least one body must be a PxRigidActor.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -239,7 +240,8 @@ namespace PhysX {
|
||||
{
|
||||
PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
|
||||
if (!actorData.parentActor || !actorData.childActor)
|
||||
//only check the child actor, as a null parent actor means this joint is a global constraint.
|
||||
if (!actorData.childActor)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@@ -252,7 +254,8 @@ namespace PhysX {
|
||||
|
||||
{
|
||||
PHYSX_SCENE_READ_LOCK(actorData.childActor->getScene());
|
||||
joint = physx::PxFixedJointCreate(PxGetPhysics(),
|
||||
joint = physx::PxFixedJointCreate(
|
||||
PxGetPhysics(),
|
||||
actorData.parentActor, PxMathConvert(parentLocalTM),
|
||||
actorData.childActor, PxMathConvert(childLocalTM));
|
||||
}
|
||||
@@ -272,7 +275,8 @@ namespace PhysX {
|
||||
{
|
||||
PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
|
||||
if (!actorData.parentActor || !actorData.childActor)
|
||||
// only check the child actor, as a null parent actor means this joint is a global constraint.
|
||||
if (!actorData.childActor)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@@ -306,7 +310,8 @@ namespace PhysX {
|
||||
{
|
||||
PxJointActorData actorData = GetJointPxActors(sceneHandle, parentBodyHandle, childBodyHandle);
|
||||
|
||||
if (!actorData.parentActor || !actorData.childActor)
|
||||
// only check the child actor, as a null parent actor means this joint is a global constraint.
|
||||
if (!actorData.childActor)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace PhysX
|
||||
|
||||
const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId());
|
||||
|
||||
EXPECT_TRUE(followerEndPosition.GetX() > followerPosition.GetX());
|
||||
EXPECT_GT(followerEndPosition.GetX(), followerPosition.GetX());
|
||||
}
|
||||
|
||||
TEST_F(PhysXJointsTest, Joint_HingeJoint_FollowerSwingsAroundLead)
|
||||
@@ -164,8 +164,8 @@ namespace PhysX
|
||||
|
||||
const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId());
|
||||
|
||||
EXPECT_TRUE(followerEndPosition.GetX() > followerPosition.GetX());
|
||||
EXPECT_TRUE(abs(followerEndPosition.GetZ()) > FLT_EPSILON);
|
||||
EXPECT_GT(followerEndPosition.GetX(), followerPosition.GetX());
|
||||
EXPECT_GT(abs(followerEndPosition.GetZ()), FLT_EPSILON);
|
||||
}
|
||||
|
||||
TEST_F(PhysXJointsTest, Joint_BallJoint_FollowerSwingsUpAboutLead)
|
||||
@@ -206,7 +206,65 @@ namespace PhysX
|
||||
|
||||
const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId());
|
||||
|
||||
EXPECT_TRUE(followerEndPosition.GetZ() > followerPosition.GetZ());
|
||||
EXPECT_GT(followerEndPosition.GetZ(), followerPosition.GetZ());
|
||||
}
|
||||
|
||||
TEST_F(PhysXJointsTest, Joint_BallJoint_GlobalConstraint)
|
||||
{
|
||||
// Place an entity in the world with a rigid body, physx collider, and a ball joint components.
|
||||
// Do not set a lead entity on the ball joint component.
|
||||
// Set entity's initial velocity to 10 in the X and Y directions on the rigid body component.
|
||||
// The entity should swing up on the global constraint.
|
||||
|
||||
const AZ::Vector3 followerPosition(0.0f, 0.0f, -1.0f);
|
||||
const AZ::Vector3 followerInitialLinearVelocity(10.0f, 10.0f, 0.0f);
|
||||
|
||||
const AZ::Vector3 jointLocalPosition(0.0f, 0.0f, 2.0f);
|
||||
const AZ::Quaternion jointLocalRotation = AZ::Quaternion::CreateRotationY(90.0f);
|
||||
const AZ::Transform jointLocalTransform = AZ::Transform::CreateFromQuaternionAndTranslation(jointLocalRotation, jointLocalPosition);
|
||||
|
||||
//we want a global constraint, so leave the lead entity unset.
|
||||
auto jointConfig = AZStd::make_shared<JointComponentConfiguration>();
|
||||
jointConfig->m_localTransformFromFollower = jointLocalTransform;
|
||||
|
||||
auto jointLimits = AZStd::make_shared<JointLimitProperties>();
|
||||
jointLimits->m_isLimited = false;
|
||||
|
||||
auto followerEntity = AddBodyColliderEntity<BallJointComponent>(
|
||||
m_testSceneHandle, followerPosition, followerInitialLinearVelocity, jointConfig, nullptr, jointLimits);
|
||||
|
||||
const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId());
|
||||
|
||||
EXPECT_GT(followerEndPosition.GetZ(), followerPosition.GetZ());
|
||||
}
|
||||
|
||||
TEST_F(PhysXJointsTest, Joint_HingeJoint_GlobalConstraint)
|
||||
{
|
||||
// Place an entity in the world with a rigid body, physx collider, and a hinge joint components.
|
||||
// Do not set a lead entity on the hinge joint component.
|
||||
// Set entity's initial velocity to 10 in the X and Y directions on the rigid body component.
|
||||
// The entity should swing up on the global constraint.
|
||||
|
||||
const AZ::Vector3 followerPosition(0.0f, 0.0f, -1.0f);
|
||||
const AZ::Vector3 followerInitialLinearVelocity(10.0f, 10.0f, 0.0f);
|
||||
|
||||
const AZ::Vector3 jointLocalPosition(0.0f, 0.0f, 2.0f);
|
||||
const AZ::Quaternion jointLocalRotation = AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 180.0f, 90.0f));
|
||||
const AZ::Transform jointLocalTransform = AZ::Transform::CreateFromQuaternionAndTranslation(jointLocalRotation, jointLocalPosition);
|
||||
|
||||
// do not set the lead entity as that makes this a global constraint
|
||||
auto jointConfig = AZStd::make_shared<JointComponentConfiguration>();
|
||||
jointConfig->m_localTransformFromFollower = jointLocalTransform;
|
||||
|
||||
auto jointLimits = AZStd::make_shared<JointLimitProperties>();
|
||||
jointLimits->m_isLimited = false;
|
||||
|
||||
auto followerEntity = AddBodyColliderEntity<HingeJointComponent>(
|
||||
m_testSceneHandle, followerPosition, followerInitialLinearVelocity, jointConfig, nullptr, jointLimits);
|
||||
|
||||
const AZ::Vector3 followerEndPosition = RunJointTest(m_defaultScene, followerEntity->GetId());
|
||||
|
||||
EXPECT_GT(followerEndPosition.GetZ(), followerPosition.GetZ());
|
||||
}
|
||||
|
||||
// for some reason TYPED_TEST_CASE with the fixture is not working on Android + Linux
|
||||
|
||||
Reference in New Issue
Block a user