fixed joint crash when no lead entity is selected (#2867)

Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com>
monroegm-disable-blank-issue-2
amzn-sean 4 years ago committed by GitHub
parent 5925bd22f6
commit e630e3324d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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

Loading…
Cancel
Save