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.
289 lines
13 KiB
Python
289 lines
13 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 : C13352089
|
|
# Test Case Title : Verify that maximum angular velocity interacts correctly with initial angular velocity
|
|
|
|
|
|
|
|
# fmt: off
|
|
class Tests:
|
|
|
|
# level
|
|
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
|
|
exit_game_mode = ("Exited game mode", "Couldn't exit game mode")
|
|
trigger_touch_times = ("Bar5 rotated more than bar6", "Bar5 did not stop more slowly than bar6")
|
|
rotation_duration = ("Bar5 stopped faster than bar6", "Bar5 did not stop faster than bar6")
|
|
|
|
# bar 1
|
|
bar1_gravity_disabled = ("Bar1 : Gravity is disabled", "Bar1 : Gravity is not disabled")
|
|
bar1_found = ("Bar1 : Found entity", "Bar1 : Entity not found")
|
|
bar1_rotation = ("Bar1 : Rotated on X axis", "Bar1 : Unexpected rotation")
|
|
bar1_angular_velocity = ("Bar1 : Expected angular velocity", "Bar1 : Unexpected angular velocity")
|
|
|
|
# bar 2
|
|
bar2_gravity_disabled = ("Bar2 : Gravity is disabled", "Bar2 : Gravity is not disabled")
|
|
bar2_found = ("Bar2 : Found entity", "Bar2 : Entity not found")
|
|
bar2_rotation = ("Bar2 : Rotated on X axis", "Bar2 : Unexpected rotation")
|
|
bar2_angular_velocity = ("Bar2 : Expected angular velocity", "Bar2 : Unexpected angular velocity")
|
|
|
|
# bar 3
|
|
bar3_gravity_disabled = ("Bar3 : Gravity is disabled", "Bar3 : Gravity is not disabled")
|
|
bar3_found = ("Bar3 : Found entity", "Bar3 : Entity not found")
|
|
bar3_rotation = ("Bar3 : Rotated on X axis", "Bar3 : Unexpected rotation")
|
|
bar3_angular_velocity = ("Bar3 : Expected angular velocity", "Bar3 : Unexpected angular velocity")
|
|
|
|
# bar 4
|
|
bar4_gravity_disabled = ("Bar4 : Gravity is disabled", "Bar4 : Gravity is not disabled")
|
|
bar4_found = ("Bar4 : Found entity", "Bar4 : Entity not found")
|
|
bar4_rotation = ("Bar4 : Did not rotate", "Bar4 : Unexpected rotation")
|
|
bar4_angular_velocity = ("Bar4 : Expected angular velocity", "Bar4 : Unexpected angular velocity")
|
|
|
|
# bar 5
|
|
bar5_gravity_disabled = ("Bar5 : Gravity is disabled", "Bar5 : Gravity is not disabled")
|
|
bar5_found = ("Bar5 : Found entity", "Bar5 : Entity not found")
|
|
bar5_rotation = ("Bar5 : Rotated on X axis", "Bar5 : Unexpected rotation")
|
|
bar5_angular_velocity = ("Bar5 : Expected angular velocity", "Bar5 : Unexpected angular velocity")
|
|
|
|
# bar 6
|
|
bar6_gravity_disabled = ("Bar6 : Gravity is disabled", "Bar6 : Gravity is not disabled")
|
|
bar6_found = ("Bar6 : Found entity", "Bar6 : Entity not found")
|
|
bar6_rotation = ("Bar6 : Rotated on X axis", "Bar6 : Unexpected rotation")
|
|
bar6_angular_velocity = ("Bar6 : Expected angular velocity", "Bar6 : Unexpected angular velocity")
|
|
|
|
# trigger for bar 5
|
|
bar5_trigger_found = ("Trigger for bar5 : Found entity", "Trigger for bar5 : Entity not found")
|
|
|
|
# trigger for bar 6
|
|
bar6_trigger_found = ("Trigger for bar6 : Found entity", "Trigger for bar6 : Entity not found")
|
|
|
|
did_not_timeout = ("Should_wait did not time out", "Should wait timed out")
|
|
# fmt: on
|
|
|
|
|
|
def C13352089_RigidBodies_MaxAngularVelocity():
|
|
"""
|
|
Summary:
|
|
Runs an automated test to ensure maximum angular velocity and angular damping interact correctly with
|
|
initial angular velocity
|
|
|
|
Level Description:
|
|
bars:
|
|
6 PhysX Rigid Bodies with PhysX Shape Collider (Box Shape, Dimensions: X=1, Y=1, Z=5), gravity disabled,
|
|
start asleep, positioned above terrain
|
|
bar 1: Initial Angular Velocity = 10 rad/s, Max Angular Velocity = 5 rad/s, Angular Damping = 0.0
|
|
bar 2: Initial Angular Velocity = 10 rad/s, Max Angular Velocity = 10 rad/s, Angular Damping = 0.0
|
|
bar 3: Initial Angular Velocity = 20 rad/s, Max Angular Velocity = 20 rad/s, Angular Damping = 0.0
|
|
bar 4: Initial Angular Velocity = 20 rad/s, Max Angular Velocity = 0 rad/s, Angular Damping = 0.0
|
|
bar 5: Initial Angular Velocity = 20 rad/s, Max Angular Velocity = 20 rad/s, Angular Damping = 2.0
|
|
bar 6: Initial Angular Velocity = 20 rad/s, Max Angular Velocity = 20 rad/s, Angular Damping = 5.0
|
|
triggers:
|
|
2 PhysX Shape Collider (Box Shape), gravity disabled, trigger enabled, start asleep
|
|
trigger for bar 5: positioned above terrain, in front of bar 5
|
|
trigger for bar 6: positioned above terrain, in front of bar 6
|
|
|
|
Expected Behavior:
|
|
bar 1: Should rotate at 5 rad/s on X axis
|
|
bar 2: Should rotate at 10 rad/s on X axis
|
|
bar 3: Should rotate at 20 rad/s on X axis
|
|
bar 4: Should not rotate at all
|
|
bar 5: Should start rotating at 20 rad/s on X axis and stop slowly (touching its trigger several times)
|
|
bar 6: Should start rotating at 20 rad/s on X axis but stop quickly (touching its trigger 0 or very few times)
|
|
|
|
Test Steps:
|
|
1) Loads the level
|
|
2) Enters game mode
|
|
3) Set up bars values
|
|
4) Loop for each bar
|
|
4.1) Find the bar
|
|
4.2) Validate ID
|
|
4.3) Activate the bar
|
|
4.4) Validate and log its position
|
|
4.5) Confirm gravity is disabled for the bar
|
|
4.6) Log bar's initial rotation
|
|
4.7) Log bar's angular damping
|
|
4.8) Log bar's angular velocity
|
|
4.9) Set up trigger if the bar has one
|
|
4.10) Wait for each bar to rotate or stop rotating
|
|
4.11) Log current location
|
|
4.12) Validate rotation based on expected behavior
|
|
4.13) Destroy bar (and its trigger)
|
|
5) Compare trigger touch times for bar5 and bar6
|
|
6) Exit game mode
|
|
7) Close editor
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import math
|
|
import time
|
|
|
|
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.math as lymath
|
|
import azlmbr.legacy.general as general
|
|
import azlmbr.bus
|
|
|
|
# Constants
|
|
ANGULAR_VELOCITY_TOLERANCE = 0.05
|
|
TIME_OUT = 15.0
|
|
ROTATION_TOLERANCE = 0.001
|
|
|
|
def is_close(x, y, tolerance=ANGULAR_VELOCITY_TOLERANCE):
|
|
return abs(x - y) < tolerance
|
|
|
|
def is_angle_close(x, y):
|
|
r = (math.sin(x) - math.sin(y)) * (math.sin(x) - math.sin(y)) + (math.cos(x) - math.cos(y)) * (
|
|
math.cos(x) - math.cos(y)
|
|
)
|
|
diff = math.acos((2.0 - r) / 2.0)
|
|
return abs(diff) <= ROTATION_TOLERANCE
|
|
|
|
class Entity: # Parent class for bars and triggers
|
|
def __init__(self, name):
|
|
self.name = name
|
|
self.validate_ID()
|
|
self.activate_entity()
|
|
|
|
def validate_ID(self):
|
|
self.id = general.find_game_entity(self.name)
|
|
found_tuple = Tests.__dict__[self.name + "_found"]
|
|
Report.critical_result(found_tuple, self.id.IsValid())
|
|
|
|
def activate_entity(self):
|
|
Report.info("Activating Entity : " + self.name)
|
|
azlmbr.entity.GameEntityContextRequestBus(azlmbr.bus.Broadcast, "ActivateGameEntity", self.id)
|
|
general.idle_wait_frames(1)
|
|
self.rotation_start_time = time.time()
|
|
|
|
class Bar(Entity):
|
|
def __init__(self, name, init_ang_velocity_on_X, max_ang_velocity, has_trigger=False):
|
|
# 1) Validate ID, then activate Bar
|
|
Entity.__init__(self, name)
|
|
self.rotation_duration = 999999.9
|
|
self.init_angular_velocity = lymath.Vector3(init_ang_velocity_on_X, 0.0, 0.0)
|
|
self.max_angular_velocity = max_ang_velocity
|
|
self.max_valid_velocity = min(self.max_angular_velocity, self.init_angular_velocity.GetLength())
|
|
self.angular_damping = azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "GetAngularDamping", self.id)
|
|
# ) Log initial rotation
|
|
self.init_rotation = self.get_rotation()
|
|
# ) Verify gravity is disabled for bar
|
|
self.validate_gravity_is_disabled()
|
|
# ) Validate angular velocity according to max angular velocity
|
|
self.validate_angular_velocity()
|
|
# ) Setup trigger
|
|
if has_trigger:
|
|
self.touched_trigger = 0
|
|
self.setup_trigger()
|
|
|
|
def validate_gravity_is_disabled(self):
|
|
gravity_enabled = azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsGravityEnabled", self.id)
|
|
gravity_tuple = Tests.__dict__[self.name + "_gravity_disabled"]
|
|
Report.result(gravity_tuple, not gravity_enabled)
|
|
|
|
def setup_trigger(self):
|
|
self.trigger = Entity(self.name + "_trigger")
|
|
self.trigger.handler = azlmbr.physics.TriggerNotificationBusHandler()
|
|
self.trigger.handler.connect(self.trigger.id)
|
|
self.trigger.handler.add_callback("OnTriggerEnter", self.count_touch_times)
|
|
|
|
def get_angular_velocity(self):
|
|
return azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "GetAngularVelocity", self.id)
|
|
|
|
def get_rotation(self):
|
|
return azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldRotation", self.id)
|
|
|
|
def validate_angular_velocity(self):
|
|
general.idle_wait_frames(10)
|
|
self.angular_velocity = self.get_angular_velocity()
|
|
angular_velocity_tuple = Tests.__dict__[self.name + "_angular_velocity"]
|
|
if self.angular_damping == 0:
|
|
velocity_is_valid = is_close(self.angular_velocity.GetLength(), self.max_valid_velocity)
|
|
else:
|
|
velocity_is_valid = self.max_valid_velocity >= self.angular_velocity.GetLength() >= 0.0
|
|
|
|
Report.result(angular_velocity_tuple, velocity_is_valid)
|
|
|
|
def validate_rotation(self):
|
|
self.rotation = self.get_rotation()
|
|
rotated_on_x = not is_angle_close(self.init_rotation.x, self.rotation.x)
|
|
rotated_on_y = not is_angle_close(self.init_rotation.y, self.rotation.y)
|
|
rotated_on_z = not is_angle_close(self.init_rotation.z, self.rotation.z)
|
|
if self.max_valid_velocity != 0:
|
|
return rotated_on_x and not rotated_on_y and not rotated_on_z
|
|
else:
|
|
return not rotated_on_x and not rotated_on_y and not rotated_on_z
|
|
|
|
def has_waited_enough(self):
|
|
if self.angular_damping > 0:
|
|
# Bar5 or bar6 should stop rotating to consider their movement as done
|
|
if self.get_angular_velocity().IsZero():
|
|
self.rotation_duration = time.time() - self.rotation_start_time
|
|
return True
|
|
elif self.angular_damping == 0:
|
|
# Bar1, bar2, bar3 or bar4
|
|
return True
|
|
return False
|
|
|
|
def count_touch_times(self, args):
|
|
entering_entity_id = args[0]
|
|
if entering_entity_id.Equal(self.id):
|
|
Report.info(self.name + " touched " + self.trigger.name)
|
|
self.touched_trigger += 1
|
|
|
|
helper.init_idle()
|
|
|
|
# 1) Load the level
|
|
helper.open_level("Physics", "C13352089_RigidBodies_MaxAngularVelocity")
|
|
|
|
# 2) Enter game mode
|
|
helper.enter_game_mode(Tests.enter_game_mode)
|
|
|
|
# 3) Init bars values
|
|
bars = [
|
|
Bar(name="bar1", init_ang_velocity_on_X=10.0, max_ang_velocity=5),
|
|
Bar(name="bar2", init_ang_velocity_on_X=10.0, max_ang_velocity=20),
|
|
Bar(name="bar3", init_ang_velocity_on_X=20.0, max_ang_velocity=20),
|
|
Bar(name="bar4", init_ang_velocity_on_X=20.0, max_ang_velocity=0,),
|
|
Bar(name="bar5", init_ang_velocity_on_X=20.0, max_ang_velocity=20, has_trigger=True,),
|
|
Bar(name="bar6", init_ang_velocity_on_X=20.0, max_ang_velocity=20, has_trigger=True,),
|
|
]
|
|
|
|
# 4.10) Wait
|
|
Report.critical_result(
|
|
Tests.did_not_timeout,
|
|
helper.wait_for_condition(lambda: all([bar.has_waited_enough() for bar in bars]), TIME_OUT),
|
|
)
|
|
|
|
# 4.12) Validate rotation
|
|
for bar in bars:
|
|
Report.result(Tests.__dict__["{}_rotation".format(bar.name)], bar.validate_rotation())
|
|
|
|
# 5) Compare number of times bar5 and bar6 touched their trigger
|
|
Report.result(Tests.trigger_touch_times, bars[4].touched_trigger > bars[5].touched_trigger)
|
|
|
|
Report.info(bars[4].rotation_duration)
|
|
Report.info(bars[5].rotation_duration)
|
|
|
|
Report.result(Tests.rotation_duration, bars[4].rotation_duration > bars[5].rotation_duration)
|
|
|
|
# 6) Exit Game mode
|
|
helper.exit_game_mode(Tests.exit_game_mode)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import ImportPathHelper as imports
|
|
imports.init()
|
|
|
|
from editor_python_test_tools.utils import Report
|
|
Report.start_test(C13352089_RigidBodies_MaxAngularVelocity)
|