You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
278 lines
12 KiB
Python
278 lines
12 KiB
Python
"""
|
|
Copyright (c) Contributors to the Open 3D Engine Project.
|
|
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
|
|
SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
"""
|
|
|
|
# Test case ID : C4976199
|
|
# Test Case Title : Verify that with higher linear damping, the object in motion comes to rest faster
|
|
|
|
|
|
# fmt: off
|
|
class Tests:
|
|
enter_game_mode_low = ("Entered game mode low", "Failed to enter game mode low")
|
|
enter_game_mode_medium = ("Entered game mode medium", "Failed to enter game medium")
|
|
enter_game_mode_high = ("Entered game mode high", "Failed to enter game mode high")
|
|
find_sphere_low = ("Find sphere low", "Failed to find sphere low")
|
|
find_sphere_medium = ("Find sphere medium", "Failed to find sphere medium")
|
|
find_sphere_high = ("Find sphere high", "Failed to find sphere high")
|
|
find_triggers_low = ("Find triggers low", "Failed to find triggers low")
|
|
find_triggers_medium = ("Find triggers medium", "Failed to find triggers medium")
|
|
find_triggers_high = ("Find triggers high", "Failed to find triggers high")
|
|
x_movement = ("x direction movement decreases with increased damping", "x direction movement does not decrease with increased damping")
|
|
high_damping_no_movement = ("High damping IsClose to 0 movement", "High damping is not IsClose to 0 movement")
|
|
triggers_tripped_low = ("Low damping trips all 3 triggers", "Low damping did not trip all 3 triggers")
|
|
triggers_tripped_medium = ("Medium damping trips 2/3 triggers", "Medium damping does not trip 2/3 triggers")
|
|
triggers_tripped_high = ("High damping trips no triggers", "High damping trips triggers and should not")
|
|
timeout = ("All spheres velocity IsClose to 0 before timeout", "All spheres velocity are not IsClose to 0 before timeout")
|
|
exit_game_mode_low = ("Exited game mode low", "Couldn't exit game mode low")
|
|
exit_game_mode_medium = ("Exited game mode medium", "Couldn't exit game mode medium")
|
|
exit_game_mode_high = ("Exited game mode high", "Couldn't exit game mode high")
|
|
# fmt: on
|
|
|
|
|
|
def C4976199_RigidBodies_LinearDampingObjectMotion():
|
|
"""
|
|
The level consists of a PhysX Terrain component that is not interacted with (per the test case)
|
|
and a PhysX collider with shape sphere, PhysX rigid bodies physics, and mesh with shape sphere.
|
|
3 colliders with trigger are added to ensure x movement length is decreased quantitatively not
|
|
just comparatively.
|
|
The sphere starts asleep.
|
|
We will enter game mode for each state defined
|
|
|
|
1) Open level
|
|
2) Enter game mode
|
|
3) Set sphere attributes, measure initial position, and then ForceAwake
|
|
5) Measure
|
|
6) Exit game mode
|
|
7) Run and repeat steps 2-6
|
|
8) Report results
|
|
|
|
Notes:
|
|
Initially we calculated time to stop by calling time.time() both when awakening the sphere and when velocity equaled zero.
|
|
Comparing the time to stop accross sphere settings proved flaky.
|
|
"""
|
|
# Setup path
|
|
import os
|
|
import sys
|
|
|
|
import ImportPathHelper as imports
|
|
|
|
imports.init()
|
|
|
|
from editor_python_test_tools.utils import Report
|
|
from editor_python_test_tools.utils import TestHelper as helper
|
|
|
|
import azlmbr.legacy.general as general
|
|
import azlmbr.bus
|
|
import azlmbr.math as lymath
|
|
|
|
class SphereInfo:
|
|
def __init__(
|
|
self,
|
|
initial_linear_velocity,
|
|
linear_damping,
|
|
enter_game_mode_test,
|
|
find_sphere_test,
|
|
exit_game_mode_test,
|
|
triggers_test,
|
|
):
|
|
self.initial_linear_velocity = initial_linear_velocity
|
|
self.linear_damping = linear_damping
|
|
self.entity = None
|
|
self.initial_position = None
|
|
self.final_position = None
|
|
self.timeout = False
|
|
self.triggers = []
|
|
self.enter_game_mode_test = enter_game_mode_test
|
|
self.find_sphere_test = find_sphere_test
|
|
self.exit_game_mode_test = exit_game_mode_test
|
|
self.triggers_test = triggers_test
|
|
|
|
def __str__(self):
|
|
return """
|
|
initial_linear_velocity = {}
|
|
linear_damping = {}
|
|
timeout = {}
|
|
""".format(
|
|
self.initial_linear_velocity.GetLength(), self.linear_damping, self.timeout
|
|
)
|
|
|
|
def report(self):
|
|
Report.info(self.__str__())
|
|
Report.info_vector3(self.initial_position, "Initial position")
|
|
Report.info_vector3(self.final_position, "Final position")
|
|
for trigger in self.triggers:
|
|
Report.info(trigger.__str__())
|
|
|
|
class Trigger:
|
|
def __init__(self, name):
|
|
self.name = name
|
|
self.entity = None
|
|
self.handler = None
|
|
self.triggering_entity = None
|
|
self.triggered = False
|
|
|
|
def on_trigger(self, args):
|
|
self.triggered = True
|
|
self.triggering_entity = args[0]
|
|
Report.info("{} was triggered by {}".format(self.name, self.triggering_entity_name()))
|
|
|
|
def __str__(self):
|
|
return """
|
|
name = {}
|
|
triggering entity name = {}
|
|
triggered = {}
|
|
""".format(
|
|
self.name, self.triggering_entity_name(), self.triggered
|
|
)
|
|
|
|
def triggering_entity_name(self):
|
|
if self.triggering_entity:
|
|
return azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "GetEntityName", self.triggering_entity)
|
|
return None
|
|
|
|
INITIAL_LINEAR_VELOCITY = lymath.Vector3(5.0, 0.0, 0.0)
|
|
ZERO_VELOCITY = lymath.Vector3(0.0, 0.0, 0.0)
|
|
TOLERANCE = 0.001
|
|
TIMEOUT = 3.0
|
|
TRIGGER1 = "Trigger1"
|
|
TRIGGER2 = "Trigger2"
|
|
TRIGGER3 = "Trigger3"
|
|
|
|
# sphere state under test
|
|
# fmt: off
|
|
low_damping = SphereInfo(
|
|
INITIAL_LINEAR_VELOCITY,
|
|
5.0,
|
|
Tests.enter_game_mode_low,
|
|
Tests.find_sphere_low,
|
|
Tests.exit_game_mode_low,
|
|
Tests.find_triggers_low,
|
|
)
|
|
medium_damping = SphereInfo(
|
|
INITIAL_LINEAR_VELOCITY,
|
|
10.0,
|
|
Tests.enter_game_mode_medium,
|
|
Tests.find_sphere_medium,
|
|
Tests.exit_game_mode_medium,
|
|
Tests.find_triggers_medium,
|
|
)
|
|
high_damping = SphereInfo(
|
|
INITIAL_LINEAR_VELOCITY,
|
|
10000.0,
|
|
Tests.enter_game_mode_high,
|
|
Tests.find_sphere_high,
|
|
Tests.exit_game_mode_high,
|
|
Tests.find_triggers_high,
|
|
)
|
|
# fmt: on
|
|
|
|
spheres = [low_damping, medium_damping, high_damping]
|
|
|
|
helper.init_idle()
|
|
# 1) Open level
|
|
helper.open_level("Physics", "C4976199_RigidBodies_LinearDampingObjectMotion")
|
|
|
|
def run_test_steps(sphere):
|
|
|
|
# 2) Enter game mode
|
|
helper.enter_game_mode(sphere.enter_game_mode_test)
|
|
|
|
# 3) Retrieve entities
|
|
sphere.entity = general.find_game_entity("Sphere")
|
|
Report.critical_result(sphere.find_sphere_test, sphere.entity.IsValid())
|
|
|
|
triggers = [Trigger(TRIGGER1), Trigger(TRIGGER2), Trigger(TRIGGER3)]
|
|
for trigger in triggers:
|
|
trigger.entity = general.find_game_entity(trigger.name)
|
|
|
|
invalid_triggers = [t for t in triggers if not t.entity.IsValid()]
|
|
for trigger in invalid_triggers:
|
|
Report.info("Trigger {} is invalid".format(trigger.name))
|
|
Report.critical_result(sphere.triggers_test, len(invalid_triggers) == 0)
|
|
|
|
# 4) Set sphere attributes, measure initial position, and then ForceAwake
|
|
azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "SetLinearVelocity", sphere.entity, sphere.initial_linear_velocity)
|
|
azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "SetLinearDamping", sphere.entity, sphere.linear_damping)
|
|
sphere.initial_position = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTM", sphere.entity).GetPosition()
|
|
|
|
# add handler for each trigger
|
|
for trigger in triggers:
|
|
trigger.handler = azlmbr.physics.TriggerNotificationBusHandler()
|
|
trigger.handler.connect(trigger.entity)
|
|
trigger.handler.add_callback("OnTriggerEnter", trigger.on_trigger)
|
|
|
|
azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "ForceAwake", sphere.entity)
|
|
general.idle_wait_frames(1) # wait one frame for changes to apply
|
|
|
|
# 5) Measure
|
|
|
|
def sphere_stopped():
|
|
sphere_linear_velocity = azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "GetLinearVelocity", sphere.entity)
|
|
if sphere_linear_velocity.IsClose(ZERO_VELOCITY, TOLERANCE):
|
|
sphere.final_position = azlmbr.components.TransformBus(
|
|
azlmbr.bus.Event, "GetWorldTM", sphere.entity
|
|
).GetPosition()
|
|
for trigger in [t for t in triggers if t.triggered]:
|
|
if trigger.triggering_entity.Equal(sphere.entity):
|
|
sphere.triggers.append(trigger)
|
|
return True
|
|
return False
|
|
|
|
if not helper.wait_for_condition(sphere_stopped, TIMEOUT):
|
|
sphere.timeout = True
|
|
sphere.report()
|
|
|
|
# 6) Exit game mode
|
|
helper.exit_game_mode(sphere.exit_game_mode_test)
|
|
|
|
# 7) Run and repeat steps 2-6
|
|
for sphere in spheres:
|
|
run_test_steps(sphere)
|
|
|
|
# 8) Report results
|
|
no_timeout = True
|
|
for sphere in spheres:
|
|
if sphere.timeout:
|
|
Report.info(
|
|
"Timeout occurred. Sphere with damping = {} and Initial velocity = {} did not come to rest in the timeout of {}".format(
|
|
sphere.linear_damping, sphere.initial_linear_velocity, TIMEOUT
|
|
)
|
|
)
|
|
no_timeout = False
|
|
|
|
# fast fail if timeout occurred, comparisons will be meaningless and all info is in log to determine which sphere(s) timed out
|
|
Report.critical_result(Tests.timeout, no_timeout)
|
|
Report.result(
|
|
Tests.high_damping_no_movement, high_damping.final_position.IsClose(high_damping.initial_position, TOLERANCE)
|
|
)
|
|
# comparative movement length
|
|
Report.result(
|
|
Tests.x_movement, high_damping.final_position.x < medium_damping.final_position.x < low_damping.final_position.x
|
|
)
|
|
# quantitative movement length
|
|
all_three_tripped = (
|
|
len(low_damping.triggers) == 3
|
|
and len([t for t in low_damping.triggers if t.name == TRIGGER1]) == 1
|
|
and len([t for t in low_damping.triggers if t.name == TRIGGER2]) == 1
|
|
and len([t for t in low_damping.triggers if t.name == TRIGGER3]) == 1
|
|
)
|
|
Report.result(Tests.triggers_tripped_low, all_three_tripped)
|
|
first_two_triggers_tripped = (
|
|
len(medium_damping.triggers) == 2
|
|
and len([t for t in medium_damping.triggers if t.name == TRIGGER1]) == 1
|
|
and len([t for t in medium_damping.triggers if t.name == TRIGGER2]) == 1
|
|
)
|
|
Report.result(Tests.triggers_tripped_medium, first_two_triggers_tripped)
|
|
Report.result(Tests.triggers_tripped_high, len(high_damping.triggers) == 0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import ImportPathHelper as imports
|
|
imports.init()
|
|
|
|
from editor_python_test_tools.utils import Report
|
|
Report.start_test(C4976199_RigidBodies_LinearDampingObjectMotion)
|