45 void locomotion_system::update_legged(
float t,
float dt)
50 std::execution::par_unseq,
55 auto& locomotion = legged_group.get<legged_locomotion_component>(entity_id);
58 float cos_target_direction{};
59 if (locomotion.speed != 0.0f)
61 auto& rigid_body = *legged_group.get<rigid_body_component>(entity_id).body;
63 const auto max_steering_angle = locomotion.max_angular_frequency * dt;
65 const auto current_direction = rigid_body.get_orientation() * math::fvec3{0, 0, 1};
68 cos_target_direction =
math::dot(current_direction, locomotion.target_direction);
69 if (cos_target_direction < -0.999f)
75 steering_rotation =
math::rotate_towards(current_direction, locomotion.target_direction, max_steering_angle);
78 rigid_body.set_orientation(
math::normalize(steering_rotation * rigid_body.get_orientation()));
84 if (locomotion.speed != 0.0f && navmesh_agent.face)
88 const auto& agent_transform = agent_rigid_body.get_transform();
92 const auto& navmesh_transform = navmesh_rigid_body.get_transform();
95 const auto traversal_direction = agent_transform.rotation *
math::fvec3{0, 0, 1};
96 auto traversal_start = agent_transform.translation;
97 auto traversal_end = agent_transform.translation + traversal_direction * (locomotion.speed * dt);
100 traversal_start = ((traversal_start - navmesh_transform.translation) * navmesh_transform.rotation) / navmesh_transform.scale;
101 traversal_end = ((traversal_end - navmesh_transform.translation) * navmesh_transform.rotation) / navmesh_transform.scale;
105 auto traversal =
ai::traverse_navmesh(*navmesh_agent.mesh, navmesh_agent.face, traversal_start, traversal_end);
108 traversal.closest_point = navmesh_transform.translation + (navmesh_transform.rotation * (navmesh_transform.scale * traversal.closest_point));
111 navmesh_agent.face = traversal.face;
114 const auto& vertex_normals = navmesh_agent.mesh->vertices().attributes().at<
math::fvec3>(
"normal");
115 auto loop = navmesh_agent.face->loops().
begin();
116 const auto& na = vertex_normals[loop->vertex()->index()];
117 const auto& nb = vertex_normals[(++loop)->
vertex()->index()];
118 const auto& nc = vertex_normals[(++loop)->
vertex()->index()];
119 const auto& uvw = traversal.barycentric;
120 navmesh_agent.surface_normal =
math::normalize(na * uvw.x() + nb * uvw.y() + nc * uvw.z());
123 navmesh_agent.surface_normal =
math::normalize(navmesh_transform.rotation * (navmesh_agent.surface_normal / navmesh_transform.scale));
129 agent_rigid_body.set_position(traversal.closest_point);
141 locomotion.gait_phase =
math::fract(locomotion.gait_phase + locomotion.speed * dt / locomotion.stride_length);
147 auto body_xf = locomotion.midstance_pose->get_relative_transform(locomotion.body_bone);
149 body_xf.translation.y() += locomotion.standing_height;
153 for (std::size_t i = 0;
i < locomotion.tip_bones.size(); ++
i)
156 float step_phase = locomotion.gait->steps[
i].phase(locomotion.gait_phase);
159 const ::pose* pose_a;
160 const ::pose* pose_b;
162 if (step_phase < 0.0f)
164 pose_b = locomotion.touchdown_pose;
165 pose_a = locomotion.liftoff_pose;
170 if (step_phase < 0.5f)
172 pose_a = locomotion.liftoff_pose;
173 pose_b = locomotion.midswing_pose;
174 t = step_phase * 2.0f;
178 pose_a = locomotion.midswing_pose;
179 pose_b = locomotion.touchdown_pose;
180 t = (step_phase - 0.5f) * 2.0f;
186 for (std::uint8_t j = 0;
j < locomotion.leg_bone_count; ++
j)
197 auto transform = pose_a->get_relative_transform(
bone_index);
198 const auto rotation_a = pose_a->get_relative_transform(
bone_index).rotation;
199 const auto rotation_b = pose_b->get_relative_transform(
bone_index).rotation;
200 transform.rotation =
math::nlerp(rotation_a, rotation_b, t);
215 void locomotion_system::update_winged(
float t,
float dt)
220 std::execution::par_unseq,
221 winged_group.begin(),
225 const auto& locomotion = winged_group.get<winged_locomotion_component>(entity_id);
226 auto& body = *(winged_group.get<rigid_body_component>(entity_id).body);
228 const math::fvec3 gravity{0.0f, 9.80665f * 10.0f, 0.0f};
232 body.apply_central_force(locomotion.force + gravity * body.get_mass());
std::uint16_t bone_index_type
Bone index type.
void update(float t, float dt) override
Perform's a system's update() function.
locomotion_system(entity::registry ®istry)
const skeleton * get_skeleton() const noexcept
Returns the skeleton with which the pose is associated.
void set_relative_transform(bone_index_type index, const bone_transform_type &transform)
Sets the relative transform describing a bone pose.
void update()
Updates the pose after one or more relative transforms have been changed.
const bone_transform_type & get_relative_transform(bone_index_type index) const
Returns the relative transform describing a bone pose.
bone_index_type get_bone_parent(bone_index_type child_index) const
Returns the index of the parent of a bone.
Abstract base class for updatable systems.
entity::registry & registry
Registry on which the system operate.
navmesh_traversal traverse_navmesh(const geom::brep_mesh &mesh, geom::brep_face *face, const math::fvec3 &start, const math::fvec3 &end)
Moves a point along the surface of a mesh.
entt::registry registry
Component registry type.
@ vertex
Vertex shader stage.
quaternion< T > nlerp(const quaternion< T > &a, const quaternion< T > &b, T t)
Performs normalized linear interpolation between two quaternions.
quaternion< T > rotate_towards(const vec3< T > &from, const vec3< T > &to, T max_angle)
Constructs a quaternion representing an angle-limited rotation from one direction towards another dir...
T fract(T x)
Returns the fractional part of a floating-point number.
quaternion< T > normalize(const quaternion< T > &q)
Normalizes a quaternion.
quaternion< T > angle_axis(T angle, const vec3< T > &axis)
Creates a rotation from an angle and axis.
constexpr vector< T, N > abs(const vector< T, N > &x)
Returns the absolute values of each element.
quaternion< T > rotation(const vec3< T > &from, const vec3< T > &to, T tolerance=T{1e-6})
Constructs a quaternion representing the minimum rotation from one direction to another direction.
constexpr T dot(const quaternion< T > &a, const quaternion< T > &b) noexcept
Calculates the dot product of two quaternions.
@ bone_index
Vertex bone indices (uvec4)
Legged terrestrial locomotion.
Quaternion composed of a real scalar part and imaginary vector part.
constexpr element_type * begin() noexcept
Returns an iterator to the first element.
pose current_pose
Pose of the current state.
pose previous_pose
Pose of the previous state.
Winged aerial locomotion.