Browse Source

Add more constraints and constraint and control callback-based camera controls

master
C. J. Howard 3 years ago
parent
commit
76291c5612
30 changed files with 998 additions and 482 deletions
  1. +1
    -1
      src/animation/orbit-cam.cpp
  2. +1
    -0
      src/application.cpp
  3. +17
    -7
      src/entity/commands.cpp
  4. +2
    -1
      src/entity/commands.hpp
  5. +4
    -2
      src/entity/components/camera.hpp
  6. +15
    -4
      src/entity/components/chamber.hpp
  7. +61
    -0
      src/entity/components/constraint-stack.hpp
  8. +12
    -7
      src/entity/components/constraints/constraints.hpp
  9. +9
    -3
      src/entity/components/constraints/copy-rotation.hpp
  10. +18
    -6
      src/entity/components/constraints/copy-scale.hpp
  11. +9
    -3
      src/entity/components/constraints/copy-transform.hpp
  12. +63
    -0
      src/entity/components/constraints/copy-translation.hpp
  13. +56
    -0
      src/entity/components/constraints/spring-to.hpp
  14. +46
    -0
      src/entity/components/constraints/three-dof.hpp
  15. +14
    -10
      src/entity/components/constraints/track-to.hpp
  16. +2
    -86
      src/entity/systems/camera.cpp
  17. +1
    -41
      src/entity/systems/camera.hpp
  18. +161
    -55
      src/entity/systems/constraint.cpp
  19. +20
    -0
      src/entity/systems/constraint.hpp
  20. +8
    -37
      src/entity/systems/control.cpp
  21. +0
    -39
      src/entity/systems/control.hpp
  22. +16
    -0
      src/entity/systems/render.cpp
  23. +61
    -111
      src/game/bootloader.cpp
  24. +17
    -1
      src/game/context.hpp
  25. +361
    -27
      src/game/states/brood.cpp
  26. +0
    -17
      src/game/states/forage.cpp
  27. +0
    -16
      src/game/states/nuptial-flight.cpp
  28. +11
    -0
      src/input/control.cpp
  29. +4
    -0
      src/input/control.hpp
  30. +8
    -8
      src/input/event-router.cpp

+ 1
- 1
src/animation/orbit-cam.cpp View File

@ -74,7 +74,7 @@ void orbit_cam::update(float dt)
float fov = math::log_lerp<float>(fov_limits[1], fov_limits[0], zoom_spring.x0);
float clip_near = math::log_lerp<float>(clip_near_limits[1], clip_near_limits[0], zoom_spring.x0);
float clip_far = math::log_lerp<float>(clip_far_limits[1], clip_far_limits[0], zoom_spring.x0);
// Calculate camera transform
transform_type transform = math::identity_transform<float>;

+ 1
- 0
src/application.cpp View File

@ -537,6 +537,7 @@ void application::translate_sdl_events()
case SDL_MOUSEMOTION:
{
/// @WARNING: more than one mouse motion event is often generated per frame and may be a source of lag.
mouse->move(sdl_event.motion.x, sdl_event.motion.y, sdl_event.motion.xrel, sdl_event.motion.yrel);
break;
}

+ 17
- 7
src/entity/commands.cpp View File

@ -20,7 +20,6 @@
#include "entity/commands.hpp"
#include "entity/components/model.hpp"
#include "entity/components/transform.hpp"
#include "entity/components/copy-transform.hpp"
#include "entity/components/snap.hpp"
#include "entity/components/parent.hpp"
#include "entity/components/celestial-body.hpp"
@ -40,6 +39,15 @@ void translate(entity::registry& registry, entity::id eid, const float3& transla
}
}
void rotate(entity::registry& registry, entity::id eid, float angle, const float3& axis)
{
if (registry.has<component::transform>(eid))
{
component::transform& transform = registry.get<component::transform>(eid);
transform.local.rotation = math::angle_axis(angle, axis) * transform.local.rotation;
}
}
void move_to(entity::registry& registry, entity::id eid, const float3& position)
{
if (registry.has<component::transform>(eid))
@ -128,12 +136,6 @@ void assign_render_layers(entity::registry& registry, entity::id eid, unsigned i
}
}
void bind_transform(entity::registry& registry, entity::id source, entity::id target)
{
component::copy_transform copy_transform = {target};
registry.assign_or_replace<component::copy_transform>(source, copy_transform);
}
math::transform<float> get_local_transform(entity::registry& registry, entity::id eid)
{
if (registry.has<component::transform>(eid))
@ -193,5 +195,13 @@ entity::id create(entity::registry& registry, const std::string& name)
return eid;
}
entity::id find_or_create(entity::registry& registry, const std::string& name)
{
entity::id eid = find(registry, name);
if (eid == entt::null)
eid = create(registry, name);
return eid;
}
} // namespace command
} // namespace entity

+ 2
- 1
src/entity/commands.hpp View File

@ -31,13 +31,13 @@ namespace entity {
namespace command {
void translate(entity::registry& registry, entity::id eid, const float3& translation);
void rotate(entity::registry& registry, entity::id eid, float angle, const float3& axis);
void move_to(entity::registry& registry, entity::id eid, const float3& position);
void warp_to(entity::registry& registry, entity::id eid, const float3& position);
void set_scale(entity::registry& registry, entity::id eid, const float3& scale);
void set_transform(entity::registry& registry, entity::id eid, const math::transform<float>& transform, bool warp = false);
void place(entity::registry& registry, entity::id eid, entity::id celestial_body_id, double altitude, double latitude, double longitude);
void assign_render_layers(entity::registry& registry, entity::id eid, unsigned int layers);
void bind_transform(entity::registry& registry, entity::id source_eid, entity::id target_eid);
math::transform<float> get_local_transform(entity::registry& registry, entity::id eid);
math::transform<float> get_world_transform(entity::registry& registry, entity::id eid);
void parent(entity::registry& registry, entity::id child, entity::id parent);
@ -46,6 +46,7 @@ void rename(entity::registry& registry, entity::id eid, const std::string& name)
entity::id find(entity::registry& registry, const std::string& name);
entity::id create(entity::registry& registry);
entity::id create(entity::registry& registry, const std::string& name);
entity::id find_or_create(entity::registry& registry, const std::string& name);
} // namespace command
} // namespace entity

+ 4
- 2
src/entity/components/camera.hpp View File

@ -25,9 +25,11 @@
namespace entity {
namespace component {
struct flight_controller
/// Camera scene object component.
struct camera
{
/// Pointer to camera scene object
scene::camera* object;
};
} // namespace component

+ 15
- 4
src/entity/components/chamber.hpp View File

@ -27,16 +27,27 @@
namespace entity {
namespace component {
/// Ant nest chamber.
struct chamber
{
entity nest;
float depth;
/// Entity ID of shaft to which the chamber is connected
entity::id shaft_eid;
/// Distance along shaft at which the chamber is located
float distance;
/// Entity ID of the chamber above this chamber
entity::id previous_chamber_eid;
/// Entity ID of the chamber below this chamber
entity::id next_chamber_eid;
float outer_radius;
float inner_radius;
float inner_sector_angle;
float tile_radius;
std::unordered_set<std::array<int, 2>> tiles;
}
//std::unordered_set<std::array<int, 2>> tiles;
};
} // namespace component
} // namespace entity

+ 61
- 0
src/entity/components/constraint-stack.hpp View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_STACK_HPP
#define ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_STACK_HPP
#include "entity/id.hpp"
namespace entity {
namespace component {
/**
* Causes an ordered stack of constraints to be applied to an entity.
*
* @see entity::component::constraint_stack_node
* @see entity::component::constraint
*/
struct constraint_stack
{
/// ID of the entity containing the first constraint stack node.
entity::id head;
};
/**
* Single node in a constraint stack. Allows toggling and weighing of constraints and links to the following constraint stack node (if any).
*
* @see entity::component::constraint_stack
* @see entity::component::constraint
*/
struct constraint_stack_node
{
/// Enables or disables the constraint.
bool active;
/// Controls the amount of influence the constraint has on the final result.
float weight;
/// ID of the entity containing the next constraint in the constraint stack.
entity::id next;
};
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_STACK_HPP

src/entity/components/camera-follow.hpp → src/entity/components/constraints/constraints.hpp View File

@ -17,19 +17,24 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_CAMERA_FOLLOW_HPP
#define ANTKEEPER_ENTITY_COMPONENT_CAMERA_FOLLOW_HPP
#ifndef ANTKEEPER_ENTITY_COMPONENT_CONSTRAINTS_HPP
#define ANTKEEPER_ENTITY_COMPONENT_CONSTRAINTS_HPP
namespace entity {
namespace component {
struct camera_follow
{
};
/// Transform constraint components
namespace constraint {}
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_CAMERA_FOLLOW_HPP
#include "copy-translation.hpp"
#include "copy-rotation.hpp"
#include "copy-scale.hpp"
#include "copy-transform.hpp"
#include "track-to.hpp"
#include "spring-to.hpp"
#include "three-dof.hpp"
#endif // ANTKEEPER_ENTITY_COMPONENT_CONSTRAINTS_HPP

src/entity/components/copy-rotation.hpp → src/entity/components/constraints/copy-rotation.hpp View File

@ -17,20 +17,26 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_COPY_ROTATION_HPP
#define ANTKEEPER_ENTITY_COMPONENT_COPY_ROTATION_HPP
#ifndef ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_ROTATION_HPP
#define ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_ROTATION_HPP
#include "entity/id.hpp"
namespace entity {
namespace component {
namespace constraint {
/**
* Copies the rotation of a target entity.
*/
struct copy_rotation
{
/// Target entity ID.
entity::id target;
};
} // namespace constraint
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_COPY_ROTATION_HPP
#endif // ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_ROTATION_HPP

src/entity/components/copy-scale.hpp → src/entity/components/constraints/copy-scale.hpp View File

@ -17,23 +17,35 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_COPY_SCALE_HPP
#define ANTKEEPER_ENTITY_COMPONENT_COPY_SCALE_HPP
#ifndef ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_SCALE_HPP
#define ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_SCALE_HPP
#include "entity/id.hpp"
namespace entity {
namespace component {
namespace constraint {
/**
* Copies the scale of a target entity.
*/
struct copy_scale
{
/// Target entity ID.
entity::id target;
bool use_x;
bool use_y;
bool use_z;
/// Copy X scale.
bool copy_x;
/// Copy Y scale.
bool copy_y;
/// Copy Z scale.
bool copy_z;
};
} // namespace constraint
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_COPY_SCALE_HPP
#endif // ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_SCALE_HPP

src/entity/components/copy-transform.hpp → src/entity/components/constraints/copy-transform.hpp View File

@ -17,20 +17,26 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_COPY_TRANSFORM_HPP
#define ANTKEEPER_ENTITY_COMPONENT_COPY_TRANSFORM_HPP
#ifndef ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_TRANSFORM_HPP
#define ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_TRANSFORM_HPP
#include "entity/id.hpp"
namespace entity {
namespace component {
namespace constraint {
/**
* Copies the transform of a target entity.
*/
struct copy_transform
{
/// Target entity ID.
entity::id target;
};
} // namespace constraint
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_COPY_TRANSFORM_HPP
#endif // ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_TRANSFORM_HPP

+ 63
- 0
src/entity/components/constraints/copy-translation.hpp View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_TRANSLATION_HPP
#define ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_TRANSLATION_HPP
#include "entity/id.hpp"
namespace entity {
namespace component {
namespace constraint {
/**
* Copies the translation of a target entity.
*/
struct copy_translation
{
/// Target entity ID.
entity::id target;
/// Copy X translation.
bool copy_x;
/// Copy Y translation.
bool copy_y;
/// Copy Z translation.
bool copy_z;
/// Invert the copied X translation.
bool invert_x;
/// Invert the copied Y translation.
bool invert_y;
/// Invert the copied Z translation.
bool invert_z;
/// Add the copied translation.
bool offset;
};
} // namespace constraint
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_COPY_TRANSLATION_HPP

+ 56
- 0
src/entity/components/constraints/spring-to.hpp View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_SPRING_TO_HPP
#define ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_SPRING_TO_HPP
#include "entity/id.hpp"
#include "animation/spring.hpp"
#include "utility/fundamental-types.hpp"
namespace entity {
namespace component {
namespace constraint {
/**
* Springs to a target entity.
*/
struct spring_to
{
/// Target entity ID.
entity::id target;
/// Translation spring.
numeric_spring<float3, float> translation;
/// Rotation spring.
numeric_spring<float4, float> rotation;
/// Spring translation.
bool spring_translation;
/// Spring rotation.
bool spring_rotation;
};
} // namespace constraint
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_SPRING_TO_HPP

+ 46
- 0
src/entity/components/constraints/three-dof.hpp View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_THREE_DOF_HPP
#define ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_THREE_DOF_HPP
namespace entity {
namespace component {
namespace constraint {
/**
* Springs to a target entity.
*/
struct three_dof
{
/// Yaw rotation angle, in radians.
float yaw;
/// Pitch rotation angle, in radians.
float pitch;
/// Roll rotation angle, in radians.
float roll;
};
} // namespace constraint
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_THREE_DOF_HPP

src/entity/components/copy-translation.hpp → src/entity/components/constraints/track-to.hpp View File

@ -17,26 +17,30 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ENTITY_COMPONENT_COPY_TRANSLATION_HPP
#define ANTKEEPER_ENTITY_COMPONENT_COPY_TRANSLATION_HPP
#ifndef ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_TRACK_TO_HPP
#define ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_TRACK_TO_HPP
#include "entity/id.hpp"
#include "utility/fundamental-types.hpp"
namespace entity {
namespace component {
namespace constraint {
struct copy_translation
/**
* Rotates a transform to face a target.
*/
struct track_to
{
/// Target entity ID.
entity::id target;
bool use_x;
bool use_y;
bool use_z;
bool invert_x;
bool invert_y;
bool invert_z;
/// Up direction vector.
float3 up;
};
} // namespace constraint
} // namespace component
} // namespace entity
#endif // ANTKEEPER_ENTITY_COMPONENT_COPY_TRANSLATION_HPP
#endif // ANTKEEPER_ENTITY_COMPONENT_CONSTRAINT_TRACK_TO_HPP

+ 2
- 86
src/entity/systems/camera.cpp View File

@ -18,107 +18,23 @@
*/
#include "camera.hpp"
#include "entity/components/camera-follow.hpp"
#include "entity/components/transform.hpp"
#include "entity/id.hpp"
#include "math/math.hpp"
#include <algorithm>
#include <cmath>
namespace entity {
namespace system {
camera::camera(entity::registry& registry):
updatable(registry),
active_camera(nullptr),
viewport{0, 0, 0, 0},
mouse_position{0, 0}
{
//orbit_cam.set_elevation_limits({math::radians(5.0f), math::radians(89.0f)});
orbit_cam.set_elevation_limits({math::radians(-89.0f), math::radians(89.0f)});
orbit_cam.set_focal_distance_limits({2.0f, 200.0f});
orbit_cam.set_fov_limits({math::radians(80.0f), math::radians(35.0f)});
orbit_cam.set_clip_near_limits({0.1f, 5.0f});
orbit_cam.set_clip_far_limits({100.0f, 5000.0f});
orbit_cam.set_target_focal_point({0.0f, 0.0f, 0.0f});
orbit_cam.set_target_azimuth(0.0f);
orbit_cam.set_target_elevation(math::radians(45.0f));
orbit_cam.set_target_zoom(0.0f);
orbit_cam.set_focal_point_oscillation(hz_to_rads(8.0f));
orbit_cam.set_azimuth_oscillation(hz_to_rads(2.0f));
orbit_cam.set_elevation_oscillation(hz_to_rads(2.0f));
orbit_cam.set_zoom_oscillation(hz_to_rads(5.0f));
orbit_cam.reset_springs();
}
viewport{0, 0, 0, 0}
{}
void camera::update(double t, double dt)
{
if (!active_camera)
return;
// Determine target focal point
int subject_count = 0;
float3 target_focal_point = {0, 0, 0};
registry.view<component::camera_follow, component::transform>().each(
[&](entity::id entity_id, auto& follow, auto& transform)
{
target_focal_point += transform.local.translation;
++subject_count;
});
if (subject_count > 1)
target_focal_point /= static_cast<float>(subject_count);
// Focus at ant's head height off the ground.
target_focal_point.y += 0.2f;
// Check for collision with environment
//...
orbit_cam.set_target_focal_point(target_focal_point);
orbit_cam.update(static_cast<float>(dt));
}
void camera::pan(float angle)
{
orbit_cam.pan(angle);
}
void camera::tilt(float angle)
{
orbit_cam.tilt(angle);
}
void camera::zoom(float factor)
{
orbit_cam.zoom(factor);
}
void camera::set_camera(scene::camera* active_camera)
{
this->active_camera = active_camera;
if (active_camera)
{
orbit_cam.attach(active_camera);
}
else
{
orbit_cam.detach();
}
}
void camera::set_viewport(const float4& viewport)
{
this->viewport = viewport;
orbit_cam.set_aspect_ratio(viewport[2] / viewport[3]);
}
void camera::handle_event(const mouse_moved_event& event)
{
mouse_position[0] = event.x;
mouse_position[1] = event.y;
}
void camera::handle_event(const window_resized_event& event)

+ 1
- 41
src/entity/systems/camera.hpp View File

@ -25,66 +25,26 @@
#include "event/input-events.hpp"
#include "event/window-events.hpp"
#include "utility/fundamental-types.hpp"
#include "math/quaternion-type.hpp"
#include "math/transform-type.hpp"
#include "animation/orbit-cam.hpp"
#include "scene/camera.hpp"
class orbit_cam;
namespace entity {
namespace system {
class camera:
public updatable,
public event_handler<mouse_moved_event>,
public event_handler<window_resized_event>
{
public:
typedef math::quaternion<float> quaternion_type;
typedef math::transform<float> transform_type;
camera(entity::registry& registry);
virtual void update(double t, double dt);
void pan(float angle);
void tilt(float angle);
void zoom(float factor);
void set_camera(scene::camera* active_camera);
void set_viewport(const float4& viewport);
const orbit_cam* get_orbit_cam() const;
orbit_cam* get_orbit_cam();
scene::camera* get_camera();
private:
virtual void handle_event(const mouse_moved_event& event);
virtual void handle_event(const window_resized_event& event);
scene::camera* active_camera;
float4 viewport;
float2 mouse_position;
orbit_cam orbit_cam;
float4 viewport;
};
inline const orbit_cam* camera::get_orbit_cam() const
{
return &orbit_cam;
}
inline orbit_cam* camera::get_orbit_cam()
{
return &orbit_cam;
}
inline scene::camera* camera::get_camera()
{
return active_camera;
}
} // namespace system
} // namespace entity

+ 161
- 55
src/entity/systems/constraint.cpp View File

@ -18,12 +18,9 @@
*/
#include "constraint.hpp"
#include "entity/components/copy-translation.hpp"
#include "entity/components/copy-rotation.hpp"
#include "entity/components/copy-scale.hpp"
#include "entity/components/copy-transform.hpp"
#include "entity/components/constraint-stack.hpp"
#include "entity/components/constraints/constraints.hpp"
#include "entity/components/transform.hpp"
#include "utility/fundamental-types.hpp"
namespace entity {
namespace system {
@ -34,67 +31,176 @@ constraint::constraint(entity::registry& registry):
void constraint::update(double t, double dt)
{
auto transforms_view = registry.view<component::transform>();
// Handle copy translation constraints
registry.view<component::copy_translation, component::transform>().each
(
[&](entity::id entity_id, auto& constraint, auto& transform)
// For each entity with transform and constraint stack components
registry.view<component::transform, component::constraint_stack>().each(
[&](entity::id transform_eid, auto& transform, auto& stack)
{
if (this->registry.has<component::transform>(constraint.target))
// Get entity ID of first constraint
entity::id constraint_eid = stack.head;
// Consecutively apply constraints
while (constraint_eid != entt::null)
{
const float3& target_translation = transforms_view.get(constraint.target).world.translation;
if (constraint.use_x)
transform.world.translation.x = (constraint.invert_x) ? -target_translation.x : target_translation.x;
if (constraint.use_y)
transform.world.translation.y = (constraint.invert_y) ? -target_translation.y : target_translation.y;
if (constraint.use_z)
transform.world.translation.z = (constraint.invert_z) ? -target_translation.z : target_translation.z;
// Invalid constraint
if (!registry.has<component::constraint_stack_node>(constraint_eid))
break;
// Get constraint stack node of this constraint
const auto& node = registry.get<component::constraint_stack_node>(constraint_eid);
// Apply constraint if enabled
if (node.active)
handle_constraint(transform, constraint_eid, static_cast<float>(dt));
// Get entity ID of next constraint
constraint_eid = node.next;
}
}
);
});
}
void constraint::handle_constraint(component::transform& transform, entity::id constraint_eid, float dt)
{
if (registry.has<component::constraint::copy_translation>(constraint_eid))
handle_copy_translation_constraint(transform, constraint_eid);
else if (registry.has<component::constraint::copy_rotation>(constraint_eid))
handle_copy_rotation_constraint(transform, constraint_eid);
else if (registry.has<component::constraint::copy_scale>(constraint_eid))
handle_copy_scale_constraint(transform, constraint_eid);
else if (registry.has<component::constraint::copy_transform>(constraint_eid))
handle_copy_transform_constraint(transform, constraint_eid);
else if (registry.has<component::constraint::track_to>(constraint_eid))
handle_track_to_constraint(transform, constraint_eid);
else if (registry.has<component::constraint::three_dof>(constraint_eid))
handle_three_dof_constraint(transform, constraint_eid);
else if (registry.has<component::constraint::spring_to>(constraint_eid))
handle_spring_to_constraint(transform, constraint_eid, dt);
}
void constraint::handle_copy_translation_constraint(component::transform& transform, entity::id constraint_eid)
{
const auto& params = registry.get<component::constraint::copy_translation>(constraint_eid);
// Handle copy rotation constraints
registry.view<component::copy_rotation, component::transform>().each
(
[&](entity::id entity_id, auto& constraint, auto& transform)
if (this->registry.has<component::transform>(params.target))
{
const auto& target_translation = registry.get<component::transform>(params.target).world.translation;
if (params.offset)
{
if (this->registry.has<component::transform>(constraint.target))
{
transform.world.rotation = transforms_view.get(constraint.target).world.rotation;
}
if (params.copy_x)
transform.world.translation.x += (params.invert_x) ? -target_translation.x : target_translation.x;
if (params.copy_y)
transform.world.translation.y += (params.invert_y) ? -target_translation.y : target_translation.y;
if (params.copy_z)
transform.world.translation.z += (params.invert_z) ? -target_translation.z : target_translation.z;
}
);
// Handle copy scale constraints
registry.view<component::copy_scale, component::transform>().each
(
[&](entity::id entity_id, auto& constraint, auto& transform)
else
{
if (this->registry.has<component::transform>(constraint.target))
{
const float3& target_scale = transforms_view.get(constraint.target).world.scale;
if (constraint.use_x)
transform.world.scale.x = target_scale.x;
if (constraint.use_y)
transform.world.scale.y = target_scale.y;
if (constraint.use_z)
transform.world.scale.z = target_scale.z;
}
if (params.copy_x)
transform.world.translation.x = (params.invert_x) ? -target_translation.x : target_translation.x;
if (params.copy_y)
transform.world.translation.y = (params.invert_y) ? -target_translation.y : target_translation.y;
if (params.copy_z)
transform.world.translation.z = (params.invert_z) ? -target_translation.z : target_translation.z;
}
);
}
}
void constraint::handle_copy_rotation_constraint(component::transform& transform, entity::id constraint_eid)
{
const auto& params = registry.get<component::constraint::copy_rotation>(constraint_eid);
if (this->registry.has<component::transform>(params.target))
{
const auto& target_rotation = registry.get<component::transform>(params.target).world.rotation;
transform.world.rotation = target_rotation;
}
}
void constraint::handle_copy_scale_constraint(component::transform& transform, entity::id constraint_eid)
{
const auto& params = registry.get<component::constraint::copy_scale>(constraint_eid);
// Handle copy transform constraints
registry.view<component::copy_transform, component::transform>().each
(
[&](entity::id entity_id, auto& constraint, auto& transform)
if (this->registry.has<component::transform>(params.target))
{
const auto& target_scale = registry.get<component::transform>(params.target).world.scale;
if (params.copy_x)
transform.world.scale.x = target_scale.x;
if (params.copy_y)
transform.world.scale.y = target_scale.y;
if (params.copy_z)
transform.world.scale.z = target_scale.z;
}
}
void constraint::handle_copy_transform_constraint(component::transform& transform, entity::id constraint_eid)
{
const auto& params = registry.get<component::constraint::copy_transform>(constraint_eid);
if (this->registry.has<component::transform>(params.target))
{
const auto& target_transform = registry.get<component::transform>(params.target).world;
transform.world = target_transform;
}
}
void constraint::handle_track_to_constraint(component::transform& transform, entity::id constraint_eid)
{
const auto& params = registry.get<component::constraint::track_to>(constraint_eid);
if (this->registry.has<component::transform>(params.target))
{
const auto& target_transform = registry.get<component::transform>(params.target).world;
transform.world.rotation = math::look_rotation(math::normalize(math::sub(target_transform.translation, transform.world.translation)), params.up);
}
}
void constraint::handle_three_dof_constraint(component::transform& transform, entity::id constraint_eid)
{
const auto& params = registry.get<component::constraint::three_dof>(constraint_eid);
const math::quaternion<float> yaw = math::angle_axis(params.yaw, {0.0f, 1.0f, 0.0f});
const math::quaternion<float> pitch = math::angle_axis(params.pitch, {-1.0f, 0.0f, 0.0f});
const math::quaternion<float> roll = math::angle_axis(params.roll, {0.0f, 0.0f, -1.0f});
transform.local.rotation = math::normalize(yaw * pitch * roll);
}
void constraint::handle_spring_to_constraint(component::transform& transform, entity::id constraint_eid, float dt)
{
auto& params = registry.get<component::constraint::spring_to>(constraint_eid);
if (this->registry.has<component::transform>(params.target))
{
// Get transform of target entity
const auto& target_transform = registry.get<component::transform>(params.target).world;
// Spring translation
if (params.spring_translation)
{
if (this->registry.has<component::transform>(constraint.target))
{
transform.world = transforms_view.get(constraint.target).world;
}
// Update translation spring target
params.translation.x1 = target_transform.translation;
// Solve translation spring
solve_numeric_spring<float3, float>(params.translation, dt);
// Update transform translation
transform.world.translation = params.translation.x0;
}
// Spring rotation
if (params.spring_rotation)
{
// Update rotation spring target
params.rotation.x1 = {target_transform.rotation.w, target_transform.rotation.x, target_transform.rotation.y, target_transform.rotation.z};
// Solve rotation spring
solve_numeric_spring<float4, float>(params.rotation, dt);
// Update transform rotation
transform.world.rotation = math::normalize(math::quaternion<float>{params.rotation.x0[0], params.rotation.x0[1], params.rotation.x0[2], params.rotation.x0[3]});
}
);
}
}
} // namespace system

+ 20
- 0
src/entity/systems/constraint.hpp View File

@ -21,16 +21,36 @@
#define ANTKEEPER_ENTITY_SYSTEM_CONSTRAINT_HPP
#include "entity/systems/updatable.hpp"
#include "entity/components/transform.hpp"
#include "entity/id.hpp"
namespace entity {
namespace system {
/**
* Applies constraint stacks to transform components.
*
* @see entity::component::constraint_stack
* @see entity::component::constraint_stack_node
* @see entity::component::constraint
*/
class constraint:
public updatable
{
public:
constraint(entity::registry& registry);
virtual void update(double t, double dt);
private:
void handle_constraint(component::transform& transform, entity::id constraint_eid, float dt);
void handle_copy_translation_constraint(component::transform& transform, entity::id constraint_eid);
void handle_copy_rotation_constraint(component::transform& transform, entity::id constraint_eid);
void handle_copy_scale_constraint(component::transform& transform, entity::id constraint_eid);
void handle_copy_transform_constraint(component::transform& transform, entity::id constraint_eid);
void handle_track_to_constraint(component::transform& transform, entity::id constraint_eid);
void handle_three_dof_constraint(component::transform& transform, entity::id constraint_eid);
void handle_spring_to_constraint(component::transform& transform, entity::id constraint_eid, float dt);
};
} // namespace system

+ 8
- 37
src/entity/systems/control.cpp View File

@ -32,12 +32,7 @@ namespace entity {
namespace system {
control::control(entity::registry& registry):
updatable(registry),
timestep(0.0f),
zoom(0.0f),
tool(nullptr),
flashlight_entity(entt::null),
underground_camera(nullptr)
updatable(registry)
{
control_set.add_control(&move_forward_control);
control_set.add_control(&move_back_control);
@ -74,6 +69,8 @@ control::control(entity::registry& registry):
{
control->set_deadzone(0.15f);
}
/*
zoom_speed = 5.0f; //1
min_elevation = math::radians(-85.0f);
@ -96,11 +93,12 @@ control::control(entity::registry& registry):
flashlight_turns = 0.0f;
flashlight_turns_i = 0;
flashlight_turns_f = 0.0f;
*/
}
void control::update(double t, double dt)
{
timestep = dt;
/*
// Zoom camera
if (zoom_in_control.is_active())
@ -192,31 +190,7 @@ void control::update(double t, double dt)
}
}
}
}
void control::set_camera_system(system::camera* camera_system)
{
this->camera_system = camera_system;
}
void control::set_nest(::nest* nest)
{
this->nest = nest;
}
void control::set_tool(scene::model_instance* tool)
{
this->tool = tool;
}
void control::set_flashlight(entity::id entity_id)
{
flashlight_entity = entity_id;
}
void control::set_camera_subject(entity::id entity_id)
{
camera_subject_entity = entity_id;
*/
}
void control::set_viewport(const float4& viewport)
@ -224,13 +198,9 @@ void control::set_viewport(const float4& viewport)
this->viewport = viewport;
}
void control::set_underground_camera(scene::camera* camera)
{
this->underground_camera = camera;
}
void control::handle_event(const mouse_moved_event& event)
{
/*
if (adjust_camera_control.is_active())
{
bool invert_x = true;
@ -260,6 +230,7 @@ void control::handle_event(const mouse_moved_event& event)
mouse_position[0] = event.x;
mouse_position[1] = event.y;
}
*/
}
void control::handle_event(const window_resized_event& event)

+ 0
- 39
src/entity/systems/control.hpp View File

@ -48,17 +48,7 @@ public:
virtual void update(double t, double dt);
void set_invert_mouse_x(bool invert);
void set_invert_mouse_y(bool invert);
void set_camera_system(system::camera* camera_system);
void set_nest(::nest* nest);
void set_tool(scene::model_instance* tool);
void set_flashlight(entity::id entity_id);
void set_camera_subject(entity::id entity_id);
void set_viewport(const float4& viewport);
void set_underground_camera(scene::camera* camera);
input::control_set* get_control_set();
input::control* get_move_forward_control();
@ -123,38 +113,9 @@ private:
input::control rewind_control;
input::control exposure_increase_control;
input::control exposure_decrease_control;
float zoom_speed;
float min_elevation;
float max_elevation;
float near_focal_distance;
float far_focal_distance;
float near_movement_speed;
float far_movement_speed;
float near_fov;
float far_fov;
float near_clip_near;
float far_clip_near;
float near_clip_far;
float far_clip_far;
float timestep;
float zoom;
system::camera* camera_system;
::nest* nest;
scene::model_instance* tool;
float2 mouse_position;
float4 viewport;
entity::id flashlight_entity;
entity::id camera_subject_entity;
scene::camera* underground_camera;
float mouse_angle;
float old_mouse_angle;
float flashlight_turns;
float flashlight_turns_i;
float flashlight_turns_f;
};
inline input::control_set* control::get_control_set()

+ 16
- 0
src/entity/systems/render.cpp View File

@ -19,6 +19,7 @@
#include "render.hpp"
#include "entity/components/transform.hpp"
#include "entity/components/camera.hpp"
#include "renderer/renderer.hpp"
#include "scene/point-light.hpp"
#include "scene/directional-light.hpp"
@ -61,6 +62,21 @@ void render::update(double t, double dt)
}
);
// Update camera transforms
registry.view<component::transform, component::camera>().each
(
[this](entity::id entity_id, auto& transform, auto& camera)
{
camera.object->set_transform(transform.world);
if (transform.warp)
{
camera.object->get_transform_tween().update();
camera.object->update_tweens();
transform.warp = false;
}
}
);
// Update light transforms
registry.view<component::transform, component::light>().each
(

+ 61
- 111
src/game/bootloader.cpp View File

@ -375,7 +375,7 @@ void load_strings(game::context* ctx)
{
debug::logger* logger = ctx->logger;
logger->push_task("Loading strings");
ctx->string_table = ctx->resource_manager->load<string_table>("strings.csv");
build_string_table_map(&ctx->string_table_map, *ctx->string_table);
@ -815,13 +815,11 @@ void setup_systems(game::context* ctx)
// Setup camera system
ctx->camera_system = new entity::system::camera(*ctx->entity_registry);
ctx->camera_system->set_viewport(viewport);
event_dispatcher->subscribe<mouse_moved_event>(ctx->camera_system);
event_dispatcher->subscribe<window_resized_event>(ctx->camera_system);
// Setup tool system
ctx->tool_system = new entity::system::tool(*ctx->entity_registry, event_dispatcher);
ctx->tool_system->set_camera(ctx->surface_camera);
ctx->tool_system->set_orbit_cam(ctx->camera_system->get_orbit_cam());
ctx->tool_system->set_viewport(viewport);
// Setup subterrain system
@ -908,14 +906,8 @@ void setup_systems(game::context* ctx)
// Setup control system
ctx->control_system = new entity::system::control(*ctx->entity_registry);
ctx->control_system->set_viewport(viewport);
ctx->control_system->set_underground_camera(ctx->underground_camera);
ctx->control_system->set_tool(nullptr);
//ctx->control_system->set_flashlight(flashlight, flashlight_light_cone);
ctx->control_system->get_adjust_camera_control()->set_activated_callback([ctx](){ ctx->app->set_relative_mouse_mode(true); ctx->tool_system->set_pick(false); });
ctx->control_system->get_adjust_camera_control()->set_deactivated_callback([ctx](){ ctx->app->set_relative_mouse_mode(false); ctx->tool_system->set_pick(true); });
ctx->control_system->set_flashlight(ctx->flashlight_entity);
ctx->control_system->set_camera_subject(ctx->focal_point_entity);
ctx->control_system->set_camera_system(ctx->camera_system);
event_dispatcher->subscribe<mouse_moved_event>(ctx->control_system);
event_dispatcher->subscribe<window_resized_event>(ctx->control_system);
@ -996,8 +988,23 @@ void setup_controls(game::context* ctx)
ctx->menu_controls->add_control(ctx->menu_back_control);
ctx->menu_controls->add_control(ctx->menu_select_control);
// Create camera controls
ctx->camera_control_modifier = new input::control();
ctx->camera_control_mouse_left = new input::control();
ctx->camera_control_mouse_right = new input::control();
ctx->camera_control_mouse_down = new input::control();
ctx->camera_control_mouse_up = new input::control();
ctx->camera_control_orbit = new input::control();
ctx->camera_control_dolly_forward = new input::control();
ctx->camera_control_dolly_backward = new input::control();
ctx->camera_control_truck_left = new input::control();
ctx->camera_control_truck_right = new input::control();
ctx->camera_control_pedestal_up = new input::control();
ctx->camera_control_pedestal_down = new input::control();
ctx->camera_control_pan_left = new input::control();
ctx->camera_control_pan_right = new input::control();
ctx->camera_control_tilt_up = new input::control();
ctx->camera_control_tilt_down = new input::control();
ctx->camera_controls = ctx->control_system->get_control_set();
@ -1009,7 +1016,7 @@ void setup_controls(game::context* ctx)
ctx->input_event_router->add_mapping(input::key_mapping(ctx->menu_back_control, nullptr, input::scancode::escape));
ctx->input_event_router->add_mapping(input::key_mapping(ctx->menu_back_control, nullptr, input::scancode::backspace));
ctx->input_event_router->add_mapping(input::game_controller_button_mapping(ctx->menu_back_control, nullptr, input::game_controller_button::b));
ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_tool_menu_control(), nullptr, input::scancode::left_shift));
//ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_tool_menu_control(), nullptr, input::scancode::left_shift));
ctx->input_event_router->add_mapping(input::game_controller_button_mapping(ctx->control_system->get_tool_menu_control(), nullptr, input::game_controller_button::x));
ctx->input_event_router->add_mapping(input::key_mapping(ctx->menu_select_control, nullptr, input::scancode::enter));
ctx->input_event_router->add_mapping(input::key_mapping(ctx->menu_select_control, nullptr, input::scancode::space));
@ -1066,7 +1073,7 @@ void setup_controls(game::context* ctx)
ctx->input_event_router->add_mapping(input::game_controller_axis_mapping(ctx->control_system->get_tilt_down_control(), nullptr, input::game_controller_axis::right_y, true));
ctx->input_event_router->add_mapping(input::mouse_wheel_mapping(ctx->control_system->get_zoom_in_control(), nullptr, input::mouse_wheel_axis::positive_y));
ctx->input_event_router->add_mapping(input::mouse_wheel_mapping(ctx->control_system->get_zoom_out_control(), nullptr, input::mouse_wheel_axis::negative_y));
ctx->input_event_router->add_mapping(input::mouse_button_mapping(ctx->control_system->get_adjust_camera_control(), nullptr, 3));
//ctx->input_event_router->add_mapping(input::mouse_button_mapping(ctx->control_system->get_adjust_camera_control(), nullptr, 3));
ctx->input_event_router->add_mapping(input::game_controller_button_mapping(ctx->control_system->get_ascend_control(), nullptr, input::game_controller_button::y));
ctx->input_event_router->add_mapping(input::game_controller_button_mapping(ctx->control_system->get_descend_control(), nullptr, input::game_controller_button::a));
ctx->input_event_router->add_mapping(input::game_controller_axis_mapping(ctx->control_system->get_zoom_out_control(), nullptr, input::game_controller_axis::trigger_left, false));
@ -1087,107 +1094,29 @@ void setup_controls(game::context* ctx)
ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_equip_lens_control(), nullptr, input::scancode::five));
ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_equip_marker_control(), nullptr, input::scancode::six));
//ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_next_marker_control(), nullptr, input::scancode::right_brace));
//ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_previous_marker_control(), nullptr, input::scancode::left_brace));
ctx->input_event_router->add_mapping(input::mouse_button_mapping(ctx->control_system->get_use_tool_control(), nullptr, 1));
ctx->control_system->get_use_tool_control()->set_activated_callback
(
[ctx]()
{
ctx->tool_system->set_tool_active(true);
}
);
ctx->control_system->get_use_tool_control()->set_deactivated_callback
(
[ctx]()
{
ctx->tool_system->set_tool_active(false);
}
);
ctx->input_event_router->add_mapping(input::key_mapping(ctx->camera_control_modifier, nullptr, input::scancode::left_shift));
ctx->input_event_router->add_mapping(input::key_mapping(ctx->camera_control_dolly_forward, nullptr, input::scancode::w));
ctx->input_event_router->add_mapping(input::game_controller_axis_mapping(ctx->camera_control_dolly_forward, nullptr, input::game_controller_axis::left_y, true));
ctx->input_event_router->add_mapping(input::key_mapping(ctx->camera_control_dolly_backward, nullptr, input::scancode::s));
ctx->input_event_router->add_mapping(input::game_controller_axis_mapping(ctx->camera_control_dolly_backward, nullptr, input::game_controller_axis::left_y, false));
ctx->input_event_router->add_mapping(input::key_mapping(ctx->camera_control_truck_left, nullptr, input::scancode::a));
ctx->input_event_router->add_mapping(input::game_controller_axis_mapping(ctx->camera_control_truck_left, nullptr, input::game_controller_axis::left_x, true));
ctx->input_event_router->add_mapping(input::key_mapping(ctx->camera_control_truck_right, nullptr, input::scancode::d));
ctx->input_event_router->add_mapping(input::game_controller_axis_mapping(ctx->camera_control_truck_right, nullptr, input::game_controller_axis::left_x, false));
ctx->control_system->get_equip_forceps_control()->set_activated_callback
(
[ctx]()
{
ctx->tool_system->set_active_tool(ctx->forceps_entity);
}
);
ctx->control_system->get_equip_brush_control()->set_activated_callback
(
[ctx]()
{
ctx->tool_system->set_active_tool(ctx->brush_entity);
}
);
ctx->control_system->get_equip_lens_control()->set_activated_callback
(
[ctx]()
{
ctx->tool_system->set_active_tool(ctx->lens_entity);
}
);
ctx->control_system->get_equip_marker_control()->set_activated_callback
(
[ctx]()
{
ctx->tool_system->set_active_tool(ctx->marker_entity);
}
);
ctx->control_system->get_equip_container_control()->set_activated_callback
(
[ctx]()
{
ctx->tool_system->set_active_tool(ctx->container_entity);
}
);
ctx->control_system->get_equip_twig_control()->set_activated_callback
(
[ctx]()
{
ctx->tool_system->set_active_tool(ctx->twig_entity);
}
);
ctx->input_event_router->add_mapping(input::mouse_wheel_mapping(ctx->camera_control_pedestal_up, nullptr, input::mouse_wheel_axis::positive_y));
ctx->input_event_router->add_mapping(input::mouse_wheel_mapping(ctx->camera_control_pedestal_down, nullptr, input::mouse_wheel_axis::negative_y));
ctx->control_system->get_next_marker_control()->set_activated_callback
(
[ctx]()
{
auto& marker = ctx->entity_registry->get<entity::component::marker>(ctx->marker_entity);
marker.color = (marker.color + 1) % 8;
const gl::texture_2d* marker_albedo_texture = ctx->marker_albedo_textures[marker.color];
model* marker_model = ctx->render_system->get_model_instance(ctx->marker_entity)->get_model();
for (::model_group* group: *marker_model->get_groups())
{
material_property_base* albedo_property = group->get_material()->get_property("albedo_texture");
if (albedo_property)
{
static_cast<material_property<const gl::texture_2d*>*>(albedo_property)->set_value(marker_albedo_texture);
}
}
}
);
ctx->input_event_router->add_mapping(input::mouse_button_mapping(ctx->camera_control_orbit, nullptr, 3));
ctx->input_event_router->add_mapping(input::mouse_motion_mapping(ctx->camera_control_mouse_left, nullptr, input::mouse_motion_axis::negative_x));
ctx->input_event_router->add_mapping(input::mouse_motion_mapping(ctx->camera_control_mouse_right, nullptr, input::mouse_motion_axis::positive_x));
ctx->input_event_router->add_mapping(input::mouse_motion_mapping(ctx->camera_control_mouse_down, nullptr, input::mouse_motion_axis::positive_y));
ctx->input_event_router->add_mapping(input::mouse_motion_mapping(ctx->camera_control_mouse_up, nullptr, input::mouse_motion_axis::negative_y));
//ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_next_marker_control(), nullptr, input::scancode::right_brace));
//ctx->input_event_router->add_mapping(input::key_mapping(ctx->control_system->get_previous_marker_control(), nullptr, input::scancode::left_brace));
ctx->control_system->get_previous_marker_control()->set_activated_callback
(
[ctx]()
{
auto& marker = ctx->entity_registry->get<entity::component::marker>(ctx->marker_entity);
marker.color = (marker.color + 7) % 8;
const gl::texture_2d* marker_albedo_texture = ctx->marker_albedo_textures[marker.color];
model* marker_model = ctx->render_system->get_model_instance(ctx->marker_entity)->get_model();
for (::model_group* group: *marker_model->get_groups())
{
material_property_base* albedo_property = group->get_material()->get_property("albedo_texture");
if (albedo_property)
{
static_cast<material_property<const gl::texture_2d*>*>(albedo_property)->set_value(marker_albedo_texture);
}
}
}
);
float time_scale = ctx->config->get<float>("time_scale");
@ -1265,7 +1194,10 @@ void setup_callbacks(game::context* ctx)
ctx->timeline->advance(dt);
ctx->control_system->update(t, dt);
ctx->terrain_system->update(t, dt);
//ctx->vegetation_system->update(t, dt);
ctx->snapping_system->update(t, dt);
@ -1304,6 +1236,24 @@ void setup_callbacks(game::context* ctx)
ctx->application_controls->update();
ctx->menu_controls->update();
ctx->camera_controls->update();
ctx->control_system->update(t, dt);
ctx->camera_control_modifier->update();
ctx->camera_control_mouse_left->update();
ctx->camera_control_mouse_right->update();
ctx->camera_control_mouse_down->update();
ctx->camera_control_mouse_up->update();
ctx->camera_control_dolly_forward->update();
ctx->camera_control_dolly_backward->update();
ctx->camera_control_truck_left->update();
ctx->camera_control_truck_right->update();
ctx->camera_control_pedestal_up->update();
ctx->camera_control_pedestal_down->update();
ctx->camera_control_pan_left->update();
ctx->camera_control_pan_right->update();
ctx->camera_control_tilt_up->update();
ctx->camera_control_tilt_down->update();
ctx->camera_control_orbit->update();
}
);

+ 17
- 1
src/game/context.hpp View File

@ -228,6 +228,23 @@ struct context
input::control* menu_select_control;
input::control* screenshot_control;
input::control* toggle_fullscreen_control;
input::control* camera_control_mouse_left;
input::control* camera_control_mouse_right;
input::control* camera_control_mouse_down;
input::control* camera_control_mouse_up;
input::control* camera_control_orbit;
input::control* camera_control_dolly_forward;
input::control* camera_control_dolly_backward;
input::control* camera_control_truck_left;
input::control* camera_control_truck_right;
input::control* camera_control_pedestal_up;
input::control* camera_control_pedestal_down;
input::control* camera_control_pan_left;
input::control* camera_control_pan_right;
input::control* camera_control_tilt_up;
input::control* camera_control_tilt_down;
input::control* camera_control_modifier;
// Entities
entity::registry* entity_registry;
@ -264,7 +281,6 @@ struct context
entity::system::astronomy* astronomy_system;
entity::system::orbit* orbit_system;
entity::system::proteome* proteome_system;
std::unordered_map<std::string, entity::id> named_entities;
// Game
biome* biome;

+ 361
- 27
src/game/states/brood.cpp View File

@ -21,9 +21,13 @@
#include "entity/archetype.hpp"
#include "entity/commands.hpp"
#include "entity/components/observer.hpp"
#include "entity/components/camera-follow.hpp"
#include "entity/components/camera.hpp"
#include "entity/components/terrain.hpp"
#include "entity/components/transform.hpp"
#include "entity/components/chamber.hpp"
#include "entity/components/constraints/spring-to.hpp"
#include "entity/components/constraints/three-dof.hpp"
#include "entity/components/constraint-stack.hpp"
#include "entity/systems/control.hpp"
#include "entity/systems/camera.hpp"
#include "entity/systems/tool.hpp"
@ -31,48 +35,34 @@
#include "animation/ease.hpp"
#include "resources/resource-manager.hpp"
#include "renderer/passes/sky-pass.hpp"
#include "application.hpp"
#include <iostream>
namespace game {
namespace state {
namespace brood {
static void setup_nest(game::context* ctx);
static void setup_ants(game::context* ctx);
static void setup_camera(game::context* ctx);
static void setup_controls(game::context* ctx);
void enter(game::context* ctx)
{
// Switch to underground camera
ctx->surface_camera->set_active(false);
ctx->underground_camera->set_active(true);
setup_nest(ctx);
setup_ants(ctx);
setup_camera(ctx);
setup_controls(ctx);
ctx->underground_ambient_light->set_intensity(1.0f);
// Create camera focal point
{
entity::component::transform focal_point_transform;
focal_point_transform.local = math::identity_transform<float>;
focal_point_transform.warp = true;
ctx->entity_registry->assign_or_replace<entity::component::transform>(ctx->focal_point_entity, focal_point_transform);
entity::component::camera_follow focal_point_follow;
ctx->entity_registry->assign_or_replace<entity::component::camera_follow>(ctx->focal_point_entity, focal_point_follow);
}
// Setup camera
ctx->underground_camera->look_at({0, 0, 1}, {0, 0, 0}, {0, 1, 0});
ctx->underground_camera->set_exposure(0.0f);
ctx->camera_system->set_camera(ctx->underground_camera);
ctx->tool_system->set_camera(ctx->underground_camera);
ctx->tool_system->set_orbit_cam(ctx->camera_system->get_orbit_cam());
entity::system::control* control_system = ctx->control_system;
control_system->update(0.0, 0.0);
control_system->set_nest(nullptr);
// Create larva
{
entity::archetype* larva_archetype = ctx->resource_manager->load<entity::archetype>("ant-larva.ent");
auto larva_eid = larva_archetype->create(*ctx->entity_registry);
entity::command::warp_to(*ctx->entity_registry, larva_eid, {0.0f, 0.0f, 0.0f});
entity::command::assign_render_layers(*ctx->entity_registry, larva_eid, 0b1);
entity::command::rename(*ctx->entity_registry, larva_eid, "larva");
}
// Create cocoon
@ -81,8 +71,10 @@ void enter(game::context* ctx)
auto cocoon_eid = cocoon_archetype->create(*ctx->entity_registry);
entity::command::warp_to(*ctx->entity_registry, cocoon_eid, {-50, 0.1935f, 0});
entity::command::assign_render_layers(*ctx->entity_registry, cocoon_eid, 0b1);
entity::command::rename(*ctx->entity_registry, cocoon_eid, "cocoon");
}
// Reset tweening
ctx->underground_scene->update_tweens();
// Start fade in
@ -92,6 +84,348 @@ void enter(game::context* ctx)
void exit(game::context* ctx)
{}
void setup_nest(game::context* ctx)
{
// Find or create nest central shaft entity
entity::id shaft_eid = entity::command::find(*ctx->entity_registry, "shaft");
if (shaft_eid == entt::null)
{
shaft_eid = entity::command::create(*ctx->entity_registry, "shaft");
entity::component::transform transform;
transform.local = math::identity_transform<float>;
transform.world = transform.local;
transform.warp = true;
ctx->entity_registry->assign<entity::component::transform>(shaft_eid, transform);
}
// Find or create nest lobby chamber entity
entity::id lobby_eid = entity::command::find(*ctx->entity_registry, "lobby");
if (lobby_eid == entt::null)
{
lobby_eid = entity::command::create(*ctx->entity_registry, "lobby");
entity::component::chamber chamber;
chamber.shaft_eid = shaft_eid;
chamber.distance = 10.0f;
chamber.previous_chamber_eid = entt::null;
chamber.next_chamber_eid = entt::null;
}
// Find or create nest shaft elevator entity
entity::id elevator_eid = entity::command::find(*ctx->entity_registry, "elevator");
if (elevator_eid == entt::null)
{
elevator_eid = entity::command::create(*ctx->entity_registry, "elevator");
// Create transform component
entity::component::transform transform;
transform.local = math::identity_transform<float>;
transform.world = transform.local;
transform.warp = true;
ctx->entity_registry->assign<entity::component::transform>(elevator_eid, transform);
/*
entity::component::constraint::follow_curve follow_curve;
follow_curve.target_eid = shaft_eid;
follow_curve.offset = 10.0f;
*/
}
}
void setup_ants(game::context* ctx)
{
// Find or create queen ant entity
entity::id queen_eid = entity::command::find(*ctx->entity_registry, "queen");
if (queen_eid == entt::null)
{
queen_eid = entity::command::create(*ctx->entity_registry, "queen");
}
}
void setup_camera(game::context* ctx)
{
// Switch to underground camera
ctx->surface_camera->set_active(false);
ctx->underground_camera->set_active(true);
// Get underground camera entity
entity::id camera_eid = entity::command::find(*ctx->entity_registry, "underground_cam");
if (camera_eid == entt::null)
{
// Create camera target entity
entity::id target_eid = entity::command::create(*ctx->entity_registry, "underground_cam_target");
{
// Transform
entity::component::transform target_transform;
target_transform.local = math::identity_transform<float>;
target_transform.world = target_transform.local;
target_transform.warp = true;
ctx->entity_registry->assign<entity::component::transform>(target_eid, target_transform);
// 3DOF constraint
entity::id three_dof_eid = entity::command::create(*ctx->entity_registry, "underground_cam_3dof");
entity::component::constraint::three_dof three_dof;
three_dof.yaw = 0.0f;
three_dof.pitch = 0.0f;
three_dof.roll = 0.0f;
ctx->entity_registry->assign<entity::component::constraint::three_dof>(three_dof_eid, three_dof);
entity::component::constraint_stack_node node;
node.active = true;
node.weight = 1.0f;
node.next = entt::null;
ctx->entity_registry->assign<entity::component::constraint_stack_node>(three_dof_eid, node);
// Create target constraint stack component
entity::component::constraint_stack constraint_stack;
constraint_stack.head = three_dof_eid;
ctx->entity_registry->assign<entity::component::constraint_stack>(target_eid, constraint_stack);
}
// Create camera entity
camera_eid = entity::command::create(*ctx->entity_registry, "underground_cam");
// Create camera transform component
entity::component::transform transform;
transform.local = math::identity_transform<float>;
transform.world = transform.local;
transform.warp = true;
ctx->entity_registry->assign<entity::component::transform>(camera_eid, transform);
// Create camera camera component
entity::component::camera camera;
camera.object = ctx->underground_camera;
ctx->entity_registry->assign<entity::component::camera>(camera_eid, camera);
// Create camera spring to constraint entity
entity::id spring_constraint_eid = entity::command::create(*ctx->entity_registry);
{
// Create spring to constraint
entity::component::constraint::spring_to spring;
spring.target = target_eid;
spring.translation = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 1.0f, math::two_pi<float>};
spring.translation.w = hz_to_rads(8.0f);
spring.rotation = {{1.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}, 1.0f, math::two_pi<float>};
spring.rotation.w = hz_to_rads(8.0f);
spring.spring_translation = true;
spring.spring_rotation = true;
ctx->entity_registry->assign<entity::component::constraint::spring_to>(spring_constraint_eid, spring);
// Create constraint stack node component
entity::component::constraint_stack_node node;
node.active = true;
node.weight = 1.0f;
node.next = entt::null;
ctx->entity_registry->assign<entity::component::constraint_stack_node>(spring_constraint_eid, node);
}
// Create camera constraint stack component
entity::component::constraint_stack constraint_stack;
constraint_stack.head = spring_constraint_eid;
ctx->entity_registry->assign<entity::component::constraint_stack>(camera_eid, constraint_stack);
}
/*
entity::component::orbit_rig orbit;
orbit.azimuth_min = -std::numeric_limits<float>::infinity();
orbit.azimuth_max = std::numeric_limits<float>::infinity();
orbit.elevation_min = math::radians(-89.0f);
orbit.elevation_max = math::radians(89.0f);
orbit.dolly_min = 2.0f;
orbit.dolly_max = 200.0f;
orbit.fov_near = math::radians(80.0f);
orbit.fov_far = math::radians(35.0f);
orbit.clip_near_min = 0.1f;
orbit.clip_near_max = 5.0f;
orbit.clip_far_min = 100.0f;
orbit.clip_far_max = 5000.0f;
*/
ctx->underground_camera->set_exposure(0.0f);
}
void setup_controls(game::context* ctx)
{
// Get underground camera entity
entity::id camera_eid = entity::command::find(*ctx->entity_registry, "underground_cam");
entity::id target_eid = entity::command::find(*ctx->entity_registry, "underground_cam_target");
entity::id three_dof_eid = entity::command::find(*ctx->entity_registry, "underground_cam_3dof");
const float dolly_speed = 10.0f;
const float truck_speed = dolly_speed;
const float pedestal_speed = 20.0f;
const float pan_speed = math::radians(10.0f);
const float tilt_speed = pan_speed;
ctx->camera_control_dolly_forward->set_active_callback
(
[ctx, target_eid, three_dof_eid, truck_speed](float value)
{
auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
const float3 movement = {0.0f, 0.0f, -truck_speed * value * (1.0f / 60.0f)};
entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
}
);
ctx->camera_control_dolly_backward->set_active_callback
(
[ctx, target_eid, three_dof_eid, truck_speed](float value)
{
auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
const float3 movement = {0.0f, 0.0f, truck_speed * value * (1.0f / 60.0f)};
entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
}
);
ctx->camera_control_truck_right->set_active_callback
(
[ctx, target_eid, three_dof_eid, truck_speed](float value)
{
auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
}
);
ctx->camera_control_truck_left->set_active_callback
(
[ctx, target_eid, three_dof_eid, truck_speed](float value)
{
auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
}
);
// Pedestal up
ctx->camera_control_pedestal_up->set_activated_callback
(
[ctx, target_eid]()
{
if (ctx->camera_control_modifier->is_active())
{
// Snap to chamber
// Find closest chamber
// Pedestal to chamber + offset
}
}
);
ctx->camera_control_pedestal_up->set_active_callback
(
[ctx, target_eid, pedestal_speed](float value)
{
if (!ctx->camera_control_modifier->is_active())
{
const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f};
entity::command::translate(*ctx->entity_registry, target_eid, movement);
}
}
);
// Pedestal down
ctx->camera_control_pedestal_down->set_activated_callback
(
[ctx, target_eid]()
{
//...
}
);
ctx->camera_control_pedestal_down->set_active_callback
(
[ctx, target_eid, pedestal_speed](float value)
{
if (!ctx->camera_control_modifier->is_active())
{
const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f};
entity::command::translate(*ctx->entity_registry, target_eid, movement);
}
}
);
ctx->camera_control_orbit->set_activated_callback
(
[ctx]()
{
ctx->app->set_relative_mouse_mode(true);
}
);
ctx->camera_control_orbit->set_deactivated_callback
(
[ctx]()
{
ctx->app->set_relative_mouse_mode(false);
}
);
// Pan left
ctx->camera_control_mouse_left->set_active_callback
(
[ctx, three_dof_eid, pan_speed](float value)
{
if (!ctx->camera_control_orbit->is_active())
return;
auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
three_dof.yaw += pan_speed * value * (1.0f / 60.0f);
}
);
// Pan right
ctx->camera_control_mouse_right->set_active_callback
(
[ctx, three_dof_eid, pan_speed](float value)
{
if (!ctx->camera_control_orbit->is_active())
return;
auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
three_dof.yaw -= pan_speed * value * (1.0f / 60.0f);
}
);
// Tilt up
ctx->camera_control_mouse_up->set_active_callback
(
[ctx, three_dof_eid, tilt_speed](float value)
{
if (!ctx->camera_control_orbit->is_active())
return;
auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
three_dof.pitch -= tilt_speed * value * (1.0f / 60.0f);
three_dof.pitch = std::max<float>(math::radians(-89.0f), three_dof.pitch);
}
);
// Tilt down
ctx->camera_control_mouse_down->set_active_callback
(
[ctx, three_dof_eid, tilt_speed](float value)
{
if (!ctx->camera_control_orbit->is_active())
return;
auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
three_dof.pitch += tilt_speed * value * (1.0f / 60.0f);
three_dof.pitch = std::min<float>(math::radians(89.0f), three_dof.pitch);
}
);
}
} // namespace brood
} // namespace state
} // namespace game

+ 0
- 17
src/game/states/forage.cpp View File

@ -21,7 +21,6 @@
#include "entity/archetype.hpp"
#include "entity/commands.hpp"
#include "entity/components/observer.hpp"
#include "entity/components/camera-follow.hpp"
#include "entity/components/terrain.hpp"
#include "entity/components/transform.hpp"
#include "entity/systems/astronomy.hpp"
@ -72,25 +71,9 @@ void enter(game::context* ctx)
ctx->astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude});
}
// Create camera focal point
{
entity::component::transform focal_point_transform;
focal_point_transform.local = math::identity_transform<float>;
focal_point_transform.warp = true;
ctx->entity_registry->assign_or_replace<entity::component::transform>(ctx->focal_point_entity, focal_point_transform);
entity::component::camera_follow focal_point_follow;
ctx->entity_registry->assign_or_replace<entity::component::camera_follow>(ctx->focal_point_entity, focal_point_follow);
}
// Setup camera
ctx->surface_camera->look_at({0, 0, 1}, {0, 0, 0}, {0, 1, 0});
ctx->surface_camera->set_exposure(-14.5f);
ctx->camera_system->set_camera(ctx->surface_camera);
entity::system::control* control_system = ctx->control_system;
control_system->update(0.0, 0.0);
control_system->set_nest(nullptr);
// Create larva
{

+ 0
- 16
src/game/states/nuptial-flight.cpp View File

@ -24,7 +24,6 @@
#include "entity/systems/control.hpp"
#include "entity/systems/camera.hpp"
#include "entity/components/observer.hpp"
#include "entity/components/camera-follow.hpp"
#include "entity/components/transform.hpp"
#include "entity/components/terrain.hpp"
#include "entity/commands.hpp"
@ -86,24 +85,9 @@ void enter(game::context* ctx)
auto orb_ring_eid = ctx->entity_registry->create();
//orb_ring_archetype->assign(*ctx->entity_registry, orb_ring_eid);
// Create camera focal point
{
entity::component::transform focal_point_transform;
focal_point_transform.local = math::identity_transform<float>;
focal_point_transform.warp = true;
ctx->entity_registry->assign_or_replace<entity::component::transform>(ctx->focal_point_entity, focal_point_transform);
entity::component::camera_follow focal_point_follow;
ctx->entity_registry->assign_or_replace<entity::component::camera_follow>(ctx->focal_point_entity, focal_point_follow);
}
// Setup camera
ctx->surface_camera->look_at({0, 0, 1}, {0, 0, 0}, {0, 1, 0});
ctx->surface_camera->set_exposure(-14.5f);
ctx->camera_system->set_camera(ctx->surface_camera);
entity::system::control* control_system = ctx->control_system;
control_system->update(0.0, 0.0);
ctx->surface_scene->update_tweens();

+ 11
- 0
src/input/control.cpp View File

@ -29,6 +29,7 @@ control::control():
activated_callback(nullptr),
deactivated_callback(nullptr),
value_changed_callback(nullptr),
active_callback(nullptr),
callbacks_enabled(true)
{}
@ -66,6 +67,11 @@ void control::update()
}
}
}
if (active_callback && is_active())
{
active_callback(current_value);
}
}
// Update previous value
@ -111,4 +117,9 @@ void control::set_value_changed_callback(std::function callback)
this->value_changed_callback = callback;
}
void control::set_active_callback(std::function<void(float)> callback)
{
this->active_callback = callback;
}
} // namespace input

+ 4
- 0
src/input/control.hpp View File

@ -68,6 +68,9 @@ public:
/// Sets the callback for when the control value is changed.
void set_value_changed_callback(std::function<void(float)> callback);
/// Sets the callback for while the control is active.
void set_active_callback(std::function<void(float)> callback);
/**
* Enables or disables callbacks.
@ -99,6 +102,7 @@ private:
std::function<void()> activated_callback;
std::function<void()> deactivated_callback;
std::function<void(float)> value_changed_callback;
std::function<void(float)> active_callback;
bool callbacks_enabled;
};

+ 8
- 8
src/input/event-router.cpp View File

@ -235,19 +235,19 @@ void event_router::handle_event(const mouse_moved_event& event)
{
if (mapping->axis == mouse_motion_axis::negative_x && event.dx < 0)
{
mapping->control->set_temporary_value(-event.dx);
mapping->control->set_temporary_value(mapping->control->get_current_value() - event.dx);
}
else if (mapping->axis == mouse_motion_axis::positive_x && event.dx > 0)
{
mapping->control->set_temporary_value(event.dx);
mapping->control->set_temporary_value(mapping->control->get_current_value() + event.dx);
}
else if (mapping->axis == mouse_motion_axis::negative_y && event.dy < 0)
{
mapping->control->set_temporary_value(-event.dy);
mapping->control->set_temporary_value(mapping->control->get_current_value() - event.dy);
}
else if (mapping->axis == mouse_motion_axis::positive_y && event.dy > 0)
{
mapping->control->set_temporary_value(event.dy);
mapping->control->set_temporary_value(mapping->control->get_current_value() + event.dy);
}
}
}
@ -261,19 +261,19 @@ void event_router::handle_event(const mouse_wheel_scrolled_event& event)
{
if (mapping->axis == mouse_wheel_axis::negative_x && event.x < 0)
{
mapping->control->set_temporary_value(-event.x);
mapping->control->set_temporary_value(mapping->control->get_current_value() - event.x);
}
else if (mapping->axis == mouse_wheel_axis::positive_x && event.x > 0)
{
mapping->control->set_temporary_value(event.x);
mapping->control->set_temporary_value(mapping->control->get_current_value() + event.x);
}
else if (mapping->axis == mouse_wheel_axis::negative_y && event.y < 0)
{
mapping->control->set_temporary_value(-event.y);
mapping->control->set_temporary_value(mapping->control->get_current_value() - event.y);
}
else if (mapping->axis == mouse_wheel_axis::positive_y && event.y > 0)
{
mapping->control->set_temporary_value(event.y);
mapping->control->set_temporary_value(mapping->control->get_current_value() + event.y);
}
}
}

Loading…
Cancel
Save