Browse Source

Replace mesh class with new brep_mesh class. Add initial bvh class. Revise vector, matrix, and quaternion type naming conventions.

master
C. J. Howard 9 months ago
parent
commit
46de558337
207 changed files with 5436 additions and 4690 deletions
  1. +1
    -0
      CMakeLists.txt
  2. +7
    -7
      src/engine/ai/steering/agent.hpp
  3. +3
    -3
      src/engine/ai/steering/behavior/flee.cpp
  4. +2
    -2
      src/engine/ai/steering/behavior/flee.hpp
  5. +3
    -3
      src/engine/ai/steering/behavior/seek.cpp
  6. +2
    -2
      src/engine/ai/steering/behavior/seek.hpp
  7. +7
    -7
      src/engine/ai/steering/behavior/wander.cpp
  8. +3
    -3
      src/engine/ai/steering/behavior/wander.hpp
  9. +2
    -2
      src/engine/animation/ik/constraints/euler-ik-constraint.cpp
  10. +4
    -4
      src/engine/animation/ik/constraints/euler-ik-constraint.hpp
  11. +4
    -4
      src/engine/animation/ik/constraints/swing-twist-ik-constraint.cpp
  12. +1
    -1
      src/engine/animation/ik/constraints/swing-twist-ik-constraint.hpp
  13. +1
    -1
      src/engine/animation/ik/ik-constraint.hpp
  14. +6
    -6
      src/engine/animation/ik/solvers/ccd-ik-solver.hpp
  15. +1
    -1
      src/engine/animation/screen-transition.cpp
  16. +1
    -1
      src/engine/animation/screen-transition.hpp
  17. +2
    -2
      src/engine/app/sdl/sdl-window-manager.cpp
  18. +2
    -2
      src/engine/app/sdl/sdl-window-manager.hpp
  19. +6
    -6
      src/engine/app/sdl/sdl-window.cpp
  20. +6
    -6
      src/engine/app/sdl/sdl-window.hpp
  21. +2
    -2
      src/engine/app/window-events.hpp
  22. +2
    -2
      src/engine/app/window-manager.hpp
  23. +18
    -18
      src/engine/app/window.hpp
  24. +6
    -6
      src/engine/color/aces.hpp
  25. +9
    -9
      src/engine/color/cat.hpp
  26. +4
    -4
      src/engine/color/cct.hpp
  27. +51
    -51
      src/engine/color/illuminant.hpp
  28. +15
    -15
      src/engine/color/rgb.hpp
  29. +2
    -2
      src/engine/color/srgb.hpp
  30. +2
    -2
      src/engine/color/ucs.hpp
  31. +5
    -5
      src/engine/color/xyy.hpp
  32. +5
    -5
      src/engine/color/xyz.hpp
  33. +395
    -0
      src/engine/geom/brep/brep-attribute-map.hpp
  34. +266
    -0
      src/engine/geom/brep/brep-attribute.hpp
  35. +132
    -0
      src/engine/geom/brep/brep-edge.cpp
  36. +330
    -0
      src/engine/geom/brep/brep-edge.hpp
  37. +329
    -0
      src/engine/geom/brep/brep-element-container.hpp
  38. +158
    -0
      src/engine/geom/brep/brep-face.cpp
  39. +322
    -0
      src/engine/geom/brep/brep-face.hpp
  40. +32
    -0
      src/engine/geom/brep/brep-loop.cpp
  41. +114
    -0
      src/engine/geom/brep/brep-loop.hpp
  42. +182
    -0
      src/engine/geom/brep/brep-mesh.cpp
  43. +126
    -0
      src/engine/geom/brep/brep-mesh.hpp
  44. +106
    -0
      src/engine/geom/brep/brep-operations.cpp
  45. +54
    -0
      src/engine/geom/brep/brep-operations.hpp
  46. +102
    -0
      src/engine/geom/brep/brep-vertex.cpp
  47. +312
    -0
      src/engine/geom/brep/brep-vertex.hpp
  48. +51
    -0
      src/engine/geom/bvh/bvh-node.hpp
  49. +14
    -14
      src/engine/geom/bvh/bvh-primitive.hpp
  50. +199
    -0
      src/engine/geom/bvh/bvh.cpp
  51. +113
    -0
      src/engine/geom/bvh/bvh.hpp
  52. +4
    -4
      src/engine/geom/cartesian.hpp
  53. +24
    -20
      src/engine/geom/intersection.hpp
  54. +0
    -179
      src/engine/geom/mesh-accelerator.cpp
  55. +0
    -80
      src/engine/geom/mesh-accelerator.hpp
  56. +0
    -222
      src/engine/geom/mesh-functions.cpp
  57. +0
    -76
      src/engine/geom/mesh-functions.hpp
  58. +0
    -436
      src/engine/geom/mesh.cpp
  59. +0
    -216
      src/engine/geom/mesh.hpp
  60. +0
    -102
      src/engine/geom/meshes/grid.cpp
  61. +51
    -44
      src/engine/geom/morton.hpp
  62. +5
    -5
      src/engine/geom/primitives/hyperrectangle.hpp
  63. +2
    -2
      src/engine/geom/primitives/view-frustum.hpp
  64. +1
    -1
      src/engine/geom/projection.hpp
  65. +5
    -5
      src/engine/geom/sdf.hpp
  66. +4
    -4
      src/engine/geom/spherical.hpp
  67. +60
    -60
      src/engine/gl/opengl/gl-shader-variables.cpp
  68. +94
    -94
      src/engine/gl/opengl/gl-shader-variables.hpp
  69. +15
    -15
      src/engine/gl/shader-program.cpp
  70. +19
    -19
      src/engine/gl/shader-variable-type.hpp
  71. +45
    -45
      src/engine/gl/shader-variable.cpp
  72. +47
    -46
      src/engine/gl/shader-variable.hpp
  73. +6
    -6
      src/engine/input/mouse-events.hpp
  74. +2
    -2
      src/engine/input/mouse.cpp
  75. +4
    -4
      src/engine/input/mouse.hpp
  76. +0
    -217
      src/engine/math/glsl.hpp
  77. +122
    -40
      src/engine/math/matrix.hpp
  78. +54
    -24
      src/engine/math/quaternion.hpp
  79. +3
    -3
      src/engine/math/se3.hpp
  80. +4
    -4
      src/engine/math/transform.hpp
  81. +36
    -0
      src/engine/math/types.hpp
  82. +115
    -8
      src/engine/math/vector.hpp
  83. +6
    -6
      src/engine/physics/gas/atmosphere.hpp
  84. +5
    -5
      src/engine/physics/kinematics/colliders/box-collider.hpp
  85. +5
    -5
      src/engine/physics/kinematics/colliders/plane-collider.hpp
  86. +3
    -3
      src/engine/physics/kinematics/colliders/sphere-collider.hpp
  87. +2
    -2
      src/engine/physics/kinematics/collision-contact.hpp
  88. +7
    -7
      src/engine/physics/kinematics/constraints/spring-constraint.cpp
  89. +6
    -6
      src/engine/physics/kinematics/constraints/spring-constraint.hpp
  90. +3
    -3
      src/engine/physics/kinematics/rigid-body.cpp
  91. +36
    -36
      src/engine/physics/kinematics/rigid-body.hpp
  92. +1
    -1
      src/engine/physics/orbit/elements.hpp
  93. +23
    -23
      src/engine/physics/orbit/frame.hpp
  94. +2
    -2
      src/engine/physics/orbit/state.hpp
  95. +3
    -3
      src/engine/physics/orbit/trajectory.hpp
  96. +1
    -1
      src/engine/render/context.hpp
  97. +19
    -19
      src/engine/render/material-variable-type.hpp
  98. +67
    -66
      src/engine/render/material-variable.hpp
  99. +23
    -23
      src/engine/render/material.cpp
  100. +3
    -3
      src/engine/render/operation.hpp

+ 1
- 0
CMakeLists.txt View File

@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.25)
option(APPLICATION_NAME "Application name" "Antkeeper")
option(APPLICATION_VERSION "Application version string" "0.0.0")
option(APPLICATION_AUTHOR "Application author" "C. J. Howard")

+ 7
- 7
src/engine/ai/steering/agent.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_AI_STEERING_AGENT_HPP
#define ANTKEEPER_AI_STEERING_AGENT_HPP
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
#include <engine/math/quaternion.hpp>
namespace ai {
@ -35,13 +35,13 @@ struct agent
float mass;
/// Cartesian position vector.
float3 position;
math::fvec3 position;
/// Velocity vector.
float3 velocity;
math::fvec3 velocity;
/// Acceleration vector.
float3 acceleration;
math::fvec3 acceleration;
/// Maximum force.
float max_force;
@ -53,13 +53,13 @@ struct agent
float max_speed_squared;
/// Orientation quaternion.
math::quaternion<float> orientation;
math::fquat orientation;
/// Orthonormal basis forward direction vector.
float3 forward;
math::fvec3 forward;
/// Orthonormal basis up direction vector.
float3 up;
math::fvec3 up;
};
} // namespace steering

+ 3
- 3
src/engine/ai/steering/behavior/flee.cpp View File

@ -23,10 +23,10 @@ namespace ai {
namespace steering {
namespace behavior {
float3 flee(const agent& agent, const float3& target)
math::fvec3 flee(const agent& agent, const math::fvec3& target)
{
float3 force = {0, 0, 0};
const float3 difference = target - agent.position;
math::fvec3 force = {0, 0, 0};
const math::fvec3 difference = target - agent.position;
const float sqr_distance = math::dot(difference, difference);
if (sqr_distance)

+ 2
- 2
src/engine/ai/steering/behavior/flee.hpp View File

@ -21,7 +21,7 @@
#define ANTKEEPER_AI_STEERING_BEHAVIOR_FLEE_HPP
#include <engine/ai/steering/agent.hpp>
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
namespace ai {
namespace steering {
@ -34,7 +34,7 @@ namespace behavior {
* @param target Target position.
* @return Flee force.
*/
float3 flee(const agent& agent, const float3& target);
math::fvec3 flee(const agent& agent, const math::fvec3& target);
} // namespace behavior
} // namespace steering

+ 3
- 3
src/engine/ai/steering/behavior/seek.cpp View File

@ -23,10 +23,10 @@ namespace ai {
namespace steering {
namespace behavior {
float3 seek(const agent& agent, const float3& target)
math::fvec3 seek(const agent& agent, const math::fvec3& target)
{
float3 force = {0, 0, 0};
const float3 difference = target - agent.position;
math::fvec3 force = {0, 0, 0};
const math::fvec3 difference = target - agent.position;
const float sqr_distance = math::dot(difference, difference);
if (sqr_distance)

+ 2
- 2
src/engine/ai/steering/behavior/seek.hpp View File

@ -21,7 +21,7 @@
#define ANTKEEPER_AI_STEERING_BEHAVIOR_SEEK_HPP
#include <engine/ai/steering/agent.hpp>
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
namespace ai {
namespace steering {
@ -34,7 +34,7 @@ namespace behavior {
* @param target Target position.
* @return Seek force.
*/
float3 seek(const agent& agent, const float3& target);
[[nodiscard]] math::fvec3 seek(const agent& agent, const math::fvec3& target);
} // namespace behavior
} // namespace steering

+ 7
- 7
src/engine/ai/steering/behavior/wander.cpp View File

@ -26,37 +26,37 @@ namespace ai {
namespace steering {
namespace behavior {
float3 wander_2d(const agent& agent, float noise, float distance, float radius, float& angle)
math::fvec3 wander_2d(const agent& agent, float noise, float distance, float radius, float& angle)
{
// Shift wander angle
angle += math::random(-noise, noise);
// Calculate center of wander circle
const float3 center = agent.position + agent.forward * distance;
const math::fvec3 center = agent.position + agent.forward * distance;
// Decompose orientation into swing and twist rotations
math::quaternion<float> swing, twist;
math::fquat swing, twist;
math::swing_twist(agent.orientation, agent.up, swing, twist);
// Calculate offset to point on wander circle
const float3 offset = math::conjugate(twist) * (math::angle_axis(angle, agent.up) * agent.forward * radius);
const math::fvec3 offset = math::conjugate(twist) * (math::angle_axis(angle, agent.up) * agent.forward * radius);
// Seek toward point on wander circle
return seek(agent, center + offset);
}
float3 wander_3d(const agent& agent, float noise, float distance, float radius, float& theta, float& phi)
math::fvec3 wander_3d(const agent& agent, float noise, float distance, float radius, float& theta, float& phi)
{
// Shift wander angles
theta += math::random(-noise, noise);
phi += math::random(-noise, noise);
// Calculate center of wander sphere
const float3 center = agent.position + agent.forward * distance;
const math::fvec3 center = agent.position + agent.forward * distance;
// Convert spherical coordinates to Cartesian point on wander sphere
const float r_cos_theta = radius * std::cos(theta);
const float3 offset =
const math::fvec3 offset =
{
r_cos_theta * std::cos(phi),
r_cos_theta * std::sin(phi),

+ 3
- 3
src/engine/ai/steering/behavior/wander.hpp View File

@ -21,7 +21,7 @@
#define ANTKEEPER_AI_STEERING_BEHAVIOR_WANDER_HPP
#include <engine/ai/steering/agent.hpp>
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
namespace ai {
namespace steering {
@ -38,7 +38,7 @@ namespace behavior {
*
* @return Wander force.
*/
float3 wander_2d(const agent& agent, float noise, float distance, float radius, float& angle);
math::fvec3 wander_2d(const agent& agent, float noise, float distance, float radius, float& angle);
/**
* Steers an agent in a continuously shifting random direction.
@ -52,7 +52,7 @@ float3 wander_2d(const agent& agent, float noise, float distance, float radius,
*
* @return Wander force.
*/
float3 wander_3d(const agent& agent, float noise, float distance, float radius, float& theta, float& phi);
math::fvec3 wander_3d(const agent& agent, float noise, float distance, float radius, float& theta, float& phi);
} // namespace behavior
} // namespace steering

+ 2
- 2
src/engine/animation/ik/constraints/euler-ik-constraint.cpp View File

@ -21,7 +21,7 @@
#include <algorithm>
#include <cmath>
void euler_ik_constraint::solve(math::quaternion<float>& q)
void euler_ik_constraint::solve(math::fquat& q)
{
// Derive XYZ angles from quaternion
const auto x = std::atan2(2.0f * (q.w() * q.x() + q.y() * q.z()), 1.0f - 2.0f * (q.x() * q.x() + q.y() * q.y()));
@ -42,7 +42,7 @@ void euler_ik_constraint::solve(math::quaternion& q)
const auto sz = std::sin(half_constrained_z);
q = math::normalize
(
math::quaternion<float>
math::fquat
{
cx * cy * cz + sx * sy * sz,
sx * cy * cz - cx * sy * sz,

+ 4
- 4
src/engine/animation/ik/constraints/euler-ik-constraint.hpp View File

@ -29,7 +29,7 @@
class euler_ik_constraint: public ik_constraint
{
public:
void solve(math::quaternion<float>& q) override;
void solve(math::fquat& q) override;
/**
* Sets the angular limits.
@ -37,15 +37,15 @@ public:
* @param min Minimum angles of the x-, y-, and z-axes, in radians.
* @param max Maximum angles of the x-, y-, and z-axes, in radians.
*/
inline void set_limits(const math::vector<float, 3>& min, const math::vector<float, 3>& max) noexcept
inline void set_limits(const math::fvec3& min, const math::fvec3& max) noexcept
{
m_min = min;
m_max = max;
}
private:
math::vector<float, 3> m_min{-math::pi<float>, -math::pi<float>, -math::pi<float>};
math::vector<float, 3> m_max{ math::pi<float>, math::pi<float>, math::pi<float>};
math::fvec3 m_min{-math::pi<float>, -math::pi<float>, -math::pi<float>};
math::fvec3 m_max{ math::pi<float>, math::pi<float>, math::pi<float>};
};
#endif // ANTKEEPER_ANIMATION_EULER_IK_CONSTRAINT_HPP

+ 4
- 4
src/engine/animation/ik/constraints/swing-twist-ik-constraint.cpp View File

@ -28,13 +28,13 @@ void swing_twist_ik_constraint::set_twist_limit(float angle_min, float angle_max
m_sin_half_twist_max = std::sin(angle_max * 0.5f);
}
void swing_twist_ik_constraint::solve(math::quaternion<float>& q)
void swing_twist_ik_constraint::solve(math::fquat& q)
{
constexpr math::vector<float, 3> twist_axis{0.0f, 0.0f, 1.0f};
constexpr math::fvec3 twist_axis{0.0f, 0.0f, 1.0f};
// Decompose rotation into swing and twist components
math::quaternion<float> swing;
math::quaternion<float> twist;
math::fquat swing;
math::fquat twist;
math::swing_twist(q, twist_axis, swing, twist);
// Limit twist

+ 1
- 1
src/engine/animation/ik/constraints/swing-twist-ik-constraint.hpp View File

@ -29,7 +29,7 @@
class swing_twist_ik_constraint: public ik_constraint
{
public:
void solve(math::quaternion<float>& q) override;
void solve(math::fquat& q) override;
/**
* Sets the twist rotation limit.

+ 1
- 1
src/engine/animation/ik/ik-constraint.hpp View File

@ -33,7 +33,7 @@ public:
*
* @param[in,out] q Unit quaternion representing the rotation of a joint.
*/
virtual void solve(math::quaternion<float>& q) = 0;
virtual void solve(math::fquat& q) = 0;
};
#endif // ANTKEEPER_ANIMATION_IK_CONSTRAINT_HPP

+ 6
- 6
src/engine/animation/ik/solvers/ccd-ik-solver.hpp View File

@ -83,13 +83,13 @@ public:
*
* @param position Position of the end effector, relative to the tip bone.
*/
inline void set_effector_position(const math::vector<float, 3>& position) noexcept
inline void set_effector_position(const math::fvec3& position) noexcept
{
m_effector_position = position;
}
/// Returns the position of the end effector, relative to the tip bone.
[[nodiscard]] inline const math::vector<float, 3>& get_effector_position() const
[[nodiscard]] inline const math::fvec3& get_effector_position() const
{
return m_effector_position;
}
@ -104,13 +104,13 @@ public:
*
* @param position IK goal position, in world-space.
*/
inline void set_goal_position(const math::vector<float, 3>& position) noexcept
inline void set_goal_position(const math::fvec3& position) noexcept
{
m_goal_position = position;
}
/// Returns the position of goal, in world-space.
[[nodiscard]] inline const math::vector<float, 3>& get_goal_position() const
[[nodiscard]] inline const math::fvec3& get_goal_position() const
{
return m_goal_position;
}
@ -121,8 +121,8 @@ private:
ik_rig* m_ik_rig{nullptr};
std::size_t m_max_iterations{10};
std::vector<bone_index_type> m_bone_indices;
math::vector<float, 3> m_effector_position{0.0f, 0.0f, 0.0f};
math::vector<float, 3> m_goal_position{0.0f, 0.0f, 0.0f};
math::fvec3 m_effector_position{0.0f, 0.0f, 0.0f};
math::fvec3 m_goal_position{0.0f, 0.0f, 0.0f};
float m_sqr_distance_tolerance{1e-5f};
};

+ 1
- 1
src/engine/animation/screen-transition.cpp View File

@ -23,7 +23,7 @@
screen_transition::screen_transition()
{
progress = std::make_shared<render::material_float>(1, 0.0f);
progress = std::make_shared<render::matvar_float>(1, 0.0f);
// Setup material
material = std::make_shared<render::material>();

+ 1
- 1
src/engine/animation/screen-transition.hpp View File

@ -44,7 +44,7 @@ public:
private:
scene::billboard billboard;
std::shared_ptr<render::material> material;
std::shared_ptr<render::material_float> progress;
std::shared_ptr<render::matvar_float> progress;
::animation<float> animation;
::animation<float>::channel* channel;
std::function<void()> callback;

+ 2
- 2
src/engine/app/sdl/sdl-window-manager.cpp View File

@ -95,8 +95,8 @@ sdl_window_manager::~sdl_window_manager()
std::shared_ptr<window> sdl_window_manager::create_window
(
const std::string& title,
const math::vector<int, 2>& windowed_position,
const math::vector<int, 2>& windowed_size,
const math::ivec2& windowed_position,
const math::ivec2& windowed_size,
bool maximized,
bool fullscreen,
bool v_sync

+ 2
- 2
src/engine/app/sdl/sdl-window-manager.hpp View File

@ -52,8 +52,8 @@ public:
[[nodiscard]] virtual std::shared_ptr<window> create_window
(
const std::string& title,
const math::vector<int, 2>& windowed_position,
const math::vector<int, 2>& windowed_size,
const math::ivec2& windowed_position,
const math::ivec2& windowed_size,
bool maximized,
bool fullscreen,
bool v_sync

+ 6
- 6
src/engine/app/sdl/sdl-window.cpp View File

@ -28,8 +28,8 @@ namespace app {
sdl_window::sdl_window
(
const std::string& title,
const math::vector<int, 2>& windowed_position,
const math::vector<int, 2>& windowed_size,
const math::ivec2& windowed_position,
const math::ivec2& windowed_size,
bool maximized,
bool fullscreen,
bool v_sync
@ -200,23 +200,23 @@ void sdl_window::set_title(const std::string& title)
this->m_title = title;
}
void sdl_window::set_position(const math::vector<int, 2>& position)
void sdl_window::set_position(const math::ivec2& position)
{
SDL_SetWindowPosition(m_internal_window, position.x(), position.y());
}
void sdl_window::set_size(const math::vector<int, 2>& size)
void sdl_window::set_size(const math::ivec2& size)
{
SDL_SetWindowSize(m_internal_window, size.x(), size.y());
}
void sdl_window::set_minimum_size(const math::vector<int, 2>& size)
void sdl_window::set_minimum_size(const math::ivec2& size)
{
SDL_SetWindowMinimumSize(m_internal_window, size.x(), size.y());
this->m_minimum_size = size;
}
void sdl_window::set_maximum_size(const math::vector<int, 2>& size)
void sdl_window::set_maximum_size(const math::ivec2& size)
{
SDL_SetWindowMaximumSize(m_internal_window, size.x(), size.y());
this->m_maximum_size = size;

+ 6
- 6
src/engine/app/sdl/sdl-window.hpp View File

@ -35,8 +35,8 @@ public:
sdl_window
(
const std::string& title,
const math::vector<int, 2>& windowed_position,
const math::vector<int, 2>& windowed_size,
const math::ivec2& windowed_position,
const math::ivec2& windowed_size,
bool maximized,
bool fullscreen,
bool v_sync
@ -49,10 +49,10 @@ public:
virtual ~sdl_window();
virtual void set_title(const std::string& title);
virtual void set_position(const math::vector<int, 2>& position);
virtual void set_size(const math::vector<int, 2>& size);
virtual void set_minimum_size(const math::vector<int, 2>& size);
virtual void set_maximum_size(const math::vector<int, 2>& size);
virtual void set_position(const math::ivec2& position);
virtual void set_size(const math::ivec2& size);
virtual void set_minimum_size(const math::ivec2& size);
virtual void set_maximum_size(const math::ivec2& size);
virtual void set_maximized(bool maximized);
virtual void set_fullscreen(bool fullscreen);
virtual void set_v_sync(bool v_sync);

+ 2
- 2
src/engine/app/window-events.hpp View File

@ -56,7 +56,7 @@ struct window_moved_event
window* window{nullptr};
/// Position of the window, in display units.
math::vector<int, 2> position{0, 0};
math::ivec2 position{0, 0};
};
/**
@ -95,7 +95,7 @@ struct window_resized_event
window* window{nullptr};
/// Window size, in display units.
math::vector<int, 2> size{0, 0};
math::ivec2 size{0, 0};
};
} // namespace app

+ 2
- 2
src/engine/app/window-manager.hpp View File

@ -60,8 +60,8 @@ public:
[[nodiscard]] virtual std::shared_ptr<window> create_window
(
const std::string& title,
const math::vector<int, 2>& windowed_position,
const math::vector<int, 2>& windowed_size,
const math::ivec2& windowed_position,
const math::ivec2& windowed_size,
bool maximized,
bool fullscreen,
bool v_sync

+ 18
- 18
src/engine/app/window.hpp View File

@ -48,28 +48,28 @@ public:
*
* @param position Position of the window, in display units.
*/
virtual void set_position(const math::vector<int, 2>& position) = 0;
virtual void set_position(const math::ivec2& position) = 0;
/**
* Changes the size of the window.
*
* @param size Size of the window, in display units.
*/
virtual void set_size(const math::vector<int, 2>& size) = 0;
virtual void set_size(const math::ivec2& size) = 0;
/**
* Sets the minimum size of the window.
*
* @param size Minimum size of the window, in display units.
*/
virtual void set_minimum_size(const math::vector<int, 2>& size) = 0;
virtual void set_minimum_size(const math::ivec2& size) = 0;
/**
* Sets the maximum size of the window.
*
* @param size Maximum size of the window, in display units.
*/
virtual void set_maximum_size(const math::vector<int, 2>& size) = 0;
virtual void set_maximum_size(const math::ivec2& size) = 0;
/**
* Maximizes or unmaximizes the window.
@ -109,43 +109,43 @@ public:
}
/// Returns the windowed (non-maximized, non-fullscreen) position of the window, in display units.
[[nodiscard]] inline const math::vector<int, 2>& get_windowed_position() const noexcept
[[nodiscard]] inline const math::ivec2& get_windowed_position() const noexcept
{
return m_windowed_position;
}
/// Returns the current position of the window, in display units.
[[nodiscard]] inline const math::vector<int, 2>& get_position() const noexcept
[[nodiscard]] inline const math::ivec2& get_position() const noexcept
{
return m_position;
}
/// Returns the windowed (non-maximized, non-fullscreen) size of the window, in display units.
[[nodiscard]] inline const math::vector<int, 2>& get_windowed_size() const noexcept
[[nodiscard]] inline const math::ivec2& get_windowed_size() const noexcept
{
return m_windowed_size;
}
/// Returns the current size of the window, in display units.
[[nodiscard]] inline const math::vector<int, 2>& get_size() const noexcept
[[nodiscard]] inline const math::ivec2& get_size() const noexcept
{
return m_size;
}
/// Returns the minimum size of the window, in display units.
[[nodiscard]] inline const math::vector<int, 2>& get_minimum_size() const noexcept
[[nodiscard]] inline const math::ivec2& get_minimum_size() const noexcept
{
return m_minimum_size;
}
/// Returns the maximum size of the window, in display units.
[[nodiscard]] inline const math::vector<int, 2>& get_maximum_size() const noexcept
[[nodiscard]] inline const math::ivec2& get_maximum_size() const noexcept
{
return m_minimum_size;
}
/// Returns the current size of the window's drawable viewport, in pixels.
[[nodiscard]] inline const math::vector<int, 2>& get_viewport_size() const noexcept
[[nodiscard]] inline const math::ivec2& get_viewport_size() const noexcept
{
return m_viewport_size;
}
@ -217,13 +217,13 @@ protected:
friend class window_manager;
std::string m_title;
math::vector<int, 2> m_windowed_position{0, 0};
math::vector<int, 2> m_position{0, 0};
math::vector<int, 2> m_windowed_size{0, 0};
math::vector<int, 2> m_size{0, 0};
math::vector<int, 2> m_minimum_size{0, 0};
math::vector<int, 2> m_maximum_size{0, 0};
math::vector<int, 2> m_viewport_size{0, 0};
math::ivec2 m_windowed_position{0, 0};
math::ivec2 m_position{0, 0};
math::ivec2 m_windowed_size{0, 0};
math::ivec2 m_size{0, 0};
math::ivec2 m_minimum_size{0, 0};
math::ivec2 m_maximum_size{0, 0};
math::ivec2 m_viewport_size{0, 0};
bool m_maximized{false};
bool m_fullscreen{false};
bool m_v_sync{false};

+ 6
- 6
src/engine/color/aces.hpp View File

@ -31,7 +31,7 @@ namespace aces {
/// CIE xy chromaticity coordinates of the ACES white point (~D60).
template <class T>
constexpr math::vector2<T> white_point = {T{0.32168}, T{0.33767}};
constexpr math::vec2<T> white_point = {T{0.32168}, T{0.33767}};
/// ACES AP0 color space.
template <class T>
@ -66,10 +66,10 @@ constexpr rgb::color_space ap1
* @return Saturation adjustment matrix.
*/
template <class T>
[[nodiscard]] constexpr math::matrix<T, 3, 3> adjust_saturation(T s, const math::vector3<T>& to_y) noexcept
[[nodiscard]] constexpr math::mat3<T> adjust_saturation(T s, const math::vec3<T>& to_y) noexcept
{
const math::vector3<T> v = to_y * (T{1} - s);
return math::matrix<T, 3, 3>
const math::vec3<T> v = to_y * (T{1} - s);
return math::mat3<T>
{
v[0] + s, v[0], v[0],
v[1], v[1] + s, v[1],
@ -79,11 +79,11 @@ template
/// ACES AP1 RRT saturation adjustment matrix.
template <class T>
constexpr math::matrix<T, 3, 3> ap1_rrt_sat = aces::adjust_saturation(T{0.96}, ap1<T>.to_y);
constexpr math::mat3<T> ap1_rrt_sat = aces::adjust_saturation(T{0.96}, ap1<T>.to_y);
/// ACES AP1 ODT saturation adjustment matrix.
template <class T>
constexpr math::matrix<T, 3, 3> ap1_odt_sat = aces::adjust_saturation(T{0.93}, ap1<T>.to_y);
constexpr math::mat3<T> ap1_odt_sat = aces::adjust_saturation(T{0.93}, ap1<T>.to_y);
} // namespace aces

+ 9
- 9
src/engine/color/cat.hpp View File

@ -35,7 +35,7 @@ namespace cat {
* @see http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
*/
template <class T>
constexpr math::matrix<T, 3, 3> bradford =
constexpr math::mat3<T> bradford =
{
T{ 0.8951}, T{-0.7502}, T{ 0.0389},
T{ 0.2664}, T{ 1.7135}, T{-0.0685},
@ -48,7 +48,7 @@ constexpr math::matrix bradford =
* @see http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
*/
template <class T>
constexpr math::matrix<T, 3, 3> von_kries =
constexpr math::mat3<T> von_kries =
{
T{ 0.40024}, T{-0.22630}, T{0.00000},
T{ 0.70760}, T{ 1.16532}, T{0.00000},
@ -61,7 +61,7 @@ constexpr math::matrix von_kries =
* @see http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
*/
template <class T>
constexpr math::matrix<T, 3, 3> xyz_scaling =
constexpr math::mat3<T> xyz_scaling =
{
T{1}, T{0}, T{0},
T{0}, T{1}, T{0},
@ -81,17 +81,17 @@ constexpr math::matrix xyz_scaling =
* @see http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html
*/
template <class T>
[[nodiscard]] constexpr math::matrix<T, 3, 3> matrix(const math::vector2<T>& w0, const math::vector2<T>& w1, const math::matrix<T, 3, 3>& cone_response = bradford<T>) noexcept
[[nodiscard]] constexpr math::mat3<T> matrix(const math::vec2<T>& w0, const math::vec2<T>& w1, const math::mat3<T>& cone_response = bradford<T>) noexcept
{
// Convert CIE xy chromaticity coordinates to CIE XYZ colors
const math::vector3<T> w0_xyz = {w0[0] / w0[1], T{1}, (T{1} - w0[0] - w0[1]) / w0[1]};
const math::vector3<T> w1_xyz = {w1[0] / w1[1], T{1}, (T{1} - w1[0] - w1[1]) / w1[1]};
const math::vec3<T> w0_xyz = {w0[0] / w0[1], T{1}, (T{1} - w0[0] - w0[1]) / w0[1]};
const math::vec3<T> w1_xyz = {w1[0] / w1[1], T{1}, (T{1} - w1[0] - w1[1]) / w1[1]};
// Calculate cone response of CIE XYZ colors
const math::vector3<T> w0_cone_response = cone_response * w0_xyz;
const math::vector3<T> w1_cone_response = cone_response * w1_xyz;
const math::vec3<T> w0_cone_response = cone_response * w0_xyz;
const math::vec3<T> w1_cone_response = cone_response * w1_xyz;
const math::matrix<T, 3, 3> scale =
const math::mat3<T> scale =
{
w1_cone_response[0] / w0_cone_response[0], T{0}, T{0},
T{0}, w1_cone_response[1] / w0_cone_response[1], T{0},

+ 4
- 4
src/engine/color/cct.hpp View File

@ -38,10 +38,10 @@ namespace cct {
* @see Krystek, M. (1985), An algorithm to calculate correlated colour temperature. Color Res. Appl., 10: 38-40.
*/
template <class T>
[[nodiscard]] math::vector2<T> to_ucs(T t) noexcept
[[nodiscard]] math::vec2<T> to_ucs(T t) noexcept
{
const T tt = t * t;
return math::vector2<T>
return math::vec2<T>
{
(T{0.860117757} + T{1.54118254e-4} * t + T{1.28641212e-7} * tt) / (T{1} + T{8.42420235e-4} * t + T{7.08145163e-7} * tt),
(T{0.317398726} + T{4.22806245e-5} * t + T{4.20481691e-8} * tt) / (T{1} - T{2.89741816e-5} * t + T{1.61456053e-7} * tt)
@ -55,7 +55,7 @@ template
* @return CIE xyY color with `Y = 1`.
*/
template <class T>
math::vector3<T> to_xyy(T t)
math::vec3<T> to_xyy(T t)
{
return ucs::to_xyy(to_ucs(t), T{1});
}
@ -67,7 +67,7 @@ math::vector3 to_xyy(T t)
* @return CIE XYZ color with `Y = 1`.
*/
template <class T>
math::vector3<T> to_xyz(T t)
math::vec3<T> to_xyz(T t)
{
return xyy::to_xyz(to_xyy(t));
}

+ 51
- 51
src/engine/color/illuminant.hpp View File

@ -35,65 +35,65 @@ namespace illuminant {
namespace deg2 {
template <class T>
constexpr math::vector2<T> a = {T{0.44757}, T{0.40745}};
constexpr math::vec2<T> a = {T{0.44757}, T{0.40745}};
template <class T>
constexpr math::vector2<T> b = {T{0.34842}, T{0.35161}};
constexpr math::vec2<T> b = {T{0.34842}, T{0.35161}};
template <class T>
constexpr math::vector2<T> c = {T{0.31006}, T{0.31616}};
constexpr math::vec2<T> c = {T{0.31006}, T{0.31616}};
template <class T>
constexpr math::vector2<T> d50 = {T{0.34567}, T{0.35850}};
constexpr math::vec2<T> d50 = {T{0.34567}, T{0.35850}};
template <class T>
constexpr math::vector2<T> d55 = {T{0.33242}, T{0.34743}};
constexpr math::vec2<T> d55 = {T{0.33242}, T{0.34743}};
template <class T>
constexpr math::vector2<T> d65 = {T{0.31271}, T{0.32902}};
constexpr math::vec2<T> d65 = {T{0.31271}, T{0.32902}};
template <class T>
constexpr math::vector2<T> d75 = {T{0.29902}, T{0.31485}};
constexpr math::vec2<T> d75 = {T{0.29902}, T{0.31485}};
template <class T>
constexpr math::vector2<T> d93 = {T{0.28315}, T{0.29711}};
constexpr math::vec2<T> d93 = {T{0.28315}, T{0.29711}};
template <class T>
constexpr math::vector2<T> e = {T{0.33333}, T{0.33333}};
constexpr math::vec2<T> e = {T{0.33333}, T{0.33333}};
template <class T>
constexpr math::vector2<T> f1 = {T{0.31310}, T{0.33727}};
constexpr math::vec2<T> f1 = {T{0.31310}, T{0.33727}};
template <class T>
constexpr math::vector2<T> f2 = {T{0.37208}, T{0.37529}};
constexpr math::vec2<T> f2 = {T{0.37208}, T{0.37529}};
template <class T>
constexpr math::vector2<T> f3 = {T{0.40910}, T{0.39430}};
constexpr math::vec2<T> f3 = {T{0.40910}, T{0.39430}};
template <class T>
constexpr math::vector2<T> f4 = {T{0.44018}, T{0.40329}};
constexpr math::vec2<T> f4 = {T{0.44018}, T{0.40329}};
template <class T>
constexpr math::vector2<T> f5 = {T{0.31379}, T{0.34531}};
constexpr math::vec2<T> f5 = {T{0.31379}, T{0.34531}};
template <class T>
constexpr math::vector2<T> f6 = {T{0.37790}, T{0.38835}};
constexpr math::vec2<T> f6 = {T{0.37790}, T{0.38835}};
template <class T>
constexpr math::vector2<T> f7 = {T{0.31292}, T{0.32933}};
constexpr math::vec2<T> f7 = {T{0.31292}, T{0.32933}};
template <class T>
constexpr math::vector2<T> f8 = {T{0.34588}, T{0.35875}};
constexpr math::vec2<T> f8 = {T{0.34588}, T{0.35875}};
template <class T>
constexpr math::vector2<T> f9 = {T{0.37417}, T{0.37281}};
constexpr math::vec2<T> f9 = {T{0.37417}, T{0.37281}};
template <class T>
constexpr math::vector2<T> f10 = {T{0.34609}, T{0.35986}};
constexpr math::vec2<T> f10 = {T{0.34609}, T{0.35986}};
template <class T>
constexpr math::vector2<T> f11 = {T{0.38052}, T{0.37713}};
constexpr math::vec2<T> f11 = {T{0.38052}, T{0.37713}};
template <class T>
constexpr math::vector2<T> f12 = {T{0.43695}, T{0.40441}};
constexpr math::vec2<T> f12 = {T{0.43695}, T{0.40441}};
template <class T>
constexpr math::vector2<T> led_b1 = {T{0.4560}, T{0.4078}};
constexpr math::vec2<T> led_b1 = {T{0.4560}, T{0.4078}};
template <class T>
constexpr math::vector2<T> led_b2 = {T{0.4357}, T{0.4012}};
constexpr math::vec2<T> led_b2 = {T{0.4357}, T{0.4012}};
template <class T>
constexpr math::vector2<T> led_b3 = {T{0.3756}, T{0.3723}};
constexpr math::vec2<T> led_b3 = {T{0.3756}, T{0.3723}};
template <class T>
constexpr math::vector2<T> led_b4 = {T{0.3422}, T{0.3502}};
constexpr math::vec2<T> led_b4 = {T{0.3422}, T{0.3502}};
template <class T>
constexpr math::vector2<T> led_b5 = {T{0.3118}, T{0.3236}};
constexpr math::vec2<T> led_b5 = {T{0.3118}, T{0.3236}};
template <class T>
constexpr math::vector2<T> led_bh1 = {T{0.4474}, T{0.4066}};
constexpr math::vec2<T> led_bh1 = {T{0.4474}, T{0.4066}};
template <class T>
constexpr math::vector2<T> led_rgb1 = {T{0.4557}, T{0.4211}};
constexpr math::vec2<T> led_rgb1 = {T{0.4557}, T{0.4211}};
template <class T>
constexpr math::vector2<T> led_v1 = {T{0.4560}, T{0.4548}};
constexpr math::vec2<T> led_v1 = {T{0.4560}, T{0.4548}};
template <class T>
constexpr math::vector2<T> led_v2 = {T{0.3781}, T{0.3775}};
constexpr math::vec2<T> led_v2 = {T{0.3781}, T{0.3775}};
} // deg2
@ -101,47 +101,47 @@ namespace deg2 {
namespace deg10 {
template <class T>
constexpr math::vector2<T> a = {T{0.45117}, T{0.40594}};
constexpr math::vec2<T> a = {T{0.45117}, T{0.40594}};
template <class T>
constexpr math::vector2<T> b = {T{0.34980}, T{0.35270}};
constexpr math::vec2<T> b = {T{0.34980}, T{0.35270}};
template <class T>
constexpr math::vector2<T> c = {T{0.31039}, T{0.31905}};
constexpr math::vec2<T> c = {T{0.31039}, T{0.31905}};
template <class T>
constexpr math::vector2<T> d50 = {T{0.34773}, T{0.35952}};
constexpr math::vec2<T> d50 = {T{0.34773}, T{0.35952}};
template <class T>
constexpr math::vector2<T> d55 = {T{0.33411}, T{0.34877}};
constexpr math::vec2<T> d55 = {T{0.33411}, T{0.34877}};
template <class T>
constexpr math::vector2<T> d65 = {T{0.31382}, T{0.33100}};
constexpr math::vec2<T> d65 = {T{0.31382}, T{0.33100}};
template <class T>
constexpr math::vector2<T> d75 = {T{0.29968}, T{0.31740}};
constexpr math::vec2<T> d75 = {T{0.29968}, T{0.31740}};
template <class T>
constexpr math::vector2<T> d93 = {T{0.28327}, T{0.30043}};
constexpr math::vec2<T> d93 = {T{0.28327}, T{0.30043}};
template <class T>
constexpr math::vector2<T> e = {T{0.33333}, T{0.33333}};
constexpr math::vec2<T> e = {T{0.33333}, T{0.33333}};
template <class T>
constexpr math::vector2<T> f1 = {T{0.31811}, T{0.33559}};
constexpr math::vec2<T> f1 = {T{0.31811}, T{0.33559}};
template <class T>
constexpr math::vector2<T> f2 = {T{0.37925}, T{0.36733}};
constexpr math::vec2<T> f2 = {T{0.37925}, T{0.36733}};
template <class T>
constexpr math::vector2<T> f3 = {T{0.41761}, T{0.38324}};
constexpr math::vec2<T> f3 = {T{0.41761}, T{0.38324}};
template <class T>
constexpr math::vector2<T> f4 = {T{0.44920}, T{0.39074}};
constexpr math::vec2<T> f4 = {T{0.44920}, T{0.39074}};
template <class T>
constexpr math::vector2<T> f5 = {T{0.31975}, T{0.34246}};
constexpr math::vec2<T> f5 = {T{0.31975}, T{0.34246}};
template <class T>
constexpr math::vector2<T> f6 = {T{0.38660}, T{0.37847}};
constexpr math::vec2<T> f6 = {T{0.38660}, T{0.37847}};
template <class T>
constexpr math::vector2<T> f7 = {T{0.31569}, T{0.32960}};
constexpr math::vec2<T> f7 = {T{0.31569}, T{0.32960}};
template <class T>
constexpr math::vector2<T> f8 = {T{0.34902}, T{0.35939}};
constexpr math::vec2<T> f8 = {T{0.34902}, T{0.35939}};
template <class T>
constexpr math::vector2<T> f9 = {T{0.37829}, T{0.37045}};
constexpr math::vec2<T> f9 = {T{0.37829}, T{0.37045}};
template <class T>
constexpr math::vector2<T> f10 = {T{0.35090}, T{0.35444}};
constexpr math::vec2<T> f10 = {T{0.35090}, T{0.35444}};
template <class T>
constexpr math::vector2<T> f11 = {T{0.38541}, T{0.37123}};
constexpr math::vec2<T> f11 = {T{0.38541}, T{0.37123}};
template <class T>
constexpr math::vector2<T> f12 = {T{0.44256}, T{0.39717}};
constexpr math::vec2<T> f12 = {T{0.44256}, T{0.39717}};
} // namespace deg10

+ 15
- 15
src/engine/color/rgb.hpp View File

@ -43,18 +43,18 @@ namespace rgb {
* @see https://mina86.com/2019/srgb-xyz-matrix/
*/
template <class T>
[[nodiscard]] constexpr math::matrix<T, 3, 3> to_xyz(const math::vector2<T>& r, const math::vector2<T>& g, const math::vector2<T>& b, const math::vector2<T>& w)
[[nodiscard]] constexpr math::mat3<T> to_xyz(const math::vec2<T>& r, const math::vec2<T>& g, const math::vec2<T>& b, const math::vec2<T>& w)
{
const math::matrix<T, 3, 3> m =
const math::mat3<T> m =
{
r[0], r[1], T{1} - (r[0] + r[1]),
g[0], g[1], T{1} - (g[0] + g[1]),
b[0], b[1], T{1} - (b[0] + b[1])
};
const math::vector3<T> scale = math::inverse(m) * math::vector3<T>{w[0] / w[1], T{1}, (T{1} - (w[0] + w[1])) / w[1]};
const math::vec3<T> scale = math::inverse(m) * math::vec3<T>{w[0] / w[1], T{1}, (T{1} - (w[0] + w[1])) / w[1]};
return math::matrix<T, 3, 3>
return math::mat3<T>
{
m[0][0] * scale[0], m[0][1] * scale[0], m[0][2] * scale[0],
m[1][0] * scale[1], m[1][1] * scale[1], m[1][2] * scale[1],
@ -69,19 +69,19 @@ template
struct color_space
{
/// Transfer function function pointer type.
typedef math::vector3<T> (*transfer_function_type)(const math::vector3<T>&);
typedef math::vec3<T> (*transfer_function_type)(const math::vec3<T>&);
/// CIE xy chromaticity coordinates of the red primary.
const math::vector2<T> r;
const math::vec2<T> r;
/// CIE xy chromaticity coordinates of the green primary.
const math::vector2<T> g;
const math::vec2<T> g;
/// CIE xy chromaticity coordinates of the blue primary.
const math::vector2<T> b;
const math::vec2<T> b;
/// CIE xy chromaticity coordinates of the white point.
const math::vector2<T> w;
const math::vec2<T> w;
/// Function pointer to the electro-optical transfer function.
const transfer_function_type eotf;
@ -90,13 +90,13 @@ struct color_space
const transfer_function_type oetf;
/// Matrix which transforms an RGB color to a CIE XYZ color.
const math::matrix3x3<T> to_xyz;
const math::mat3<T> to_xyz;
/// Matrix which transforms a CIE XYZ color to an RGB color.
const math::matrix3x3<T> from_xyz;
const math::mat3<T> from_xyz;
/// Vector which gives the luminance of an RGB color via dot product.
const math::vector3<T> to_y;
const math::vec3<T> to_y;
/**
* Constructs an RGB color space.
@ -106,7 +106,7 @@ struct color_space
* @param b CIE xy chromaticity coordinates of the blue primary.
* @param w CIE xy chromaticity coordinates of the white point.
*/
constexpr color_space(const math::vector2<T>& r, const math::vector2<T>& g, const math::vector2<T>& b, const math::vector2<T>& w, transfer_function_type eotf, transfer_function_type oetf):
constexpr color_space(const math::vec2<T>& r, const math::vec2<T>& g, const math::vec2<T>& b, const math::vec2<T>& w, transfer_function_type eotf, transfer_function_type oetf):
r(r),
g(g),
b(b),
@ -124,7 +124,7 @@ struct color_space
* @param x Linear RGB color.
* @return return Luminance of @p x.
*/
[[nodiscard]] inline constexpr T luminance(const math::vector3<T>& x) const noexcept
[[nodiscard]] inline constexpr T luminance(const math::vec3<T>& x) const noexcept
{
return math::dot(x, to_y);
}
@ -140,7 +140,7 @@ struct color_space
* @return Color space transformation matrix.
*/
template <class T>
[[nodiscard]] constexpr math::matrix3x3<T> to_rgb(const color_space<T>& s0, const color_space<T>& s1, const math::matrix3x3<T>& cone_response = color::cat::bradford<T>)
[[nodiscard]] constexpr math::mat3<T> to_rgb(const color_space<T>& s0, const color_space<T>& s1, const math::mat3<T>& cone_response = color::cat::bradford<T>)
{
return s1.from_xyz * color::cat::matrix(s0.w, s1.w, cone_response) * s0.to_xyz;
}

+ 2
- 2
src/engine/color/srgb.hpp View File

@ -37,7 +37,7 @@ namespace color {
* @see IEC 61966-2-1:1999
*/
template <class T>
[[nodiscard]] math::vector3<T> srgb_oetf(const math::vector3<T>& x)
[[nodiscard]] math::vec3<T> srgb_oetf(const math::vec3<T>& x)
{
auto f = [](T x) -> T
{
@ -57,7 +57,7 @@ template
* @see IEC 61966-2-1:1999
*/
template <class T>
[[nodiscard]] math::vector3<T> srgb_eotf(const math::vector3<T>& x)
[[nodiscard]] math::vec3<T> srgb_eotf(const math::vec3<T>& x)
{
auto f = [](T x) -> T
{

+ 2
- 2
src/engine/color/ucs.hpp View File

@ -35,10 +35,10 @@ namespace ucs {
* @return CIE xyY color.
*/
template <class T>
[[nodiscard]] constexpr math::vector3<T> to_xyy(const math::vector2<T>& uv, T y = T{1}) noexcept
[[nodiscard]] constexpr math::vec3<T> to_xyy(const math::vec2<T>& uv, T y = T{1}) noexcept
{
const T d = T{1} / (T{2} * uv[0] - T{8} * uv[1] + T{4});
return math::vector3<T>{(T{3} * uv[0]) * d, (T{2} * uv[1]) * d, y};
return math::vec3<T>{(T{3} * uv[0]) * d, (T{2} * uv[1]) * d, y};
}
} // namespace ucs

+ 5
- 5
src/engine/color/xyy.hpp View File

@ -34,7 +34,7 @@ namespace xyy {
* @return return Luminance of @p x.
*/
template <class T>
[[nodiscard]] inline constexpr T luminance(const math::vector3<T>& x) noexcept
[[nodiscard]] inline constexpr T luminance(const math::vec3<T>& x) noexcept
{
return x[2];
}
@ -46,10 +46,10 @@ template
* @return CIE 1960 UCS color.
*/
template <class T>
[[nodiscard]] constexpr math::vector2<T> to_ucs(const math::vector3<T>& x) noexcept
[[nodiscard]] constexpr math::vec2<T> to_ucs(const math::vec3<T>& x) noexcept
{
const T d = (T{1} / (T{-2} * x[0] + T{12} * x[1] + T{3}));
return math::vector2<T>{(T{4} * x[0]) * d, (T{6} * x[1]) * d};
return math::vec2<T>{(T{4} * x[0]) * d, (T{6} * x[1]) * d};
}
/**
@ -59,9 +59,9 @@ template
* @return CIE XYZ color.
*/
template <class T>
[[nodiscard]] constexpr math::vector3<T> to_xyz(const math::vector3<T>& x) noexcept
[[nodiscard]] constexpr math::vec3<T> to_xyz(const math::vec3<T>& x) noexcept
{
return math::vector3<T>{(x[0] * x[2]) / x[1], x[2], ((T{1} - x[0] - x[1]) * x[2]) / x[1]};
return math::vec3<T>{(x[0] * x[2]) / x[1], x[2], ((T{1} - x[0] - x[1]) * x[2]) / x[1]};
}
} // namespace xyy

+ 5
- 5
src/engine/color/xyz.hpp View File

@ -38,7 +38,7 @@ namespace xyz {
* @return return Luminance of @p x.
*/
template <class T>
[[nodiscard]] inline constexpr T luminance(const math::vector3<T>& x) noexcept
[[nodiscard]] inline constexpr T luminance(const math::vec3<T>& x) noexcept
{
return x[1];
}
@ -50,10 +50,10 @@ template
* @return CIE xyY color.
*/
template <class T>
[[nodiscard]] constexpr math::vector3<T> to_xyy(const math::vector3<T>& x) noexcept
[[nodiscard]] constexpr math::vec3<T> to_xyy(const math::vec3<T>& x) noexcept
{
const T sum = x[0] + x[1] + x[2];
return math::vector3<T>{x[0] / sum, x[1] / sum, x[1]};
return math::vec3<T>{x[0] / sum, x[1] / sum, x[1]};
}
/**
@ -131,9 +131,9 @@ template
* @see Wyman, C., Sloan, P.J., & Shirley, P. (2013). Simple Analytic Approximations to the CIE XYZ Color Matching Functions.
*/
template <class T>
[[nodiscard]] math::vector3<T> match(T lambda)
[[nodiscard]] math::vec3<T> match(T lambda)
{
return math::vector3<T>
return math::vec3<T>
{
match_x<T>(lambda),
match_y<T>(lambda),

+ 395
- 0
src/engine/geom/brep/brep-attribute-map.hpp View File

@ -0,0 +1,395 @@
/*
* Copyright (C) 2023 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_GEOM_BREP_ATTRIBUTE_MAP_HPP
#define ANTKEEPER_GEOM_BREP_ATTRIBUTE_MAP_HPP
#include <engine/geom/brep/brep-attribute.hpp>
#include <engine/utility/hash/fnv1a.hpp>
#include <iterator>
#include <memory>
#include <stdexcept>
#include <type_traits>
#include <unordered_map>
#include <utility>
namespace geom {
/**
* Maps names to B-rep attributes.
*/
class brep_attribute_map
{
public:
template <class Iter, bool Const>
class iterator_template
{
public:
using iterator_type = Iter;
using iterator_category = std::bidirectional_iterator_tag;
using iterator_concept = std::bidirectional_iterator_tag;
using difference_type = std::iter_difference_t<Iter>;
using value_type = brep_attribute_base;
using pointer = std::conditional<Const, const value_type*, value_type*>::type;
using reference = std::conditional<Const, const value_type&, value_type&>::type;
[[nodiscard]] inline constexpr reference operator*() const noexcept
{
return *m_it->second;
}
[[nodiscard]] inline constexpr pointer operator->() const noexcept
{
return &(*m_it->second);
}
[[nodiscard]] inline constexpr reference operator[](difference_type i) const noexcept
{
return *(m_it[i]);
}
inline iterator_template& operator++() noexcept
{
++m_it;
return *this;
}
[[nodiscard]] inline iterator_template operator++(int) noexcept
{
iterator_template tmp = *this;
++(*this);
return tmp;
}
inline iterator_template& operator--() noexcept
{
--m_it;
return *this;
}
[[nodiscard]] inline iterator_template operator--(int) noexcept
{
iterator_template tmp = *this;
--(*this);
return tmp;
}
inline iterator_template& operator+=(difference_type n) noexcept
{
m_it += n;
return *this;
}
inline iterator_template& operator-=(difference_type n) noexcept
{
m_it -= n;
return *this;
}
[[nodiscard]] inline bool operator==(const iterator_template& other) const noexcept
{
return m_it == other.m_it;
};
[[nodiscard]] inline std::weak_ordering operator<=>(const iterator_template& other) const noexcept
{
return m_it <=> other.m_it;
}
[[nodiscard]] inline difference_type operator-(const iterator_template& rhs) const noexcept
{
return m_it - rhs.m_it;
}
[[nodiscard]] inline iterator_template operator+(difference_type n) const noexcept
{
return iterator_template{m_it + n};
}
[[nodiscard]] inline iterator_template operator-(difference_type n) const noexcept
{
return iterator_template{m_it - n};
}
[[nodiscard]] friend iterator_template operator+(difference_type lhs, const iterator_template& rhs) noexcept
{
return iterator_template{lhs + rhs.m_it};
}
[[nodiscard]] friend iterator_template operator-(difference_type lhs, const iterator_template& rhs) noexcept
{
return iterator_template{lhs - rhs.m_it};
}
private:
friend class brep_attribute_map;
iterator_type m_it;
};
using iterator = iterator_template<std::unordered_map<hash::fnv1a32_t, std::unique_ptr<brep_attribute_base>>::iterator, false>;
using const_iterator = iterator_template<std::unordered_map<hash::fnv1a32_t, std::unique_ptr<brep_attribute_base>>::const_iterator, true>;
/// @name Iterators
/// @{
/// Returns an iterator to the first attribute.
/// @{
[[nodiscard]] inline const_iterator begin() const noexcept
{
const_iterator it;
it.m_it = m_attributes.begin();
return it;
}
[[nodiscard]] inline iterator begin() noexcept
{
iterator it;
it.m_it = m_attributes.begin();
return it;
}
[[nodiscard]] inline const_iterator cbegin() const noexcept
{
return begin();
}
/// @}
/// Returns an iterator to the attribute following the last attribute.
/// @{
[[nodiscard]] inline const_iterator end() const noexcept
{
const_iterator it;
it.m_it = m_attributes.end();
return it;
}
[[nodiscard]] inline iterator end() noexcept
{
iterator it;
it.m_it = m_attributes.end();
return it;
}
[[nodiscard]] inline const_iterator cend() const noexcept
{
return end();
}
/// @}
/// @}
/// @name Capacity
/// @{
/// Returns `true` if the container is empty, `false` otherwise.
[[nodiscard]] inline bool empty() const noexcept
{
return m_attributes.empty();
}
/// Returns the number of attributes in the container.
[[nodiscard]] inline std::size_t size() const noexcept
{
return m_attributes.size();
}
/// @}
/// @name Modifiers
/// @{
/**
* Removes all attributes from the container.
*/
inline void clear() noexcept
{
m_attributes.clear();
}
/**
* Constructs a new attribute. If an attribute with the given name exists, it will be replaced.
*
* @tparam T Attribute data type.
*
* @param name Name of the new attribute.
*
* @return Iterator to the new attribute.
*/
template <class T>
iterator emplace(hash::fnv1a32_t name)
{
if (auto i = m_attributes.find(name); i != m_attributes.end())
{
i->second.reset();
i->second = std::make_unique<brep_attribute<T>>(name, m_element_count);
iterator it;
it.m_it = i;
return it;
}
iterator it;
it.m_it = m_attributes.emplace(name, std::make_unique<brep_attribute<T>>(name, m_element_count)).first;
return it;
}
/**
* Removes an attribute from the container.
*
* @param pos Iterator to the attribute to remove.
*
* @return Iterator following the erased attribute.
*/
inline iterator erase(iterator pos)
{
iterator it;
it.m_it = m_attributes.erase(pos.m_it);
return it;
}
/**
* Removes an attribute from the container.
*
* @param name Name of the attribute to remove.
*
* @return Number of attributes removed (0 or 1).
*/
inline std::size_t erase(hash::fnv1a32_t name)
{
return m_attributes.erase(name);
}
/**
* Constructs a new attribute if an attribute with the given name does not exist.
*
* @tparam T Attribute data type.
*
* @param name Name of the new attribute.
*
* @return Pair consisting of an iterator to the new or pre-existing attribute, and a Boolean value that's `true` if the new attribute was constructed, or `false` if an attribute with the given name pre-existed.
*/
template <class T>
std::pair<iterator, bool> try_emplace(hash::fnv1a32_t name)
{
if (auto i = m_attributes.find(name); i != m_attributes.end())
{
iterator it;
it.m_it = i;
return {it, false};
}
auto pair = m_attributes.emplace(name, std::make_unique<brep_attribute<T>>(name, m_element_count));
iterator it;
it.m_it = pair.first;
return {it, pair.second};
}
/// @}
/// @name Lookup
/// @{
/**
* Returns a reference to the attribute with the given name. If no such attribute exists, an exception of type std::out_of_range is thrown.
*
* @tparam T Attribute data type.
*
* @return Reference to the attribute with the given name.
*
* @except std::out_of_range B-rep attribute not found.
*/
/// @{
template <class T>
[[nodiscard]] const brep_attribute<T>& at(hash::fnv1a32_t name) const
{
auto it = find(name);
if (it == end())
{
throw std::out_of_range("B-rep attribute not found");
}
return static_cast<const brep_attribute<T>&>(*it);
}
template <class T>
[[nodiscard]] brep_attribute<T>& at(hash::fnv1a32_t name)
{
auto it = find(name);
if (it == end())
{
throw std::out_of_range("B-rep attribute not found");
}
return static_cast<brep_attribute<T>&>(*it);
}
/// @}
/**
* Finds an attribute with the given name.
*
* @param name Name of an attribute.
*
* @return Iterator to the attribute with the given name. If no such attribute is found, an end iterator is returned.
*/
/// @{
[[nodiscard]] inline const_iterator find(hash::fnv1a32_t name) const
{
const_iterator it;
it.m_it = m_attributes.find(name);
return it;
}
[[nodiscard]] inline iterator find(hash::fnv1a32_t name)
{
iterator it;
it.m_it = m_attributes.find(name);
return it;
}
/// @}
/**
* Checks if there is an attribute with a given name in the container.
*
* @param name Attribute name.
*
* @return `true` if an attribute with the given name was found, `false` otherwise.
*/
[[nodiscard]] inline bool contains(hash::fnv1a32_t name) const
{
return m_attributes.contains(name);
}
/// @}
private:
template <class T>
friend class brep_element_container;
friend class brep_mesh;
brep_attribute_map& operator=(const brep_attribute_map& other)
{
m_element_count = other.m_element_count;
m_attributes.clear();
for (const auto& [key, value]: other.m_attributes)
{
m_attributes.emplace(key, value->clone());
}
return *this;
}
std::size_t m_element_count{};
std::unordered_map<hash::fnv1a32_t, std::unique_ptr<brep_attribute_base>> m_attributes;
};
} // namespace geom
#endif // ANTKEEPER_GEOM_BREP_ATTRIBUTE_MAP_HPP

+ 266
- 0
src/engine/geom/brep/brep-attribute.hpp View File

@ -0,0 +1,266 @@
/*
* Copyright (C) 2023 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_GEOM_BREP_ATTRIBUTE_HPP
#define ANTKEEPER_GEOM_BREP_ATTRIBUTE_HPP
#include <engine/utility/hash/fnv1a.hpp>
#include <memory>
#include <vector>
namespace geom {
/**
* Abstract base class for B-rep element attributes.
*/
class brep_attribute_base
{
public:
/// Returns the name of the attribute.
[[nodiscard]] inline constexpr hash::fnv1a32_t name() const noexcept
{
return m_name;
}
protected:
inline explicit constexpr brep_attribute_base(hash::fnv1a32_t name) noexcept:
m_name(name)
{}
private:
friend class brep_attribute_map;
template <class T>
friend class brep_element_container;
/**
* Erases the attribute value of an element with the given index.
*
* @param i Index of an element.
*/
virtual void erase(std::size_t i) = 0;
/**
* Appends a new attribute value to the end of the container.
*/
virtual void emplace_back() = 0;
/// Returns a copy of this attribute.
[[nodiscard]] virtual std::unique_ptr<brep_attribute_base> clone() const = 0;
hash::fnv1a32_t m_name;
};
/**
* Per-element B-rep data.
*
* @tparam T Data type.
*/
template <class T>
class brep_attribute: public brep_attribute_base
{
public:
using value_type = T;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
using iterator = std::vector<value_type>::iterator;
using const_iterator = std::vector<value_type>::const_iterator;
using reverse_iterator = std::vector<value_type>::reverse_iterator;
using const_reverse_iterator = std::vector<value_type>::const_reverse_iterator;
/**
* Constructs an attribute.
*
* @param name Name of the attribute.
* @param element_count Number of elements.
*/
brep_attribute(hash::fnv1a32_t name, std::size_t element_count):
brep_attribute_base(name),
m_values(element_count)
{}
/// @name Attribute access
/// @{
/**
* Returns a reference to the attribute value of an element.
*
* @param i Index of an element.
*
* @return Reference to the attribute value of the element at index @p i.
*/
/// @{
[[nodiscard]] inline constexpr const_reference operator[](std::size_t i) const
{
return m_values[i];
}
[[nodiscard]] inline constexpr reference operator[](std::size_t i)
{
return m_values[i];
}
/// @}
/// Returns a reference to the attribute value of the first element.
/// @{
[[nodiscard]] inline constexpr const_reference front() const
{
return m_values.front();
}
[[nodiscard]] inline constexpr reference front()
{
return m_values.front();
}
/// @}
/// Returns a reference to the attribute value of the last element.
/// @{
[[nodiscard]] inline constexpr const_reference back() const
{
return m_values.back();
}
[[nodiscard]] inline constexpr reference back()
{
return m_values.back();
}
/// @}
/// Returns a pointer to the underlying array serving as attribute value storage.
/// @{
[[nodiscard]] inline constexpr const value_type* data() const noexcept
{
return m_values.data();
}
[[nodiscard]] inline constexpr value_type* data() noexcept
{
return m_values.data();
}
/// @}
/// @}
/// @name Iterators
/// @{
/// Returns an iterator to the attribute value of the first element.
/// @{
[[nodiscard]] inline constexpr const_iterator begin() const noexcept
{
return m_values.begin();
}
[[nodiscard]] inline constexpr iterator begin() noexcept
{
return m_values.begin();
}
[[nodiscard]] inline constexpr const_iterator cbegin() const noexcept
{
return m_values.begin();
}
/// @}
/// Returns an iterator to the attribute value of the element following the last element.
/// @{
[[nodiscard]] inline constexpr const_iterator end() const noexcept
{
return m_values.end();
}
[[nodiscard]] inline constexpr iterator end() noexcept
{
return m_values.end();
}
[[nodiscard]] inline constexpr const_iterator cend() const noexcept
{
return m_values.end();
}
/// @}
/// Returns a reverse iterator to the attribute value of the first element of the reversed container.
/// @{
[[nodiscard]] inline constexpr const_reverse_iterator rbegin() const noexcept
{
return m_values.rbegin();
}
[[nodiscard]] inline constexpr reverse_iterator rbegin() noexcept
{
return m_values.rbegin();
}
[[nodiscard]] inline constexpr const_reverse_iterator crbegin() const noexcept
{
return m_values.rbegin();
}
/// @}
/// Returns a reverse iterator to the attribute value of the element following the last element of the reversed container.
/// @{
[[nodiscard]] inline constexpr const_reverse_iterator rend() const noexcept
{
return m_values.rend();
}
[[nodiscard]] inline constexpr reverse_iterator rend() noexcept
{
return m_values.rend();
}
[[nodiscard]] inline constexpr const_reverse_iterator crend() const noexcept
{
return m_values.rend();
}
/// @}
/// @}
/// @name Capacity
/// @{
/// Returns `true` if the container is empty, `false` otherwise.
[[nodiscard]] inline constexpr bool empty() const noexcept
{
return m_values.empty();
}
/// Returns the number of attribute values in the container.
[[nodiscard]] inline constexpr std::size_t size() const noexcept
{
return m_values.size();
}
/// @}
private:
void erase(std::size_t i) override
{
m_values[i] = std::move(m_values.back());
m_values.pop_back();
}
void emplace_back() override
{
m_values.emplace_back();
}
[[nodiscard]] std::unique_ptr<brep_attribute_base> clone() const override
{
auto copy = std::make_unique<brep_attribute<T>>(name(), 0);
copy->m_values = m_values;
return std::move(copy);
}
std::vector<value_type> m_values;
};
} // namespace geom
#endif // ANTKEEPER_GEOM_BREP_ATTRIBUTE_HPP

+ 132
- 0
src/engine/geom/brep/brep-edge.cpp View File

@ -0,0 +1,132 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/brep/brep-edge.hpp>
#include <engine/geom/brep/brep-mesh.hpp>
#include <algorithm>
namespace geom {
void brep_edge_loop_list::push_back(brep_loop* loop)
{
if (empty())
{
// List empty, initialize
m_head = loop;
loop->m_edge_next = loop;
loop->m_edge_previous = loop;
}
else
{
// Append loop
loop->m_edge_next = m_head;
loop->m_edge_previous = m_head->m_edge_previous;
m_head->m_edge_previous->m_edge_next = loop;
m_head->m_edge_previous = loop;
}
++m_size;
}
void brep_edge_loop_list::remove(brep_loop* loop)
{
// Directly link next and previous loops
loop->m_edge_next->m_edge_previous = loop->m_edge_previous;
loop->m_edge_previous->m_edge_next = loop->m_edge_next;
// If loop was the list head, update head
if (m_head == loop)
{
m_head = loop->m_edge_next;
}
--m_size;
}
brep_edge* brep_edge_container::emplace_back(brep_vertex* a, brep_vertex* b)
{
if (a == b)
{
return nullptr;
}
brep_edge* ab = brep_element_container<brep_edge>::emplace_back();
ab->m_index = size() - 1;
ab->m_vertices[0] = a;
ab->m_vertices[1] = b;
// Append edge AB to the edge lists of vertices A and B
a->m_edges.push_back(ab);
b->m_edges.push_back(ab);
return ab;
};
void brep_edge_container::erase(brep_edge* edge)
{
// Kill all loops and faces bounded by this edge
while (!edge->loops().empty())
{
m_mesh->faces().erase(edge->loops().back()->face());
}
// Remove this edge from its vertices' lists of edges
edge->vertices().front()->m_edges.remove(edge);
edge->vertices().back()->m_edges.remove(edge);
// Erase edge
brep_element_container<brep_edge>::erase(edge);
}
void brep_edge_container::clear() noexcept
{
while (!empty())
{
erase(back());
}
}
brep_edge* brep_edge_container::find(brep_vertex* a, brep_vertex* b) const
{
if (!a->edges().empty() && !b->edges().empty() && a != b)
{
brep_edge* ea = a->edges().front();
brep_edge* eb = b->edges().front();
const std::size_t n = std::min<std::size_t>(a->edges().size(), b->edges().size());
for (std::size_t i = 0; i < n; ++i)
{
if (ea->vertices()[1] == b || ea->vertices()[0] == b)
{
return ea;
}
if (eb->vertices()[1] == a || eb->vertices()[0] == a)
{
return eb;
}
ea = ea->m_vertex_next[ea->vertices()[1] == a];
eb = eb->m_vertex_next[eb->vertices()[1] == b];
}
}
return nullptr;
}
} // namespace geom

+ 330
- 0
src/engine/geom/brep/brep-edge.hpp View File

@ -0,0 +1,330 @@
/*
* Copyright (C) 2023 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_GEOM_BREP_EDGE_HPP
#define ANTKEEPER_GEOM_BREP_EDGE_HPP
#include <engine/geom/brep/brep-loop.hpp>
#include <engine/geom/brep/brep-element-container.hpp>
#include <array>
#include <cstddef>
#include <iterator>
namespace geom {
class brep_vertex;
class brep_loop;
template <class T>
class brep_element_container;
/**
* List of B-rep loops that share a common edge.
*/
class brep_edge_loop_list
{
public:
friend class brep_mesh;
friend class brep_face_container;
struct const_iterator
{
public:
friend class brep_edge_loop_list;
using iterator_category = std::bidirectional_iterator_tag;
using iterator_concept = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = brep_loop*;
using pointer = const value_type*;
using reference = const value_type&;
[[nodiscard]] inline constexpr value_type operator*() const noexcept
{
return m_loop;
}
[[nodiscard]] inline constexpr value_type operator->() const noexcept
{
return m_loop;
}
inline const_iterator& operator++() noexcept
{
m_loop = m_loop->m_edge_next;
++m_position;
return *this;
}
[[nodiscard]] inline const_iterator operator++(int) noexcept
{
const_iterator tmp = *this;
++(*this);
return tmp;
}
inline const_iterator& operator--() noexcept
{
m_loop = m_loop->m_edge_previous;
--m_position;
return *this;
}
[[nodiscard]] inline const_iterator operator--(int) noexcept
{
const_iterator tmp = *this;
--(*this);
return tmp;
}
[[nodiscard]] inline bool operator==(const const_iterator& other) const noexcept
{
return m_position == other.m_position;
};
[[nodiscard]] inline std::weak_ordering operator<=>(const const_iterator& other) const noexcept
{
return m_position <=> other.m_position;
}
[[nodiscard]] inline difference_type operator-(const const_iterator& rhs) const noexcept
{
return m_position - rhs.m_position;
}
private:
brep_loop* m_loop;
std::ptrdiff_t m_position;
};
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
/// @name Element access
/// @{
/// Returns the first loop.
[[nodiscard]] inline brep_loop* front() const noexcept
{
return m_head;
}
/// Returns the last loop.
[[nodiscard]] inline brep_loop* back() const noexcept
{
return m_head->m_edge_previous;
}
/// @}
/// @name Iterators
/// @{
/// Returns an iterator to the first loop.
/// @{
[[nodiscard]] inline constexpr const_iterator begin() const noexcept
{
const_iterator it;
it.m_loop = m_head;
it.m_position = 0;
return it;
}
[[nodiscard]] inline constexpr const_iterator cbegin() const noexcept
{
return begin();
}
/// @}
/// Returns an iterator to the loop following the last loop.
/// @{
[[nodiscard]] inline constexpr const_iterator end() const noexcept
{
const_iterator it;
it.m_loop = m_head;
it.m_position = static_cast<std::ptrdiff_t>(m_size);
return it;
}
[[nodiscard]] inline constexpr const_iterator cend() const noexcept
{
return end();
}
/// @}
/// Returns a reverse iterator to the first loop of the reversed list.
/// @{
[[nodiscard]] inline constexpr const_reverse_iterator rbegin() const noexcept
{
return std::make_reverse_iterator(end());
}
[[nodiscard]] inline constexpr const_reverse_iterator crbegin() const noexcept
{
return rbegin();
}
/// @}
/// Returns a reverse iterator to the loop following the last loop of the reversed list.
/// @{
[[nodiscard]] inline constexpr const_reverse_iterator rend() const noexcept
{
return std::make_reverse_iterator(begin());
}
[[nodiscard]] inline constexpr const_reverse_iterator crend() const noexcept
{
return rend();
}
/// @}
/// @}
/// @name Capacity
/// @{
/// Returns `true` if the list is empty, `false` otherwise.
[[nodiscard]] inline constexpr bool empty() const noexcept
{
return !m_size;
}
/// Returns the number of loops in the list.
[[nodiscard]] inline constexpr std::size_t size() const noexcept
{
return m_size;
}
/// @}
/// @name Modifiers
/// @{
/**
* Appends a loop to the end of the list.
*
* @param loop Pointer to the loop to append.
*/
void push_back(brep_loop* loop);
/**
* Removes an loop from the list.
*
* @param loop Pointer to the loop to remove.
*/
void remove(brep_loop* loop);
/// @}
private:
brep_loop* m_head{};
std::size_t m_size{};
};
/**
* Curve segment bounded by two vertices.
*/
class brep_edge
{
public:
friend class brep_mesh;
friend class brep_vertex_edge_list;
friend class brep_element_container<brep_edge>;
friend class brep_edge_container;
friend class brep_face_container;
/**
* Returns the index of this edge in the mesh edge array.
*
* @warning This index may change if any edges are removed from the mesh.
*/
[[nodiscard]] inline constexpr std::size_t index() const noexcept
{
return m_index;
}
/// Returns the pair of vertices that bound this edge.
[[nodiscard]] inline constexpr const std::array<brep_vertex*, 2>& vertices() const noexcept
{
return m_vertices;
}
/// Returns the list of loops that share this edge.
[[nodiscard]] inline constexpr const brep_edge_loop_list& loops() const noexcept
{
return m_loops;
}
private:
std::size_t m_index;
std::array<brep_vertex*, 2> m_vertices;
std::array<brep_edge*, 2> m_vertex_next;
std::array<brep_edge*, 2> m_vertex_previous;
brep_edge_loop_list m_loops;
};
/**
* B-rep edge container.
*/
class brep_edge_container: public brep_element_container<brep_edge>
{
public:
/**
* Appends a new edge to the end of the container.
*
* @param a First bounding vertex of the edge.
* @param b Second bounding vertex of the edge.
*
* @return Pointer to the new edge.
*/
brep_edge* emplace_back(brep_vertex* a, brep_vertex* b);
/**
* Erases an edge and all dependent loops and faces.
*
* @param edge Pointer to the edge to erase.
*
* @warning Invalidates iterators and indices of edges, loops, and faces.
*/
void erase(brep_edge* edge) override;
/**
* Erases all edges and their dependent loops and faces.
*/
void clear() noexcept;
/**
* Finds an edge bounded by vertices @p a and @p b (in any order).
*
* @param a First (or second) bounding vertex of the edge.
* @param b Second (or first) bounding vertex of the edge.
*
* @return Pointer to an edge bounded by vertices @p a and @p b, or `nullptr` if no such edge was found.
*/
[[nodiscard]] brep_edge* find(brep_vertex* a, brep_vertex* b) const;
private:
friend class brep_mesh;
/**
* Constructs a B-rep edge container.
*
* @param mesh Pointer to the parent mesh.
*/
inline explicit brep_edge_container(brep_mesh* mesh) noexcept:
brep_element_container<brep_edge>(mesh)
{}
};
} // namespace geom
#endif // ANTKEEPER_GEOM_BREP_EDGE_HPP

+ 329
- 0
src/engine/geom/brep/brep-element-container.hpp View File

@ -0,0 +1,329 @@
/*
* Copyright (C) 2023 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_GEOM_BREP_ELEMENT_CONTAINER_HPP
#define ANTKEEPER_GEOM_BREP_ELEMENT_CONTAINER_HPP
#include <engine/geom/brep/brep-attribute-map.hpp>
#include <engine/utility/hash/fnv1a.hpp>
#include <cstddef>
#include <iterator>
#include <memory>
#include <vector>
namespace geom {
/**
* Container for B-rep elements.
*
* @tparam T Element type.
*/
template <class T>
class brep_element_container
{
public:
friend class brep_mesh;
using element_type = T;
struct const_iterator
{
public:
using iterator_category = std::random_access_iterator_tag;
using iterator_concept = std::random_access_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = element_type*;
using pointer = const value_type*;
using reference = const value_type&;
[[nodiscard]] inline constexpr value_type operator*() const noexcept
{
return m_it->get();
}
[[nodiscard]] inline constexpr value_type operator->() const noexcept
{
return m_it->get();
}
[[nodiscard]] inline constexpr value_type operator[](difference_type i) const noexcept
{
return m_it[i]->get();
}
inline const_iterator& operator++() noexcept
{
++m_it;
return *this;
}
[[nodiscard]] inline const_iterator operator++(int) noexcept
{
const_iterator tmp = *this;
++(*this);
return tmp;
}
inline const_iterator& operator--() noexcept
{
--m_it;
return *this;
}
[[nodiscard]] inline const_iterator operator--(int) noexcept
{
const_iterator tmp = *this;
--(*this);
return tmp;
}
inline const_iterator& operator+=(difference_type n) noexcept
{
m_it += n;
return *this;
}
inline const_iterator& operator-=(difference_type n) noexcept
{
m_it -= n;
return *this;
}
[[nodiscard]] inline bool operator==(const const_iterator& other) const noexcept
{
return m_it == other.m_it;
};
[[nodiscard]] inline std::weak_ordering operator<=>(const const_iterator& other) const noexcept
{
return m_it <=> other.m_it;
}
[[nodiscard]] inline difference_type operator-(const const_iterator& rhs) const noexcept
{
return m_it - rhs.m_it;
}
[[nodiscard]] inline const_iterator operator+(difference_type n) const noexcept
{
return const_iterator{m_it + n};
}
[[nodiscard]] inline const_iterator operator-(difference_type n) const noexcept
{
return const_iterator{m_it - n};
}
[[nodiscard]] friend const_iterator operator+(difference_type lhs, const const_iterator& rhs) noexcept
{
return const_iterator{lhs + rhs.m_it};
}
[[nodiscard]] friend const_iterator operator-(difference_type lhs, const const_iterator& rhs) noexcept
{
return const_iterator{lhs - rhs.m_it};
}
private:
friend class brep_element_container;
std::vector<std::unique_ptr<element_type>>::const_iterator m_it;
};
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
/// @name Element access
/// @{
/**
* Returns a pointer to the element at the specified index.
*
* @param i Index of an element.
*
* @return Pointer to the element at index @p i.
*/
[[nodiscard]] inline constexpr element_type* operator[](std::size_t i) const
{
return m_elements[i].get();
}
/// Returns the first element.
[[nodiscard]] inline constexpr element_type* front() const noexcept
{
return m_elements.front().get();
}
/// Returns the last element.
[[nodiscard]] inline constexpr element_type* back() const noexcept
{
return m_elements.back().get();
}
/// @}
/// @name Iterators
/// @{
/// Returns an iterator to the first element.
/// @{
[[nodiscard]] inline constexpr const_iterator begin() const noexcept
{
const_iterator it;
it.m_it = m_elements.begin();
return it;
}
[[nodiscard]] inline constexpr const_iterator cbegin() const noexcept
{
return begin();
}
/// @}
/// Returns an iterator to the element following the last element.
/// @{
[[nodiscard]] inline constexpr const_iterator end() const noexcept
{
const_iterator it;
it.m_it = m_elements.end();
return it;
}
[[nodiscard]] inline constexpr const_iterator cend() const noexcept
{
return end();
}
/// @}
/// Returns a reverse iterator to the first element of the reversed container.
/// @{
[[nodiscard]] inline constexpr const_reverse_iterator rbegin() const noexcept
{
return std::make_reverse_iterator(end());
}
[[nodiscard]] inline constexpr const_reverse_iterator crbegin() const noexcept
{
return rbegin();
}
/// @}
/// Returns a reverse iterator to the element following the last element of the reversed container.
/// @{
[[nodiscard]] inline constexpr const_reverse_iterator rend() const noexcept
{
return std::make_reverse_iterator(begin());
}
[[nodiscard]] inline constexpr const_reverse_iterator crend() const noexcept
{
return rend();
}
/// @}
/// @}
/// @name Capacity
/// @{
/// Returns `true` if the container is empty, `false` otherwise.
[[nodiscard]] inline constexpr bool empty() const noexcept
{
return m_elements.empty();
}
/// Returns the number of elements in the container.
[[nodiscard]] inline constexpr std::size_t size() const noexcept
{
return m_elements.size();
}
/// @}
/// @name Attributes
/// @{
/// Returns the element attribute map.
/// @{
[[nodiscard]] const brep_attribute_map& attributes() const noexcept
{
return m_attribute_map;
}
[[nodiscard]] brep_attribute_map& attributes() noexcept
{
return m_attribute_map;
}
/// @}
/// @}
protected:
friend class brep_mesh;
/**
* Constructs a B-rep element container.
*
* @param mesh Pointer to the parent mesh.
*/
inline explicit brep_element_container(brep_mesh* mesh) noexcept:
m_mesh(mesh)
{}
/// @name Modifiers
/// @{
/**
* Erases an element from the container.
*
* @param element Pointer to the element to erase.
*/
virtual void erase(element_type* element)
{
const auto index = element->m_index;
for (auto& [key, values]: m_attribute_map.m_attributes)
{
values->erase(index);
}
--m_attribute_map.m_element_count;
m_elements.back()->m_index = index;
m_elements[index] = std::move(m_elements.back());
m_elements.pop_back();
}
/**
* Appends a new element to the end of the container.
*
* @return Pointer to the new element.
*/
virtual element_type* emplace_back()
{
for (auto& [key, values]: m_attribute_map.m_attributes)
{
values->emplace_back();
}
++m_attribute_map.m_element_count;
return m_elements.emplace_back(std::make_unique<element_type>()).get();
}
/// @}
brep_mesh* m_mesh;
private:
std::vector<std::unique_ptr<element_type>> m_elements;
brep_attribute_map m_attribute_map;
};
} // namespace geom
#endif // ANTKEEPER_GEOM_BREP_ELEMENT_CONTAINER_HPP

+ 158
- 0
src/engine/geom/brep/brep-face.cpp View File

@ -0,0 +1,158 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/brep/brep-face.hpp>
#include <engine/geom/brep/brep-mesh.hpp>
#include <algorithm>
#include <vector>
namespace geom {
void brep_face_loop_list::push_back(brep_loop* loop)
{
if (empty())
{
// List empty, initialize
m_head = loop;
loop->m_face_next = loop;
loop->m_face_previous = loop;
}
else
{
// Append loop
loop->m_face_next = m_head;
loop->m_face_previous = m_head->m_face_previous;
m_head->m_face_previous->m_face_next = loop;
m_head->m_face_previous = loop;
}
++m_size;
}
void brep_face_loop_list::insert(brep_loop* next, brep_loop* loop)
{
loop->m_face_next = next;
loop->m_face_previous = next->m_face_previous;
next->m_face_previous->m_face_next = loop;
next->m_face_previous = loop;
++m_size;
}
void brep_face_loop_list::remove(brep_loop* loop)
{
// Directly link next and previous loops
loop->m_face_next->m_face_previous = loop->m_face_previous;
loop->m_face_previous->m_face_next = loop->m_face_next;
// If loop was the list head, update head
if (m_head == loop)
{
m_head = loop->m_face_next;
}
--m_size;
}
brep_face* brep_face_container::emplace_back(const std::span<brep_vertex*> vertices)
{
if (vertices.size() < 3)
{
return nullptr;
}
// Find or make edges
std::vector<brep_edge*> edges(vertices.size());
std::size_t i = vertices.size() - 1;
for (std::size_t j = 0; j < vertices.size(); ++j)
{
edges[i] = m_mesh->edges().find(vertices[i], vertices[j]);
if (!edges[i])
{
edges[i] = m_mesh->edges().emplace_back(vertices[i], vertices[j]);
}
i = j;
}
// Allocate face
brep_face* face = brep_element_container<brep_face>::emplace_back();
face->m_index = size() - 1;
// Make face loops
for (std::size_t i = 0; i < vertices.size(); ++i)
{
brep_loop* loop = m_mesh->loops().emplace_back();
loop->m_vertex = vertices[i];
loop->m_edge = edges[i];
loop->m_face = face;
// Append loop to its edge's list of loops
loop->m_edge->m_loops.push_back(loop);
// Append loop to its face's list of loops
face->m_loops.push_back(loop);
}
return face;
};
void brep_face_container::erase(brep_face* face)
{
brep_loop* loop = face->loops().front();
do
{
// Remove loop from its edge's list of loops
loop->m_edge->m_loops.remove(loop);
brep_loop* next_loop = loop->m_face_next;
// Erase loop
m_mesh->loops().erase(loop);
loop = next_loop;
}
while (loop != face->loops().front());
// Erase face
brep_element_container<brep_face>::erase(face);
}
void brep_face_container::clear() noexcept
{
while (!empty())
{
erase(back());
}
}
void brep_face_container::reverse(brep_face* face)
{
for (brep_loop* loop: face->loops())
{
// Swap order of loop vertices
loop->m_vertex = loop->edge()->vertices()[loop->edge()->vertices()[0] == loop->vertex()];
// Swap pointers to next and previous face loops
std::swap(loop->m_face_next, loop->m_face_previous);
}
}
} // namespace geom

+ 322
- 0
src/engine/geom/brep/brep-face.hpp View File

@ -0,0 +1,322 @@
/*
* Copyright (C) 2023 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_GEOM_BREP_FACE_HPP
#define ANTKEEPER_GEOM_BREP_FACE_HPP
#include <engine/geom/brep/brep-loop.hpp>
#include <engine/geom/brep/brep-element-container.hpp>
#include <cstddef>
#include <iterator>
#include <span>
namespace geom {
class brep_vertex;
class brep_loop;
template <class T>
class brep_element_container;
/**
* List of B-rep loops that bound a common face.
*/
class brep_face_loop_list
{
public:
friend class brep_mesh;
struct const_iterator
{
public:
friend class brep_face_loop_list;
using iterator_category = std::bidirectional_iterator_tag;
using iterator_concept = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = brep_loop*;
using pointer = const value_type*;
using reference = const value_type&;
[[nodiscard]] inline constexpr value_type operator*() const noexcept
{
return m_loop;
}
[[nodiscard]] inline constexpr value_type operator->() const noexcept
{
return m_loop;
}
inline const_iterator& operator++() noexcept
{
m_loop = m_loop->m_face_next;
++m_position;
return *this;
}
[[nodiscard]] inline const_iterator operator++(int) noexcept
{
const_iterator tmp = *this;
++(*this);
return tmp;
}
inline const_iterator& operator--() noexcept
{
m_loop = m_loop->m_face_previous;
--m_position;
return *this;
}
[[nodiscard]] inline const_iterator operator--(int) noexcept
{
const_iterator tmp = *this;
--(*this);
return tmp;
}
[[nodiscard]] inline bool operator==(const const_iterator& other) const noexcept
{
return m_position == other.m_position;
};
[[nodiscard]] inline std::weak_ordering operator<=>(const const_iterator& other) const noexcept
{
return m_position <=> other.m_position;
}
[[nodiscard]] inline difference_type operator-(const const_iterator& rhs) const noexcept
{
return m_position - rhs.m_position;
}
private:
brep_loop* m_loop;
std::ptrdiff_t m_position;
};
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
/// @name Element access
/// @{
/// Returns the first loop.
[[nodiscard]] inline brep_loop* front() const noexcept
{
return m_head;
}
/// Returns the last loop.
[[nodiscard]] inline brep_loop* back() const noexcept
{
return m_head->m_face_previous;
}
/// @}
/// @name Iterators
/// @{
/// Returns an iterator to the first loop.
/// @{
[[nodiscard]] inline constexpr const_iterator begin() const noexcept
{
const_iterator it;
it.m_loop = m_head;
it.m_position = 0;
return it;
}
[[nodiscard]] inline constexpr const_iterator cbegin() const noexcept
{
return begin();
}
/// @}
/// Returns an iterator to the loop following the last loop.
/// @{
[[nodiscard]] inline constexpr const_iterator end() const noexcept
{
const_iterator it;
it.m_loop = m_head;
it.m_position = static_cast<std::ptrdiff_t>(m_size);
return it;
}
[[nodiscard]] inline constexpr const_iterator cend() const noexcept
{
return end();
}
/// @}
/// Returns a reverse iterator to the first loop of the reversed list.
/// @{
[[nodiscard]] inline constexpr const_reverse_iterator rbegin() const noexcept
{
return std::make_reverse_iterator(end());
}
[[nodiscard]] inline constexpr const_reverse_iterator crbegin() const noexcept
{
return rbegin();
}
/// @}
/// Returns a reverse iterator to the loop following the last loop of the reversed list.
/// @{
[[nodiscard]] inline constexpr const_reverse_iterator rend() const noexcept
{
return std::make_reverse_iterator(begin());
}
[[nodiscard]] inline constexpr const_reverse_iterator crend() const noexcept
{
return rend();
}
/// @}
/// @}
/// @name Capacity
/// @{
/// Returns `true` if the list is empty, `false` otherwise.
[[nodiscard]] inline constexpr bool empty() const noexcept
{
return !m_size;
}
/// Returns the number of loops in the list.
[[nodiscard]] inline constexpr std::size_t size() const noexcept
{
return m_size;
}
/// @}
/// @name Modifiers
/// @{
/**
* Appends a loop to the end of the list.
*
* @param loop Pointer to the loop to append.
*/
void push_back(brep_loop* loop);
/**
* Inserts a loop before a given loop.
*
* @param next Loop before which this loop should be inserted.
* @param loop Pointer to the loop to insert.
*/
void insert(brep_loop* next, brep_loop* loop);
/**
* Removes an loop from the list.
*
* @param loop Pointer to the loop to remove.
*/
void remove(brep_loop* loop);
/// @}
private:
brep_loop* m_head{};
std::size_t m_size{};
};
/**
* Portion of a shell bounded by loops.
*/
class brep_face
{
public:
friend class brep_mesh;
friend class brep_element_container<brep_face>;
friend class brep_face_container;
/**
* Returns the index of this face in the mesh face array.
*
* @warning This index may change if any faces are removed from the mesh.
*/
[[nodiscard]] inline constexpr std::size_t index() const noexcept
{
return m_index;
}
/// Returns the list of loops associated with this face.
[[nodiscard]] inline constexpr const brep_face_loop_list& loops() const noexcept
{
return m_loops;
}
private:
std::size_t m_index;
brep_face_loop_list m_loops;
};
/**
* B-rep face container.
*/
class brep_face_container: public brep_element_container<brep_face>
{
public:
/**
* Appends a new face to the end of the container.
*
* @param vertices Ordered vertices of the face.
*
* @return Pointer to the new face.
*/
brep_face* emplace_back(const std::span<brep_vertex*> vertices);
/**
* Erases a face and all of its loops.
*
* @param face Pointer to the face to erase.
*
* @warning Invalidates iterators and indices of loops and faces.
*/
void erase(brep_face* face) override;
/**
* Erases all faces and their loops.
*/
void clear() noexcept;
/**
* Reverses the direction of a face's bounding loops.
*
* @param face Face bounded by the loops to reverse.
*/
void reverse(brep_face* face);
private:
friend class brep_mesh;
/**
* Constructs a B-rep face container.
*
* @param mesh Pointer to the parent mesh.
*/
inline explicit brep_face_container(brep_mesh* mesh) noexcept:
brep_element_container<brep_face>(mesh)
{}
};
} // namespace geom
#endif // ANTKEEPER_GEOM_BREP_FACE_HPP

+ 32
- 0
src/engine/geom/brep/brep-loop.cpp View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/brep/brep-loop.hpp>
namespace geom {
brep_loop* brep_loop_container::emplace_back()
{
brep_loop* loop = brep_element_container<brep_loop>::emplace_back();
loop->m_index = size() - 1;
return loop;
};
} // namespace geom

+ 114
- 0
src/engine/geom/brep/brep-loop.hpp View File

@ -0,0 +1,114 @@
/*
* Copyright (C) 2023 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_GEOM_BREP_LOOP_HPP
#define ANTKEEPER_GEOM_BREP_LOOP_HPP
#include <engine/geom/brep/brep-element-container.hpp>
#include <cstddef>
namespace geom {
class brep_vertex;
class brep_edge;
class brep_face;
template <class T>
class brep_element_container;
/**
* Connected boundary of a single face.
*/
class brep_loop
{
public:
friend class brep_mesh;
friend class brep_edge_loop_list;
friend class brep_face_loop_list;
friend class brep_element_container<brep_loop>;
friend class brep_loop_container;
friend class brep_face_container;
/**
* Returns the index of this loop in the mesh loop array.
*
* @warning This index may change if any loops are removed from the mesh.
*/
[[nodiscard]] inline constexpr std::size_t index() const noexcept
{
return m_index;
}
/// Returns a pointer to the loop vertex.
[[nodiscard]] inline constexpr brep_vertex* vertex() const noexcept
{
return m_vertex;
}
/// Returns a pointer to the loop edge.
[[nodiscard]] inline constexpr brep_edge* edge() const noexcept
{
return m_edge;
}
/// Returns a pointer to the loop face.
[[nodiscard]] inline constexpr brep_face* face() const noexcept
{
return m_face;
}
private:
std::size_t m_index;
brep_vertex* m_vertex;
brep_edge* m_edge;
brep_face* m_face;
brep_loop* m_edge_next;
brep_loop* m_edge_previous;
brep_loop* m_face_next;
brep_loop* m_face_previous;
};
/**
* B-rep loop container.
*/
class brep_loop_container: public brep_element_container<brep_loop>
{
private:
friend class brep_mesh;
friend class brep_face_container;
/**
* Constructs a B-rep face container.
*
* @param mesh Pointer to the parent mesh.
*/
inline explicit brep_loop_container(brep_mesh* mesh) noexcept:
brep_element_container<brep_loop>(mesh)
{}
/**
* Appends a new loop to the end of the container.
*
* @return Pointer to the new loop.
*/
brep_loop* emplace_back() override;
};
} // namespace geom
#endif // ANTKEEPER_GEOM_BREP_LOOP_HPP

+ 182
- 0
src/engine/geom/brep/brep-mesh.cpp View File

@ -0,0 +1,182 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/brep/brep-mesh.hpp>
#include <engine/math/vector.hpp>
#include <engine/resources/resource-loader.hpp>
#include <engine/resources/deserialize-error.hpp>
#include <engine/resources/deserializer.hpp>
#include <array>
namespace geom {
brep_mesh::brep_mesh() noexcept:
m_vertices(this),
m_edges(this),
m_loops(this),
m_faces(this)
{}
brep_mesh::brep_mesh(const brep_mesh& other):
brep_mesh()
{
*this = other;
}
brep_mesh& brep_mesh::operator=(const brep_mesh& other)
{
// Allocate containers
m_vertices.m_elements.resize(other.m_vertices.m_elements.size());
m_edges.m_elements.resize(other.m_edges.m_elements.size());
m_loops.m_elements.resize(other.m_loops.m_elements.size());
m_faces.m_elements.resize(other.m_faces.m_elements.size());
// Copy-construct elements
for (std::size_t i = 0; i < m_vertices.m_elements.size(); ++i)
{
m_vertices.m_elements[i] = std::make_unique<brep_vertex>(*other.m_vertices.m_elements[i]);
}
for (std::size_t i = 0; i < m_edges.m_elements.size(); ++i)
{
m_edges.m_elements[i] = std::make_unique<brep_edge>(*other.m_edges.m_elements[i]);
}
for (std::size_t i = 0; i < m_loops.m_elements.size(); ++i)
{
m_loops.m_elements[i] = std::make_unique<brep_loop>(*other.m_loops.m_elements[i]);
}
for (std::size_t i = 0; i < m_faces.m_elements.size(); ++i)
{
m_faces.m_elements[i] = std::make_unique<brep_face>(*other.m_faces.m_elements[i]);
}
// Copy per-element attributes
m_vertices.m_attribute_map = other.m_vertices.m_attribute_map;
m_edges.m_attribute_map = other.m_edges.m_attribute_map;
m_loops.m_attribute_map = other.m_loops.m_attribute_map;
m_faces.m_attribute_map = other.m_faces.m_attribute_map;
// Reassign element pointers
for (const auto& vertex: m_vertices.m_elements)
{
if (!vertex->edges().empty())
{
vertex->m_edges.m_head = m_edges.m_elements[vertex->m_edges.m_head->m_index].get();
}
}
for (const auto& edge: m_edges.m_elements)
{
edge->m_vertices[0] = m_vertices.m_elements[edge->m_vertices[0]->m_index].get();
edge->m_vertices[1] = m_vertices.m_elements[edge->m_vertices[1]->m_index].get();
edge->m_vertex_next[0] = m_edges.m_elements[edge->m_vertex_next[0]->m_index].get();
edge->m_vertex_next[1] = m_edges.m_elements[edge->m_vertex_next[1]->m_index].get();
edge->m_vertex_previous[0] = m_edges.m_elements[edge->m_vertex_previous[0]->m_index].get();
edge->m_vertex_previous[1] = m_edges.m_elements[edge->m_vertex_previous[1]->m_index].get();
if (!edge->loops().empty())
{
edge->m_loops.m_head = m_loops.m_elements[edge->m_loops.m_head->m_index].get();
}
}
for (const auto& loop: m_loops.m_elements)
{
loop->m_vertex = m_vertices.m_elements[loop->m_vertex->m_index].get();
loop->m_edge = m_edges.m_elements[loop->m_edge->m_index].get();
loop->m_face = m_faces.m_elements[loop->m_face->m_index].get();
loop->m_edge_next = m_loops.m_elements[loop->m_edge_next->m_index].get();
loop->m_edge_previous = m_loops.m_elements[loop->m_edge_previous->m_index].get();
loop->m_face_next = m_loops.m_elements[loop->m_face_next->m_index].get();
loop->m_face_previous = m_loops.m_elements[loop->m_face_previous->m_index].get();
}
for (const auto& face: m_faces.m_elements)
{
face->m_loops.m_head = m_loops.m_elements[face->m_loops.m_head->m_index].get();
}
return *this;
}
void brep_mesh::clear() noexcept
{
m_vertices.clear();
}
} // namespace geom
/**
* Deserializes a mesh.
*
* @param[out] mesh Mesh to deserialize.
* @param[in,out] ctx Deserialize context.
*
* @throw deserialize_error Read error.
*/
template <>
void deserializer<geom::brep_mesh>::deserialize(geom::brep_mesh& mesh, deserialize_context& ctx)
{
// Read vertex, edge, and face counts
std::uint32_t vertex_count = 0;
std::uint32_t edge_count = 0;
std::uint32_t face_count = 0;
ctx.read32<std::endian::little>(reinterpret_cast<std::byte*>(&vertex_count), 1);
ctx.read32<std::endian::little>(reinterpret_cast<std::byte*>(&edge_count), 1);
ctx.read32<std::endian::little>(reinterpret_cast<std::byte*>(&face_count), 1);
// Make vertices
for (std::size_t i = 0; i < vertex_count; ++i)
{
mesh.vertices().emplace_back();
}
// Read edge vertex indices into buffer
std::vector<std::array<std::uint32_t, 2>> edges(edge_count);
ctx.read32<std::endian::little>(reinterpret_cast<std::byte*>(edges.data()), edge_count * 2);
// Make edges
for (const auto& e: edges)
{
mesh.edges().emplace_back(mesh.vertices()[e[0]], mesh.vertices()[e[1]]);
}
edges.clear();
// Read face vertex indices into buffer
std::vector<std::array<std::uint32_t, 3>> faces(face_count);
ctx.read32<std::endian::little>(reinterpret_cast<std::byte*>(faces.data()), face_count * 3);
// Make faces
for (const auto& f: faces)
{
geom::brep_vertex* vertices[3] = {mesh.vertices()[f[0]], mesh.vertices()[f[1]], mesh.vertices()[f[2]]};
mesh.faces().emplace_back(vertices);
}
faces.clear();
// Make vertex attributes
auto& vertex_positions = static_cast<geom::brep_attribute<math::fvec3>&>(*mesh.vertices().attributes().emplace<math::fvec3>("position"));
// Read vertex attributes
ctx.read32<std::endian::little>(reinterpret_cast<std::byte*>(vertex_positions.data()), vertex_count * 3);
}
template <>
std::unique_ptr<geom::brep_mesh> resource_loader<geom::brep_mesh>::load(::resource_manager& resource_manager, deserialize_context& ctx)
{
auto resource = std::make_unique<geom::brep_mesh>();
deserializer<geom::brep_mesh>().deserialize(*resource, ctx);
return resource;
}

+ 126
- 0
src/engine/geom/brep/brep-mesh.hpp View File

@ -0,0 +1,126 @@
/*
* Copyright (C) 2023 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_GEOM_BREP_MESH_HPP
#define ANTKEEPER_GEOM_BREP_MESH_HPP
#include <engine/geom/brep/brep-vertex.hpp>
#include <engine/geom/brep/brep-edge.hpp>
#include <engine/geom/brep/brep-loop.hpp>
#include <engine/geom/brep/brep-face.hpp>
namespace geom {
/**
* Boundary representation (B-rep) of a mesh.
*/
class brep_mesh
{
public:
/**
* Constructs an empty mesh.
*/
brep_mesh() noexcept;
/**
* Constructs a copy of another mesh.
*
* @param other Mesh to copy.
*/
brep_mesh(const brep_mesh& other);
/**
* Copies another mesh into this mesh.
*
* @param other Mesh to copy.
*
* @return Reference to this mesh.
*/
brep_mesh& operator=(const brep_mesh& other);
/// @name Modifiers
/// @{
/// Erases all vertices, edges, loops, and faces.
void clear() noexcept;
/// @}
/// @name Element access
/// @{
/// Returns the mesh vertices.
/// @{
[[nodiscard]] inline const brep_vertex_container& vertices() const noexcept
{
return m_vertices;
}
[[nodiscard]] inline brep_vertex_container& vertices() noexcept
{
return m_vertices;
}
///@}
/// Returns the mesh edges.
/// @{
[[nodiscard]] inline const brep_edge_container& edges() const noexcept
{
return m_edges;
}
[[nodiscard]] inline brep_edge_container& edges() noexcept
{
return m_edges;
}
/// @}
/// Returns the mesh loops.
/// @{
[[nodiscard]] inline const brep_loop_container& loops() const noexcept
{
return m_loops;
}
[[nodiscard]] inline brep_loop_container& loops() noexcept
{
return m_loops;
}
/// @}
/// Returns the mesh faces.
/// @{
[[nodiscard]] inline const brep_face_container& faces() const noexcept
{
return m_faces;
}
[[nodiscard]] inline brep_face_container& faces() noexcept
{
return m_faces;
}
/// @}
/// @}
private:
brep_vertex_container m_vertices;
brep_edge_container m_edges;
brep_loop_container m_loops;
brep_face_container m_faces;
};
} // namespace geom
#endif // ANTKEEPER_GEOM_BREP_MESH_HPP

+ 106
- 0
src/engine/geom/brep/brep-operations.cpp View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/brep/brep-operations.hpp>
#include <engine/math/vector.hpp>
#include <algorithm>
namespace geom {
void generate_face_normals(brep_mesh& mesh)
{
const auto& vertex_positions = mesh.vertices().attributes().at<math::fvec3>("position");
auto& face_normals = static_cast<brep_attribute<math::fvec3>&>(*mesh.faces().attributes().try_emplace<math::fvec3>("normal").first);
for (brep_face* face: mesh.faces())
{
auto loop = face->loops().begin();
const auto& a = vertex_positions[loop->vertex()->index()];
const auto& b = vertex_positions[(++loop)->vertex()->index()];
const auto& c = vertex_positions[(++loop)->vertex()->index()];
face_normals[face->index()] = math::normalize(math::cross(b - a, c - a));
}
}
void generate_vertex_normals(brep_mesh& mesh)
{
const auto& vertex_positions = mesh.vertices().attributes().at<math::fvec3>("position");
auto& vertex_normals = static_cast<brep_attribute<math::fvec3>&>(*mesh.vertices().attributes().try_emplace<math::fvec3>("normal").first);
// Init vertex normals to zero
std::fill(vertex_normals.begin(), vertex_normals.end(), math::fvec3::zero());
if (auto face_normals_it = mesh.faces().attributes().find("normals"); face_normals_it != mesh.faces().attributes().end())
{
const auto& face_normals = static_cast<const brep_attribute<math::fvec3>&>(*face_normals_it);
for (brep_face* face: mesh.faces())
{
// Get face normal from face normal attribute
const auto& face_normal = face_normals[face->index()];
// Accumulate vertex normals
for (brep_loop* loop: face->loops())
{
vertex_normals[loop->vertex()->index()] += face_normal;
}
}
}
else
{
for (brep_face* face: mesh.faces())
{
// Calculate face normal
auto loop = face->loops().begin();
const auto& a = vertex_positions[loop->vertex()->index()];
const auto& b = vertex_positions[(++loop)->vertex()->index()];
const auto& c = vertex_positions[(++loop)->vertex()->index()];
const auto face_normal = math::normalize(math::cross(b - a, c - a));
// Accumulate vertex normals
for (brep_loop* loop: face->loops())
{
vertex_normals[loop->vertex()->index()] += face_normal;
}
}
}
// Normalize vertex normals
for (auto& vertex_normal: vertex_normals)
{
vertex_normal = math::normalize(vertex_normal);
}
}
void generate_loop_barycentric(brep_mesh& mesh)
{
const auto& vertex_positions = mesh.vertices().attributes().at<math::fvec3>("position");
auto& loop_barycentric = static_cast<brep_attribute<math::fvec3>&>(*mesh.loops().attributes().try_emplace<math::fvec3>("barycentric").first);
for (brep_face* face: mesh.faces())
{
auto loop = face->loops().begin();
loop_barycentric[loop->index()] = {1.0f, 0.0f, 0.0f};
loop_barycentric[(++loop)->index()] = {0.0f, 1.0f, 0.0f};
loop_barycentric[(++loop)->index()] = {0.0f, 0.0f, 1.0f};
}
}
} // namespace geom

+ 54
- 0
src/engine/geom/brep/brep-operations.hpp View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2023 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_GEOM_BREP_OPERATIONS_HPP
#define ANTKEEPER_GEOM_BREP_OPERATIONS_HPP
#include <engine/geom/brep/brep-mesh.hpp>
namespace geom {
/**
* Generates the math::fvec3 face attribute "normal" for a B-rep mesh.
*
* @param mesh Mesh for which to generate normals.
*
* @warning Requires the math::fvec3 vertex attribute "position".
*/
void generate_face_normals(brep_mesh& mesh);
/**
* Generates the math::fvec3 vertex attribute "normal" for a B-rep mesh.
*
* @param mesh Mesh for which to generate normals.
*
* @warning Requires the math::fvec3 vertex attribute "position".
*/
void generate_vertex_normals(brep_mesh& mesh);
/**
* Generates the math::fvec3 loop attribute "barycentric" for a B-rep mesh.
*
* @param mesh Mesh for which to generate barycentric coordinates.
*/
void generate_loop_barycentric(brep_mesh& mesh);
} // namespace geom
#endif // ANTKEEPER_GEOM_BREP_OPERATIONS_HPP

+ 102
- 0
src/engine/geom/brep/brep-vertex.cpp View File

@ -0,0 +1,102 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/brep/brep-vertex.hpp>
#include <engine/geom/brep/brep-mesh.hpp>
namespace geom {
void brep_vertex_edge_list::push_back(brep_edge* edge)
{
// Determine index of vertex in new edge vertex array
const std::size_t i = (edge->m_vertices[1] == m_vertex);
if (empty())
{
// List empty, initialize
m_head = edge;
edge->m_vertex_next[i] = edge;
edge->m_vertex_previous[i] = edge;
}
else
{
// Determine index of vertex in head edge vertex array
const std::size_t j = (m_head->m_vertices[1] == m_vertex);
// Append edge
edge->m_vertex_next[i] = m_head;
edge->m_vertex_previous[i] = m_head->m_vertex_previous[j];
edge->m_vertex_previous[i]->m_vertex_next[edge->m_vertex_previous[i]->m_vertices[1] == m_vertex] = edge;
m_head->m_vertex_previous[j] = edge;
}
++m_size;
}
void brep_vertex_edge_list::remove(brep_edge* edge)
{
// Determine index of vertex in edge vertex array
const std::size_t i = (edge->m_vertices[1] == m_vertex);
// Get pointers to the next and previous edges
brep_edge* next = edge->m_vertex_next[i];
brep_edge* previous = edge->m_vertex_previous[i];
// Directly link next and previous edges
next->m_vertex_previous[next->m_vertices[1] == m_vertex] = previous;
previous->m_vertex_next[previous->m_vertices[1] == m_vertex] = next;
// If edge was the list head, update head
if (m_head == edge)
{
m_head = next;
}
--m_size;
}
brep_vertex* brep_vertex_container::emplace_back()
{
brep_vertex* vertex = brep_element_container<brep_vertex>::emplace_back();
vertex->m_index = size() - 1;
vertex->m_edges.m_vertex = vertex;
return vertex;
};
void brep_vertex_container::erase(brep_vertex* vertex)
{
// Erase all edges bounded by this vertex
while (!vertex->edges().empty())
{
m_mesh->edges().erase(vertex->edges().back());
}
// Erase vertex
brep_element_container<brep_vertex>::erase(vertex);
}
void brep_vertex_container::clear() noexcept
{
while (!empty())
{
erase(back());
}
}
} // namespace geom

+ 312
- 0
src/engine/geom/brep/brep-vertex.hpp View File

@ -0,0 +1,312 @@
/*
* Copyright (C) 2023 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_GEOM_BREP_VERTEX_HPP
#define ANTKEEPER_GEOM_BREP_VERTEX_HPP
#include <engine/geom/brep/brep-edge.hpp>
#include <engine/geom/brep/brep-element-container.hpp>
#include <cstddef>
#include <iterator>
namespace geom {
class brep_mesh;
class brep_edge;
class brep_vertex;
template <class T>
class brep_element_container;
/**
* List of B-rep edges bounded by a common vertex.
*/
class brep_vertex_edge_list
{
public:
friend class brep_mesh;
friend class brep_vertex_container;
friend class brep_edge_container;
struct const_iterator
{
public:
friend class brep_vertex_edge_list;
using iterator_category = std::bidirectional_iterator_tag;
using iterator_concept = std::bidirectional_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = brep_edge*;
using pointer = const value_type*;
using reference = const value_type&;
[[nodiscard]] inline constexpr value_type operator*() const noexcept
{
return m_edge;
}
[[nodiscard]] inline constexpr value_type operator->() const noexcept
{
return m_edge;
}
inline const_iterator& operator++() noexcept
{
m_edge = m_edge->m_vertex_next[m_edge->vertices()[1] == m_vertex];
++m_position;
return *this;
}
[[nodiscard]] inline const_iterator operator++(int) noexcept
{
const_iterator tmp = *this;
++(*this);
return tmp;
}
inline const_iterator& operator--() noexcept
{
m_edge = m_edge->m_vertex_previous[m_edge->vertices()[1] == m_vertex];
--m_position;
return *this;
}
[[nodiscard]] inline const_iterator operator--(int) noexcept
{
const_iterator tmp = *this;
--(*this);
return tmp;
}
[[nodiscard]] inline bool operator==(const const_iterator& other) const noexcept
{
return m_position == other.m_position;
};
[[nodiscard]] inline std::weak_ordering operator<=>(const const_iterator& other) const noexcept
{
return m_position <=> other.m_position;
}
[[nodiscard]] inline difference_type operator-(const const_iterator& rhs) const noexcept
{
return m_position - rhs.m_position;
}
private:
brep_vertex* m_vertex;
brep_edge* m_edge;
std::ptrdiff_t m_position;
};
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
/// @name Element access
/// @{
/// Returns the first edge.
[[nodiscard]] inline brep_edge* front() const noexcept
{
return m_head;
}
/// Returns the last edge.
[[nodiscard]] inline brep_edge* back() const noexcept
{
return m_head->m_vertex_previous[m_head->vertices()[1] == m_vertex];
}
/// @}
/// @name Iterators
/// @{
/// Returns an iterator to the first edge.
/// @{
[[nodiscard]] inline constexpr const_iterator begin() const noexcept
{
const_iterator it;
it.m_vertex = m_vertex;
it.m_edge = m_head;
it.m_position = 0;
return it;
}
[[nodiscard]] inline constexpr const_iterator cbegin() const noexcept
{
return begin();
}
/// @}
/// Returns an iterator to the edge following the last edge.
/// @{
[[nodiscard]] inline constexpr const_iterator end() const noexcept
{
const_iterator it;
it.m_vertex = m_vertex;
it.m_edge = m_head;
it.m_position = static_cast<std::ptrdiff_t>(m_size);
return it;
}
[[nodiscard]] inline constexpr const_iterator cend() const noexcept
{
return end();
}
/// @}
/// Returns a reverse iterator to the first edge of the reversed list.
/// @{
[[nodiscard]] inline constexpr const_reverse_iterator rbegin() const noexcept
{
return std::make_reverse_iterator(end());
}
[[nodiscard]] inline constexpr const_reverse_iterator crbegin() const noexcept
{
return rbegin();
}
/// @}
/// Returns a reverse iterator to the edge following the last edge of the reversed list.
/// @{
[[nodiscard]] inline constexpr const_reverse_iterator rend() const noexcept
{
return std::make_reverse_iterator(begin());
}
[[nodiscard]] inline constexpr const_reverse_iterator crend() const noexcept
{
return rend();
}
/// @}
/// @}
/// @name Capacity
/// @{
/// Returns `true` if the list is empty, `false` otherwise.
[[nodiscard]] inline constexpr bool empty() const noexcept
{
return !m_size;
}
/// Returns the number of edges in the list.
[[nodiscard]] inline constexpr std::size_t size() const noexcept
{
return m_size;
}
/// @}
/// @name Modifiers
/// @{
/**
* Appends an edge to the end of the list.
*
* @param edge Pointer to the edge to append.
*/
void push_back(brep_edge* edge);
/**
* Removes an edge from the list.
*
* @param edge Pointer to the edge to remove.
*/
void remove(brep_edge* edge);
/// @}
private:
brep_vertex* m_vertex{};
brep_edge* m_head{};
std::size_t m_size{};
};
/**
* A point in space.
*/
class brep_vertex
{
public:
friend class brep_mesh;
friend class brep_element_container<brep_vertex>;
friend class brep_vertex_container;
friend class brep_edge_container;
/**
* Returns the index of this vertex in the mesh vertex array.
*
* @warning This index may change if any vertices are removed from the mesh.
*/
[[nodiscard]] inline constexpr std::size_t index() const noexcept
{
return m_index;
}
/// Returns the list of edges bounded by this vertex.
[[nodiscard]] inline constexpr const brep_vertex_edge_list& edges() const noexcept
{
return m_edges;
}
private:
std::size_t m_index;
brep_vertex_edge_list m_edges;
};
/**
* B-rep vertex container.
*/
class brep_vertex_container: public brep_element_container<brep_vertex>
{
public:
/**
* Appends a new vertex to the end of the container.
*
* @return Pointer to the new vertex.
*/
brep_vertex* emplace_back() override;
/**
* Erases a vertex and all dependent edges, loops, and faces.
*
* @param vertex Pointer to the vertex to erase.
*
* @warning Invalidates iterators and indices of vertices, edges, loops, and faces.
*/
void erase(brep_vertex* vertex) override;
/**
* Erases all vertices and their dependent edges, loops, and faces.
*/
void clear() noexcept;
private:
friend class brep_mesh;
/**
* Constructs a B-rep vertex container.
*
* @param mesh Pointer to the parent mesh.
*/
inline explicit brep_vertex_container(brep_mesh* mesh) noexcept:
brep_element_container<brep_vertex>(mesh)
{}
};
} // namespace geom
#endif // ANTKEEPER_GEOM_BREP_VERTEX_HPP

+ 51
- 0
src/engine/geom/bvh/bvh-node.hpp View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2023 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_GEOM_BVH_NODE_HPP
#define ANTKEEPER_GEOM_BVH_NODE_HPP
#include <engine/geom/primitives/box.hpp>
#include <cstdint>
namespace geom {
/**
* Single node in a bounding volume hierarchy.
*/
struct bvh_node
{
/// Returns `true` if the node is a leaf node, `false` otherwise.
[[nodiscard]] inline constexpr bool is_leaf() const noexcept
{
return size;
}
/// Node bounds.
geom::box<float> bounds;
/// Number of primitives in the node.
std::uint32_t size;
/// Offset to the first child node (non-leaf) or primitive (leaf).
std::uint32_t offset;
};
} // namespace geom
#endif // ANTKEEPER_GEOM_BVH_NODE_HPP

src/engine/geom/meshes/grid.hpp → src/engine/geom/bvh/bvh-primitive.hpp View File

@ -17,26 +17,26 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GEOM_MESHES_GRID_HPP
#define ANTKEEPER_GEOM_MESHES_GRID_HPP
#ifndef ANTKEEPER_GEOM_BVH_PRIMITIVE_HPP
#define ANTKEEPER_GEOM_BVH_PRIMITIVE_HPP
#include <engine/geom/mesh.hpp>
#include <memory>
#include <engine/geom/primitives/box.hpp>
#include <engine/math/vector.hpp>
namespace geom {
namespace meshes {
/**
* Generates a grid mesh on the XY plane.
*
* @param length Side length of the grid.
* @param subdivisions_x Number of subdivisions on the x-axis.
* @param subdivisions_y Number of subdivisions on the y-axis.
* @return Grid mesh on the XY plane.
* BVH primitive.
*/
[[nodiscard]] std::unique_ptr<geom::mesh> grid_xy(float length, std::size_t subdivisions_x, std::size_t subdivisions_y);
struct bvh_primitive
{
/// Geometric center of the primitive.
math::fvec3 centroid;
/// Axis-aligned bounding box containing the primitive.
geom::box<float> bounds;
};
} // namespace meshes
} // namespace geom
#endif // ANTKEEPER_GEOM_MESHES_GRID_HPP
#endif // ANTKEEPER_GEOM_BVH_PRIMITIVE_HPP

+ 199
- 0
src/engine/geom/bvh/bvh.cpp View File

@ -0,0 +1,199 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/bvh/bvh.hpp>
#include <engine/geom/intersection.hpp>
#include <engine/geom/brep/brep-mesh.hpp>
#include <engine/debug/log.hpp>
#include <algorithm>
#include <numeric>
namespace geom {
bvh::bvh(std::span<const bvh_primitive> primitives)
{
build(primitives);
}
bvh::bvh(const brep_mesh& mesh)
{
build(mesh);
}
void bvh::build(std::span<const bvh_primitive> primitives)
{
if (primitives.empty())
{
m_primitive_indices.clear();
m_nodes.clear();
m_node_count = 0;
}
else
{
// Allocate and fill primitive index array
m_primitive_indices.resize(primitives.size());
std::iota(m_primitive_indices.begin(), m_primitive_indices.end(), 0);
// Allocate nodes
m_nodes.resize(primitives.size() << 1);
// Init root node
m_node_count = 1;
auto& root = m_nodes.front();
root.size = static_cast<std::uint32_t>(primitives.size());
root.offset = 0;
update_bounds(root, primitives);
// Recursively build BVH
subdivide(root, primitives);
}
}
void bvh::build(const brep_mesh& mesh)
{
// Get mesh vertex positions attribute
const auto& vertex_positions = mesh.vertices().attributes().at<math::fvec3>("position");
// Allocate BVH primitives for mesh faces
std::vector<bvh_primitive> primitives(mesh.faces().size());
// Calculate bounding boxes
for (brep_face* face: mesh.faces())
{
auto& primitive = primitives[face->index()];
primitive.centroid = {};
primitive.bounds = {math::fvec3::infinity(), -math::fvec3::infinity()};
for (brep_loop* loop: face->loops())
{
const auto& vertex_position = vertex_positions[loop->vertex()->index()];
primitive.centroid += vertex_position;
primitive.bounds.extend(vertex_position);
}
primitive.centroid /= static_cast<float>(face->loops().size());
}
// Build BVH from the bounding boxes of the mesh faces
build(primitives);
}
void bvh::update_bounds(bvh_node& node, const std::span<const bvh_primitive>& primitives)
{
node.bounds = {math::fvec3::infinity(), -math::fvec3::infinity()};
for (std::uint32_t i = 0; i < node.size; ++i)
{
const auto& primitive = primitives[m_primitive_indices[node.offset + i]];
node.bounds.extend(primitive.bounds);
};
}
void bvh::subdivide(bvh_node& node, const std::span<const bvh_primitive>& primitives)
{
if (node.size <= 2)
{
return;
}
// Determine index of split axis
const auto extents = node.bounds.size();
std::uint8_t split_axis = 0;
if (extents.y() > extents.x())
{
split_axis = 1;
}
if (extents.z() > extents[split_axis])
{
split_axis = 2;
}
// Determine split coordinate
const float split_coord = node.bounds.min[split_axis] + extents[split_axis] * 0.5f;
std::uint32_t i = node.offset;
std::uint32_t j = (node.size) ? i + node.size - 1 : i;
while (i <= j)
{
const auto& primitive = primitives[m_primitive_indices[i]];
if (primitive.centroid[split_axis] < split_coord)
// if (primitive.bounds.center()[split_axis] < split_coord)
{
++i;
}
else
{
std::swap(m_primitive_indices[i], m_primitive_indices[j]);
if (!j)
{
break;
}
--j;
}
}
const std::uint32_t left_size = i - node.offset;
if (!left_size || left_size == node.size)
{
return;
}
const std::uint32_t left_index = m_node_count++;
auto& left_child = m_nodes[left_index];
left_child.offset = node.offset;
left_child.size = left_size;
update_bounds(left_child, primitives);
const std::uint32_t right_index = m_node_count++;
auto& right_child = m_nodes[right_index];
right_child.offset = i;
right_child.size = node.size - left_size;
update_bounds(right_child, primitives);
node.offset = left_index;
node.size = 0;
subdivide(left_child, primitives);
subdivide(right_child, primitives);
}
void bvh::visit(const bvh_node& node, const geom::ray<float, 3>& ray, const visitor_type& f) const
{
if (!geom::intersection(ray, node.bounds))
{
return;
}
if (node.is_leaf())
{
// Visit leaf node primitives
for (std::uint32_t i = 0; i < node.size; ++i)
{
f(m_primitive_indices[node.offset + i]);
}
}
else
{
// Recursively visit node children
visit(m_nodes[node.offset], ray, f);
visit(m_nodes[node.offset + 1], ray, f);
}
}
} // namespace geom

+ 113
- 0
src/engine/geom/bvh/bvh.hpp View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2023 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_GEOM_BVH_HPP
#define ANTKEEPER_GEOM_BVH_HPP
#include <engine/geom/primitives/ray.hpp>
#include <engine/geom/bvh/bvh-primitive.hpp>
#include <engine/geom/bvh/bvh-node.hpp>
#include <cstdint>
#include <functional>
#include <span>
#include <vector>
namespace geom {
class brep_mesh;
/**
* Bounding volume hierarchy (BVH).
*/
class bvh
{
public:
using visitor_type = std::function<void(std::uint32_t)>;
/**
* Constructs a BVH from a set of primitives.
*
* @param primitives Axis-aligned bounding boxes.
*/
explicit bvh(std::span<const bvh_primitive> primitives);
/**
* Constructs a BVH from a B-rep mesh.
*
* @param mesh B-rep mesh from which to build the BVH.
*/
explicit bvh(const brep_mesh& mesh);
/// Constructs an empty BVH.
constexpr bvh() noexcept = default;
/**
* Constructs a BVH from a set of primitives.
*
* @param primitives BVH primitives.
*/
void build(std::span<const bvh_primitive> primitives);
/**
* Constructs a BVH from a B-rep mesh.
*
* @param mesh B-rep mesh from which to build the BVH.
*/
void build(const brep_mesh& mesh);
/**
* Visits the primitive indices of all BVH nodes that intersect a ray.
*
* @param ray Query ray.
* @param f Unary visitor function which operates on a BVH primitive index.
*/
inline void visit(const geom::ray<float, 3>& ray, const visitor_type& f) const
{
if (m_node_count)
{
visit(m_nodes.front(), ray, f);
}
}
/// Returns the BVH nodes.
[[nodiscard]] inline constexpr const std::vector<bvh_node>& nodes() const noexcept
{
return m_nodes;
}
private:
void update_bounds(bvh_node& node, const std::span<const bvh_primitive>& primitives);
/**
* Builds the BVH through recursive subdivision.
*
* @param node Current node.
* @param primitives BVH primitives.
*/
void subdivide(bvh_node& node, const std::span<const bvh_primitive>& primitives);
void visit(const bvh_node& node, const geom::ray<float, 3>& ray, const visitor_type& f) const;
std::vector<std::uint32_t> m_primitive_indices;
std::vector<bvh_node> m_nodes;
std::uint32_t m_node_count{};
};
} // namespace geom
#endif // ANTKEEPER_GEOM_BVH_HPP

+ 4
- 4
src/engine/geom/cartesian.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_GEOM_CARTESIAN_HPP
#define ANTKEEPER_GEOM_CARTESIAN_HPP
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
#include <cmath>
namespace geom {
@ -37,14 +37,14 @@ namespace cartesian {
* @see geom::coordinates::spherical
*/
template <class T>
math::vector3<T> to_spherical(const math::vector3<T>& v);
math::vec3<T> to_spherical(const math::vec3<T>& v);
template <class T>
math::vector3<T> to_spherical(const math::vector3<T>& v)
math::vec3<T> to_spherical(const math::vec3<T>& v)
{
const T xx_yy = v.x() * v.x() + v.y() * v.y();
return math::vector3<T>
return math::vec3<T>
{
std::sqrt(xx_yy + v.z() * v.z()),
std::atan2(v.z(), std::sqrt(xx_yy)),

+ 24
- 20
src/engine/geom/intersection.hpp View File

@ -144,51 +144,55 @@ template
*
* @return Tuple containing the distance along the ray to the point of intersection, followed by two barycentric coordinates of the point of intersection, or `std::nullopt` if no intersection occurred.
*/
/// @{
template <class T>
[[nodiscard]] std::optional<std::tuple<T, T, T>> intersection(const ray<T, 3>& ray, const math::vector<T, 3>& a, const math::vector<T, 3>& b, const math::vector<T, 3>& c)
[[nodiscard]] constexpr std::optional<std::tuple<T, T, T>> intersection(const ray<T, 3>& ray, const math::vec3<T>& a, const math::vec3<T>& b, const math::vec3<T>& c) noexcept
{
// Find edges
const math::vector<T, 3> edge10 = b - a;
const math::vector<T, 3> edge20 = c - a;
const math::vec3<T> edge_ab = b - a;
const math::vec3<T> edge_ac = c - a;
// Calculate determinant
const math::vector<T, 3> pv = math::cross(ray.direction, edge20);
const T det = math::dot(edge10, pv);
const math::vec3<T> pv = math::cross(ray.direction, edge_ac);
const T det = math::dot(edge_ab, pv);
if (!det)
{
return std::nullopt;
}
const T inverse_det = T{1} / det;
// Calculate u
const math::vector<T, 3> tv = ray.origin - a;
const math::vec3<T> tv = ray.origin - a;
const T u = math::dot(tv, pv) * inverse_det;
if (u < T{0} || u > T{1})
{
return std::nullopt;
}
// Calculate v
const math::vector<T, 3> qv = math::cross(tv, edge10);
const math::vec3<T> qv = math::cross(tv, edge_ab);
const T v = math::dot(ray.direction, qv) * inverse_det;
if (v < T{0} || u + v > T{1})
{
return std::nullopt;
}
// Calculate t
const T t = math::dot(edge20, qv) * inverse_det;
if (t > T{0})
const T t = math::dot(edge_ac, qv) * inverse_det;
if (t < T{0})
{
return std::tuple<T, T, T>{t, u, v};
return std::nullopt;
}
return std::nullopt;
return std::tuple<T, T, T>{t, u, v};
}
template <class T>
[[nodiscard]] inline constexpr std::optional<std::tuple<T, T, T>> intersection(const math::vec3<T>& a, const math::vec3<T>& b, const math::vec3<T>& c, const ray<T, 3>& ray) noexcept
{
return intersection(ray, a, b, c);
}
/// @}
/**
* Hyperrectangle-hyperrectangle intersection test.

+ 0
- 179
src/engine/geom/mesh-accelerator.cpp View File

@ -1,179 +0,0 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/mesh-accelerator.hpp>
#include <engine/geom/mesh-functions.hpp>
#include <engine/geom/morton.hpp>
#include <bitset>
namespace geom {
mesh_accelerator::mesh_accelerator()
{}
void mesh_accelerator::build(const mesh& mesh)
{
// Clear octree and face map
octree.clear();
face_map.clear();
// Calculate mesh dimensions
box<float> bounds = calculate_bounds(mesh);
float3 mesh_dimensions = bounds.max - bounds.min;
center_offset = mesh_dimensions * 0.5f - (bounds.min + bounds.max) * 0.5f;
// Calculate node dimensions at each octree depth
for (auto i = 0; i <= octree_type::max_depth; ++i)
{
node_dimensions[i] = mesh_dimensions * static_cast<float>((1.0f / std::pow(2, i)));
}
// Add faces to octree
for (mesh::face* face: mesh.get_faces())
{
// Calculate face bounds
float3 min_point = reinterpret_cast<const float3&>(face->edge->vertex->position);
float3 max_point = min_point;
mesh::edge* edge = face->edge;
do
{
const auto& position = edge->vertex->position;
for (int i = 0; i < 3; ++i)
{
min_point[i] = std::min<float>(min_point[i], position[i]);
max_point[i] = std::max<float>(max_point[i], position[i]);
}
edge = edge->next;
}
while (edge != face->edge);
// 1. Find max depth node of aabb min
// 2. Find max depth node of aabb max
// 3. Find common ancestor of the two nodes--that's the containing node.
typename octree_type::node_type min_node = find_node(min_point);
typename octree_type::node_type max_node = find_node(max_point);
typename octree_type::node_type containing_node = octree_type::common_ancestor(min_node, max_node);
// Insert containing node into octree
octree.insert(containing_node);
// Add face to face map
face_map[containing_node].push_back(face);
}
}
std::optional<mesh_accelerator::ray_query_result> mesh_accelerator::query_nearest(const ray<float, 3>& ray) const
{
ray_query_result result;
result.t = std::numeric_limits<float>::infinity();
result.face = nullptr;
query_nearest_recursive(result.t, result.face, octree.root, ray);
if (result.face)
return std::optional{result};
return std::nullopt;
}
void mesh_accelerator::query_nearest_recursive(float& nearest_t, geom::mesh::face*& nearest_face, typename octree_type::node_type node, const ray<float, 3>& ray) const
{
// Get node bounds
const box<float> node_bounds = get_node_bounds(node);
// If ray passed through this node
if (intersection(ray, node_bounds))
{
// Test all triangles in the node
if (auto it = face_map.find(node); it != face_map.end())
{
const std::list<mesh::face*>& faces = it->second;
for (mesh::face* face: faces)
{
// Get triangle coordinates
const float3& a = reinterpret_cast<const float3&>(face->edge->vertex->position);
const float3& b = reinterpret_cast<const float3&>(face->edge->next->vertex->position);
const float3& c = reinterpret_cast<const float3&>(face->edge->previous->vertex->position);
// Test for intersection with triangle
auto triangle_intersection = intersection(ray, a, b, c);
if (triangle_intersection)
{
const float t = std::get<0>(*triangle_intersection);
if (t < nearest_t)
{
nearest_t = t;
nearest_face = face;
}
}
}
}
// Test all child nodes
if (!octree.is_leaf(node))
{
for (int i = 0; i < 8; ++i)
{
query_nearest_recursive(nearest_t, nearest_face, octree.child(node, i), ray);
}
}
}
}
box<float> mesh_accelerator::get_node_bounds(typename octree_type::node_type node) const
{
// Decode Morton location of node
std::uint32_t x, y, z;
morton::decode(octree_type::location(node), x, y, z);
float3 node_location = float3{static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)};
// Get node dimensions at node depth
const float3& dimensions = node_dimensions[octree_type::depth(node)];
// Calculate AABB
float3 min_point = (node_location * dimensions) - center_offset;
return box<float>{min_point, min_point + dimensions};
}
typename mesh_accelerator::octree_type::node_type mesh_accelerator::find_node(const float3& point) const
{
// Transform point to octree space
float3 transformed_point = (point + center_offset);
// Account for floating-point tolerance
const float epsilon = 0.00001f;
transformed_point.x() = std::max<float>(0.0f, std::min<float>(node_dimensions[0].x() - epsilon, transformed_point.x()));
transformed_point.y() = std::max<float>(0.0f, std::min<float>(node_dimensions[0].y() - epsilon, transformed_point.y()));
transformed_point.z() = std::max<float>(0.0f, std::min<float>(node_dimensions[0].z() - epsilon, transformed_point.z()));
// Transform point to max-depth node space
transformed_point = transformed_point / node_dimensions[octree_type::max_depth];
// Encode transformed point as a Morton location code
std::uint32_t location = morton::encode(
static_cast<std::uint32_t>(transformed_point.x()),
static_cast<std::uint32_t>(transformed_point.y()),
static_cast<std::uint32_t>(transformed_point.z()));
// Return max depth node at the determined location
return octree_type::node(octree_type::max_depth, location);
}
} // namespace geom

+ 0
- 80
src/engine/geom/mesh-accelerator.hpp View File

@ -1,80 +0,0 @@
/*
* Copyright (C) 2023 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_GEOM_MESH_ACCELERATOR_HPP
#define ANTKEEPER_GEOM_MESH_ACCELERATOR_HPP
#include <engine/geom/mesh.hpp>
#include <engine/geom/octree.hpp>
#include <engine/geom/primitives/box.hpp>
#include <engine/geom/intersection.hpp>
#include <engine/utility/fundamental-types.hpp>
#include <list>
#include <optional>
#include <unordered_map>
namespace geom {
/**
* Acceleration structure for querying mesh geometry.
*/
class mesh_accelerator
{
public:
struct ray_query_result
{
float t;
geom::mesh::face* face;
};
mesh_accelerator();
/**
* Builds the acceleration structure.
*/
void build(const mesh& mesh);
/**
* Finds the first intersection between a ray and a triangle in the mesh.
*
* @param ray Ray to test for intersection.
* @return Ray query result on intersection, and `std::nullopt` if no intersection occurred.
*/
std::optional<ray_query_result> query_nearest(const ray<float, 3>& ray) const;
private:
typedef unordered_octree32 octree_type;
box<float> get_node_bounds(typename octree_type::node_type node) const;
void query_nearest_recursive(float& nearest_t, geom::mesh::face*& nearest_face, typename octree_type::node_type node, const ray<float, 3>& ray) const;
/// Returns the max-depth node in which the point is located
typename octree_type::node_type find_node(const float3& point) const;
octree_type octree;
float3 node_dimensions[octree_type::max_depth + 1];
float3 center_offset;
std::unordered_map<typename octree_type::node_type, std::list<mesh::face*>> face_map;
};
} // namespace geom
#endif // ANTKEEPER_GEOM_MESH_ACCELERATOR_HPP

+ 0
- 222
src/engine/geom/mesh-functions.cpp View File

@ -1,222 +0,0 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/mesh-functions.hpp>
#include <engine/utility/fundamental-types.hpp>
#include <unordered_map>
#include <vector>
namespace geom {
struct edge_hasher
{
std::size_t operator()(const std::array<std::size_t, 2>& v) const noexcept
{
std::size_t hash = std::hash<std::size_t>()(v[0]);
return hash ^ (std::hash<std::size_t>()(v[1]) + 0x9e3779b9 + (hash << 6) + (hash >> 2));
}
};
void create_triangle_mesh(mesh& mesh, const std::vector<float3>& vertices, const std::vector<std::array<std::uint_fast32_t, 3>>& triangles)
{
for (const auto& vertex: vertices)
mesh.add_vertex(vertex);
std::unordered_map<std::array<std::size_t, 2>, geom::mesh::edge*, edge_hasher> edge_map;
const std::vector<mesh::vertex*>& mesh_vertices = mesh.get_vertices();
std::vector<geom::mesh::edge*> loop(3);
for (const auto& triangle: triangles)
{
geom::mesh::vertex* triangle_vertices[3] =
{
mesh_vertices[triangle[0]],
mesh_vertices[triangle[1]],
mesh_vertices[triangle[2]]
};
for (int j = 0; j < 3; ++j)
{
geom::mesh::vertex* start = triangle_vertices[j];
geom::mesh::vertex* end = triangle_vertices[(j + 1) % 3];
if (auto it = edge_map.find({start->index, end->index}); it != edge_map.end())
{
loop[j] = it->second;
}
else
{
loop[j] = mesh.add_edge(start, end);
edge_map[{start->index, end->index}] = loop[j];
edge_map[{end->index, start->index}] = loop[j]->symmetric;
}
}
mesh.add_face(loop);
}
}
void calculate_face_normals(float3* normals, const mesh& mesh)
{
const std::vector<mesh::face*>& faces = mesh.get_faces();
for (std::size_t i = 0; i < faces.size(); ++i)
{
const mesh::face& face = *(faces[i]);
const float3& a = face.edge->vertex->position;
const float3& b = face.edge->next->vertex->position;
const float3& c = face.edge->previous->vertex->position;
normals[i] = math::normalize(math::cross(b - a, c - a));
}
}
float3 calculate_face_normal(const mesh::face& face)
{
const float3& a = face.edge->vertex->position;
const float3& b = face.edge->next->vertex->position;
const float3& c = face.edge->previous->vertex->position;
return math::normalize(math::cross(b - a, c - a));
}
void calculate_vertex_tangents(float4* tangents, const float2* texcoords, const float3* normals, const mesh& mesh)
{
const std::vector<mesh::face*>& faces = mesh.get_faces();
const std::vector<mesh::vertex*>& vertices = mesh.get_vertices();
// Allocate tangent and bitangent buffers
std::vector<float3> tangent_buffer(vertices.size(), float3{0.0f, 0.0f, 0.0f});
std::vector<float3> bitangent_buffer(vertices.size(), float3{0.0f, 0.0f, 0.0f});
// Accumulate tangents and bitangents
for (std::size_t i = 0; i < faces.size(); ++i)
{
const mesh::face& face = *(faces[i]);
std::size_t ia = face.edge->vertex->index;
std::size_t ib = face.edge->next->vertex->index;
std::size_t ic = face.edge->previous->vertex->index;
const float3& a = vertices[ia]->position;
const float3& b = vertices[ib]->position;
const float3& c = vertices[ic]->position;
const float2& uva = texcoords[ia];
const float2& uvb = texcoords[ib];
const float2& uvc = texcoords[ic];
float3 ba = b - a;
float3 ca = c - a;
float2 uvba = uvb - uva;
float2 uvca = uvc - uva;
float f = 1.0f / (uvba.x() * uvca.y() - uvca.x() * uvba.y());
float3 tangent = (ba * uvca.y() - ca * uvba.y()) * f;
float3 bitangent = (ba * -uvca.x() + ca * uvba.x()) * f;
tangent_buffer[ia] += tangent;
tangent_buffer[ib] += tangent;
tangent_buffer[ic] += tangent;
bitangent_buffer[ia] += bitangent;
bitangent_buffer[ib] += bitangent;
bitangent_buffer[ic] += bitangent;
}
// Orthogonalize tangents
for (std::size_t i = 0; i < vertices.size(); ++i)
{
const float3& n = normals[i];
const float3& t = tangent_buffer[i];
const float3& b = bitangent_buffer[i];
// Gram-Schmidt orthogonalize tangent
float3 tangent = math::normalize(t - n * math::dot(n, t));
// Calculate bitangent sign
float bitangent_sign = (math::dot(math::cross(n, t), b) < 0.0f) ? -1.0f : 1.0f;
tangents[i] = {tangent.x(), tangent.y(), tangent.z(), bitangent_sign};
}
}
box<float> calculate_bounds(const mesh& mesh)
{
box<float> bounds;
for (int i = 0; i < 3; ++i)
{
bounds.min[i] = std::numeric_limits<float>::infinity();
bounds.max[i] = -std::numeric_limits<float>::infinity();
}
for (const mesh::vertex* vertex: mesh.get_vertices())
{
const auto& position = vertex->position;
bounds.extend(position);
}
return bounds;
}
mesh::vertex* poke_face(mesh& mesh, std::size_t index)
{
mesh::face* face = mesh.get_faces()[index];
// Collect face edges and sum edge vertex positions
mesh::loop loop = {face->edge};
float3 sum_positions = face->edge->vertex->position;
for (mesh::edge* edge = face->edge->next; edge != face->edge; edge = edge->next)
{
loop.push_back(edge);
sum_positions += edge->vertex->position;
}
if (loop.size() <= 2)
return nullptr;
// Remove face
mesh.remove_face(face);
// Add vertex in center
mesh::vertex* center = mesh.add_vertex(sum_positions / static_cast<float>(loop.size()));
// Create first triangle
geom::mesh::edge* ab = loop[0];
geom::mesh::edge* bc = mesh.add_edge(ab->next->vertex, center);
geom::mesh::edge* ca = mesh.add_edge(center, ab->vertex);
mesh.add_face({ab, bc, ca});
// Save first triangle CA edge
geom::mesh::edge* first_triangle_ca = ca;
// Create remaining triangles
for (std::size_t i = 1; i < loop.size(); ++i)
{
ab = loop[i];
ca = bc->symmetric;
if (i == loop.size() - 1)
bc = first_triangle_ca->symmetric;
else
bc = mesh.add_edge(ab->next->vertex, center);
mesh.add_face({ab, bc, ca});
}
return center;
}
} // namespace geom

+ 0
- 76
src/engine/geom/mesh-functions.hpp View File

@ -1,76 +0,0 @@
/*
* Copyright (C) 2023 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_GEOM_MESH_FUNCTIONS_HPP
#define ANTKEEPER_GEOM_MESH_FUNCTIONS_HPP
#include <engine/geom/primitives/box.hpp>
#include <engine/geom/mesh.hpp>
#include <engine/utility/fundamental-types.hpp>
#include <array>
#include <vector>
namespace geom {
/**
* Creates a triangle mesh from a list of vertices and indices.
*
* @param[out] mesh Mesh to which vertices, edges, and faces will be added.
* @param vertices Vertex positions
* @param triangles Triangle indices
* @return Newly created triangle mesh.
*/
void create_triangle_mesh(mesh& mesh, const std::vector<float3>& vertices, const std::vector<std::array<std::uint_fast32_t, 3>>& triangles);
/**
* Calculates normals for each face.
*
* @param[out] Array in which faceted normals will be stored.
*/
void calculate_face_normals(float3* normals, const mesh& mesh);
float3 calculate_face_normal(const mesh::face& face);
/**
* Calculates smooth tangents per-vertex.
*
* @param[out] tangents Array in which vertex tangents will be stored. A bitangent sign is stored in each tangent vector's fourth component.
* @param[in] texcoords Array containing vertex texture coordinates.
* @param[in] normals Array containing vertex normals.
*/
void calculate_vertex_tangents(float4* tangents, const float2* texcoords, const float3* normals, const mesh& mesh);
/**
* Calculates the AABB bounds of a mesh.
*/
box<float> calculate_bounds(const mesh& mesh);
/**
* Triangulates a face by adding a new vertex in the center, then creating triangles between the edges of the original face and the new vertex.
*
* @param mesh Mesh containing the face to poke.
* @param index Index of the face to poke.
* @return Pointer to the newly-created vertex in the center of the face, or `nullptr` if the face could not be poked.
*/
mesh::vertex* poke_face(mesh& mesh, std::size_t index);
} // namespace geom
#endif // ANTKEEPER_GEOM_MESH_FUNCTIONS_HPP

+ 0
- 436
src/engine/geom/mesh.cpp View File

@ -1,436 +0,0 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/mesh.hpp>
#include <stdexcept>
namespace geom {
mesh::mesh(const mesh& other)
{
*this = other;
}
mesh::~mesh()
{
clear();
}
mesh& mesh::operator=(const mesh& other)
{
// Clear the mesh
clear();
// Resize vertices, edges, and faces
vertices.resize(other.vertices.size());
edges.resize(other.edges.size());
faces.resize(other.faces.size());
// Allocate vertices
for (std::size_t i = 0; i < vertices.size(); ++i)
vertices[i] = new vertex();
// Allocate edges
for (std::size_t i = 0; i < edges.size(); ++i)
{
edges[i] = new edge();
edges[i]->symmetric = new edge();
edges[i]->symmetric->symmetric = edges[i];
}
// Allocate faces
for (std::size_t i = 0; i < faces.size(); ++i)
faces[i] = new face();
// Copy vertices
for (std::size_t i = 0; i < vertices.size(); ++i)
{
vertex* va = vertices[i];
const vertex* vb = other.vertices[i];
va->index = vb->index;
va->position = vb->position;
va->edge = nullptr;
if (vb->edge)
{
va->edge = edges[vb->edge->index];
if (vb->edge != other.edges[vb->edge->index])
va->edge = va->edge->symmetric;
}
}
// Copy edges
for (std::size_t i = 0; i < edges.size(); ++i)
{
edge* ea = edges[i];
const edge* eb = other.edges[i];
for (std::size_t j = 0; j < 2; ++j)
{
ea->index = eb->index;
ea->vertex = vertices[eb->vertex->index];
ea->face = nullptr;
if (eb->face)
ea->face = faces[eb->face->index];
ea->previous = edges[eb->previous->index];
if (eb->previous != other.edges[eb->previous->index])
ea->previous = ea->previous->symmetric;
ea->next = edges[eb->next->index];
if (eb->next != other.edges[eb->next->index])
ea->next = ea->next->symmetric;
ea = ea->symmetric;
eb = eb->symmetric;
}
}
// Copy faces
for (std::size_t i = 0; i < faces.size(); ++i)
{
face* fa = faces[i];
const face* fb = other.faces[i];
fa->index = fb->index;
fa->edge = edges[fb->edge->index];
if (fb->edge != other.edges[fb->edge->index])
fa->edge = fa->edge->symmetric;
}
return *this;
}
void mesh::clear() noexcept
{
// Deallocate vertices
for (mesh::vertex* vertex: vertices)
delete vertex;
// Deallocate edges
for (mesh::edge* edge: edges)
{
delete edge->symmetric;
delete edge;
}
// Deallocate faces
for (mesh::face* face: faces)
delete face;
vertices.clear();
edges.clear();
faces.clear();
}
mesh::vertex* mesh::add_vertex(const float3& position)
{
mesh::vertex* vertex = new mesh::vertex
{
vertices.size(),
nullptr,
position
};
vertices.push_back(vertex);
return vertex;
}
mesh::edge* mesh::add_edge(mesh::vertex* a, mesh::vertex* b)
{
mesh::edge* ab = new mesh::edge();
mesh::edge* ba = new mesh::edge();
ab->index = edges.size();
ab->vertex = a;
ab->face = nullptr;
ab->previous = ba;
ab->next = ba;
ab->symmetric = ba;
ba->index = edges.size();
ba->vertex = b;
ba->face = nullptr;
ba->previous = ab;
ba->next = ab;
ba->symmetric = ab;
if (!a->edge)
{
a->edge = ab;
}
else
{
mesh::edge* a_in = find_free_incident(a);
mesh::edge* a_out = a_in->next;
a_in->next = ab;
ab->previous = a_in;
ba->next = a_out;
a_out->previous = ba;
}
if (!b->edge)
{
b->edge = ba;
}
else
{
mesh::edge* b_in = find_free_incident(b);
mesh::edge* b_out = b_in->next;
b_in->next = ba;
ba->previous = b_in;
ab->next = b_out;
b_out->previous = ab;
}
// Add edge
edges.push_back(ab);
return ab;
}
mesh::face* mesh::add_face(const loop& loop)
{
if (loop.empty())
{
throw std::runtime_error("Empty edge loop");
}
// Validate edge loop
for (std::size_t i = 0; i < loop.size(); ++i)
{
mesh::edge* current = loop[i];
mesh::edge* next = loop[(i + 1) % loop.size()];
if (current->symmetric->vertex != next->vertex)
{
// Disconnected edge loop
throw std::runtime_error("Disconnected edge loop");
}
if (current->face)
{
// This edge already has a face
throw std::runtime_error("Non-manifold mesh 1");
}
}
// Make edges adjacent
for (std::size_t i = 0; i < loop.size(); ++i)
{
if (!make_adjacent(loop[i], loop[(i + 1) % loop.size()]))
{
throw std::runtime_error("Non-manifold mesh 2");
}
}
// Create face
mesh::face* face = new mesh::face();
face->edge = loop[0];
face->index = faces.size();
// Add face
faces.push_back(face);
// Connect edges to the face
for (mesh::edge* edge: loop)
{
edge->face = face;
}
return face;
}
void mesh::remove_face(mesh::face* face)
{
// Nullify pointers to this face
mesh::edge* edge = face->edge;
do
{
edge->face = nullptr;
edge = edge->next;
}
while (edge != face->edge);
// Adjust indices of faces after this face
for (std::size_t i = face->index + 1; i < faces.size(); ++i)
{
--faces[i]->index;
}
// Remove face from the faces vector
faces.erase(faces.begin() + face->index);
// Deallocate face
delete face;
}
void mesh::remove_edge(mesh::edge* edge)
{
mesh::edge* ab = edge;
mesh::edge* ba = edge->symmetric;
mesh::vertex* a = ab->vertex;
mesh::edge* a_in = ab->previous;
mesh::edge* a_out = ba->next;
mesh::vertex* b = ba->vertex;
mesh::edge* b_in = ba->previous;
mesh::edge* b_out = ab->next;
// Remove dependent faces
if (ab->face)
remove_face(ab->face);
if (ba->face)
remove_face(ba->face);
// Re-link edges
if (a->edge == ab)
a->edge = (a_out == ab) ? nullptr : a_out;
if (b->edge == ba)
b->edge = (b_out == ba) ? nullptr : b_out;
a_in->next = a_out;
a_out->previous = a_in;
b_in->next = b_out;
b_out->previous = b_in;
// Adjust indices of edges after this edge
for (std::size_t i = edge->index + 1; i < edges.size(); ++i)
{
--edges[i]->index;
--edges[i]->symmetric->index;
}
// Remove edge from the edges vector
edges.erase(edges.begin() + edge->index);
// Deallocate edge
delete edge->symmetric;
delete edge;
}
void mesh::remove_vertex(mesh::vertex* vertex)
{
// Remove connected edges
if (vertex->edge)
{
mesh::edge* current = nullptr;
mesh::edge* next = vertex->edge;
do
{
current = next;
next = next->symmetric->next;
if (next == current)
{
next = next->symmetric->next;
}
remove_edge(current);
}
while (current != next);
}
// Adjust indices of vertices after this vertex
for (std::size_t i = vertex->index + 1; i < vertices.size(); ++i)
{
--vertices[i]->index;
}
// Remove vertex from the vertices vector
vertices.erase(vertices.begin() + vertex->index);
// Deallocate vertex
delete vertex;
}
mesh::edge* mesh::find_free_incident(mesh::vertex* vertex) const
{
mesh::edge* begin = vertex->edge->symmetric;
mesh::edge* current = begin;
do
{
if (!current->face)
{
return current;
}
current = current->next->symmetric;
}
while (current != begin);
return nullptr;
}
mesh::edge* mesh::find_free_incident(mesh::edge* start_edge, mesh::edge* end_edge) const
{
if (start_edge == end_edge)
{
return nullptr;
}
mesh::edge* current = start_edge;
do
{
if (!current->face)
{
return current;
}
current = current->next->symmetric;
}
while (current != end_edge);
return nullptr;
}
bool mesh::make_adjacent(mesh::edge* in, mesh::edge* out)
{
if (in->next == out)
{
return true;
}
mesh::edge* b = in->next;
mesh::edge* d = out->previous;
mesh::edge* g = find_free_incident(out->symmetric, in);
if (!g)
{
return false;
}
mesh::edge* h = g->next;
in->next = out;
out->previous = in;
g->next = b;
b->previous = g;
d->next = h;
h->previous = d;
return true;
}
} // namespace geom

+ 0
- 216
src/engine/geom/mesh.hpp View File

@ -1,216 +0,0 @@
/*
* Copyright (C) 2023 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_GEOM_MESH_HPP
#define ANTKEEPER_GEOM_MESH_HPP
#include <engine/utility/fundamental-types.hpp>
#include <vector>
namespace geom {
/**
* Half-edge mesh.
*
* @see http://kaba.hilvi.org/homepage/blog/halfedge/halfedge.htm
*/
class mesh
{
public:
struct vertex;
struct edge;
struct face;
/**
* Half-edge mesh vertex, containing its index, a pointer to its parent edge, and its position vector.
*/
struct vertex
{
/// Index of this vertex.
std::size_t index;
/// Pointer to the edge to which this vertex belongs.
mesh::edge* edge;
/// Vertex position.
float3 position;
};
/**
* Half-edge mesh edge, containing its index and pointers to its starting vertex, parent face, and related edges.
*/
struct edge
{
/// Index of this edge.
std::size_t index;
/// Pointer to the vertex at which the edge starts.
mesh::vertex* vertex;
/// Pointer to the face on the left of this edge.
mesh::face* face;
/// Pointer to the previous edge in the parent face.
mesh::edge* previous;
/// Pointer to the next edge in the parent face.
mesh::edge* next;
/// Pointer to the symmetric edge.
mesh::edge* symmetric;
};
/**
* Half-edge mesh face, containing its index and a pointer to its first edge.
*/
struct face
{
/// Index of this face.
std::size_t index;
/// Pointer to the first edge in this face.
mesh::edge* edge;
};
/**
* List of edges which form a face.
*/
typedef std::vector<edge*> loop;
/**
* Constructs a mesh.
*/
constexpr mesh() noexcept = default;
/**
* Copy-constructs a mesh.
*/
mesh(const mesh& other);
/**
* Destructs a mesh.
*/
~mesh() noexcept;
/**
* Copies another mesh into this mesh.
*
* @param other Mesh to copy.
*
* @return Reference to this mesh.
*/
mesh& operator=(const mesh& other);
/**
* Removes all vertices, edges, and faces from the mesh.
*/
void clear() noexcept;
/**
* Adds a vertex to the mesh.
*
* @param position Position of the vertex.
*
* @return Pointer to the added vertex.
*
* @warning The added vertex will initially have a null edge.
*/
mesh::vertex* add_vertex(const float3& position);
/**
* Adds two half edges to the mesh.
*
* @param a Vertex from which the edge originates.
* @param b Vertex at which the edge ends.
*
* @return Pointer to the half edge `ab`. The symmetric half edge `ba` can be accessed through `ab->symmetric`.
*/
mesh::edge* add_edge(mesh::vertex* a, mesh::vertex* b);
/**
* Adds a face to the mesh.
*
* @param loop List of edges which form the face.
* @return Pointer to the added face.
*
* @exception std::runtime_error Empty edge loop.
* @exception std::runtime_error Disconnected edge loop.
* @exception std::runtime_error Non-manifold mesh 1.
* @exception std::runtime_error Non-manifold mesh 2.
*/
mesh::face* add_face(const loop& loop);
/**
* Removes a face from the mesh.
*
* @param face Face to be removed. This face will be deallocated after removal.
*/
void remove_face(mesh::face* face);
/**
* Removes an edge and all dependent faces from the mesh.
*
* @param edge Edge to be removed. This edge will be deallocated after removal.
*/
void remove_edge(mesh::edge* edge);
/**
* Removes a vertex, all dependent edges, and all dependent faces from the mesh.
*
* @param vertex Vertex to be removed. This vertex will be deallocated after removal.
*/
void remove_vertex(mesh::vertex* vertex);
/// Returns the mesh vertices.
const std::vector<mesh::vertex*>& get_vertices() const;
/// Returns the mesh edges.
const std::vector<mesh::edge*>& get_edges() const;
/// Returns the mesh faces.
const std::vector<mesh::face*>& get_faces() const;
private:
mesh::edge* find_free_incident(mesh::vertex* vertex) const;
mesh::edge* find_free_incident(mesh::edge* start_edge, mesh::edge* end_edge) const;
bool make_adjacent(mesh::edge* in_edge, mesh::edge* out_edge);
std::vector<mesh::vertex*> vertices;
std::vector<mesh::edge*> edges;
std::vector<mesh::face*> faces;
};
inline const std::vector<mesh::vertex*>& mesh::get_vertices() const
{
return vertices;
}
inline const std::vector<mesh::edge*>& mesh::get_edges() const
{
return edges;
}
inline const std::vector<mesh::face*>& mesh::get_faces() const
{
return faces;
}
} // namespace geom
#endif // ANTKEEPER_GEOM_MESH_HPP

+ 0
- 102
src/engine/geom/meshes/grid.cpp View File

@ -1,102 +0,0 @@
/*
* Copyright (C) 2023 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/>.
*/
#include <engine/geom/meshes/grid.hpp>
#include <array>
#include <cmath>
#include <map>
namespace geom {
namespace meshes {
std::unique_ptr<geom::mesh> grid_xy(float length, std::size_t subdivisions_x, std::size_t subdivisions_y)
{
// Allocate new mesh
std::unique_ptr<geom::mesh> mesh = std::make_unique<geom::mesh>();
// Determine vertex count and placement
std::size_t columns = subdivisions_x + 1;
std::size_t rows = subdivisions_y + 1;
float column_length = length / static_cast<float>(columns);
float row_length = length / static_cast<float>(rows);
// Generate mesh vertices
float3 position;
position.z() = 0.0f;
position.y() = -length * 0.5f;
for (std::size_t i = 0; i <= rows; ++i)
{
position.x() = -length * 0.5f;
for (std::size_t j = 0; j <= columns; ++j)
{
mesh->add_vertex(position);
position.x() += column_length;
}
position.y() += row_length;
}
// Function to eliminate duplicate edges
std::map<std::array<std::size_t, 2>, geom::mesh::edge*> edge_map;
auto add_or_find_edge = [&](geom::mesh::vertex* start, geom::mesh::vertex* end) -> geom::mesh::edge*
{
geom::mesh::edge* edge;
if (auto it = edge_map.find({start->index, end->index}); it != edge_map.end())
{
edge = it->second;
}
else
{
edge = mesh->add_edge(start, end);
edge_map[{start->index, end->index}] = edge;
edge_map[{end->index, start->index}] = edge->symmetric;
}
return edge;
};
// Connect vertices with edges and faces
const std::vector<geom::mesh::vertex*>& vertices = mesh->get_vertices();
for (std::size_t i = 0; i < rows; ++i)
{
for (std::size_t j = 0; j < columns; ++j)
{
geom::mesh::vertex* a = vertices[i * (columns + 1) + j];
geom::mesh::vertex* b = vertices[(i + 1) * (columns + 1) + j];
geom::mesh::vertex* c = vertices[i * (columns + 1) + j + 1];
geom::mesh::vertex* d = vertices[(i + 1) * (columns + 1) + j + 1];
// a---c
// | |
// b---d
geom::mesh::edge* ab = add_or_find_edge(a, b);
geom::mesh::edge* bd = add_or_find_edge(b, d);
geom::mesh::edge* dc = add_or_find_edge(d, c);
geom::mesh::edge* ca = add_or_find_edge(c, a);
mesh->add_face({ab, bd, dc, ca});
}
}
return mesh;
}
} // namespace meshes
} // namespace geom

+ 51
- 44
src/engine/geom/morton.hpp View File

@ -24,9 +24,6 @@
namespace geom {
/// Morton location code encoding and decoding functions.
namespace morton {
/**
* Encodes 2D coordinates as a Morton location code.
*
@ -36,18 +33,24 @@ namespace morton {
* @return Morton location code.
*/
template <std::unsigned_integral T>
constexpr T encode(T x, T y) noexcept
constexpr T morton_encode(T x, T y) noexcept
{
auto expand = [](T x) -> T
{
x &= (1 << (sizeof(T) << 2)) - 1;
if constexpr(sizeof(T) >= 8)
{
x = (x ^ (x << 16)) & T(0x0000ffff0000ffff);
}
if constexpr(sizeof(T) >= 4)
{
x = (x ^ (x << 8)) & T(0x00ff00ff00ff00ff);
}
if constexpr(sizeof(T) >= 2)
{
x = (x ^ (x << 4)) & T(0x0f0f0f0f0f0f0f0f);
}
x = (x ^ (x << 2)) & T(0x3333333333333333);
x = (x ^ (x << 1)) & T(0x5555555555555555);
@ -68,38 +71,38 @@ constexpr T encode(T x, T y) noexcept
* @return Morton location code.
*/
template <std::unsigned_integral T>
constexpr T encode(T x, T y, T z) noexcept
constexpr T morton_encode(T x, T y, T z) noexcept
{
auto expand = [](T x) -> T
{
if constexpr(sizeof(T) == 1)
{
x &= 0x3;
x = (x | x << 2) & 0x9;
x &= T(0x3);
x = (x | x << 2) & T(0x9);
}
else if constexpr(sizeof(T) == 2)
{
x &= 0x001f;
x = (x | x << 8) & 0x100f;
x = (x | x << 4) & 0x10c3;
x = (x | x << 2) & 0x1249;
x &= T(0x001f);
x = (x | x << 8) & T(0x100f);
x = (x | x << 4) & T(0x10c3);
x = (x | x << 2) & T(0x1249);
}
else if constexpr(sizeof(T) == 4)
{
x &= 0x00003ff;
x = (x | x << 16) & 0x30000ff;
x = (x | x << 8) & 0x300f00f;
x = (x | x << 4) & 0x30c30c3;
x = (x | x << 2) & 0x9249249;
x &= T(0x00003ff);
x = (x | x << 16) & T(0x30000ff);
x = (x | x << 8) & T(0x300f00f);
x = (x | x << 4) & T(0x30c30c3);
x = (x | x << 2) & T(0x9249249);
}
else if constexpr(sizeof(T) == 8)
{
x &= 0x00000000001fffff;
x = (x | x << 32) & 0x001f00000000ffff;
x = (x | x << 16) & 0x001f0000ff0000ff;
x = (x | x << 8) & 0x100f00f00f00f00f;
x = (x | x << 4) & 0x10c30c30c30c30c3;
x = (x | x << 2) & 0x1249249249249249;
x &= T(0x00000000001fffff);
x = (x | x << 32) & T(0x001f00000000ffff);
x = (x | x << 16) & T(0x001f0000ff0000ff);
x = (x | x << 8) & T(0x100f00f00f00f00f);
x = (x | x << 4) & T(0x10c30c30c30c30c3);
x = (x | x << 2) & T(0x1249249249249249);
}
return x;
@ -116,21 +119,26 @@ constexpr T encode(T x, T y, T z) noexcept
* @param[out] y Decoded y-coordinate.
*/
template <std::unsigned_integral T>
void decode(T code, T& x, T& y) noexcept
void morton_decode(T code, T& x, T& y) noexcept
{
auto compress = [](T x) -> T
{
x &= T(0x5555555555555555);
x &= T(0x5555555555555555);
x = (x ^ (x >> 1)) & T(0x3333333333333333);
x = (x ^ (x >> 2)) & T(0x0f0f0f0f0f0f0f0f);
if constexpr(sizeof(T) >= 2)
{
x = (x ^ (x >> 4)) & T(0x00ff00ff00ff00ff);
}
if constexpr(sizeof(T) >= 4)
{
x = (x ^ (x >> 8)) & T(0x0000ffff0000ffff);
}
if constexpr(sizeof(T) >= 8)
{
x = (x ^ (x >> 16)) & T(0x00000000ffffffff);
}
return x;
};
@ -148,38 +156,38 @@ void decode(T code, T& x, T& y) noexcept
* @param[out] z Decoded z-coordinate.
*/
template <std::unsigned_integral T>
void decode(T code, T& x, T& y, T& z) noexcept
void morton_decode(T code, T& x, T& y, T& z) noexcept
{
auto compress = [](T x) -> T
{
if constexpr(sizeof(T) == 1)
{
x &= 0x9;
x = (x ^ x >> 2) & 0x3;
x &= T(0x9);
x = (x ^ x >> 2) & T(0x3);
}
else if constexpr(sizeof(T) == 2)
{
x &= 0x1249;
x = (x ^ x >> 2) & 0x10c3;
x = (x ^ x >> 4) & 0x100f;
x = (x ^ x >> 8) & 0x001f;
x &= T(0x1249);
x = (x ^ x >> 2) & T(0x10c3);
x = (x ^ x >> 4) & T(0x100f);
x = (x ^ x >> 8) & T(0x001f);
}
else if constexpr(sizeof(T) == 4)
{
x &= 0x9249249;
x = (x ^ x >> 2) & 0x30c30c3;
x = (x ^ x >> 4) & 0x300f00f;
x = (x ^ x >> 8) & 0x30000ff;
x = (x ^ x >> 16) & 0x00003ff;
x &= T(0x9249249);
x = (x ^ x >> 2) & T(0x30c30c3);
x = (x ^ x >> 4) & T(0x300f00f);
x = (x ^ x >> 8) & T(0x30000ff);
x = (x ^ x >> 16) & T(0x00003ff);
}
else if constexpr(sizeof(T) == 8)
{
x &= 0x1249249249249249;
x = (x ^ x >> 2) & 0x10c30c30c30c30c3;
x = (x ^ x >> 4) & 0x100f00f00f00f00f;
x = (x ^ x >> 8) & 0x001f0000ff0000ff;
x = (x ^ x >> 16) & 0x001f00000000ffff;
x = (x ^ x >> 32) & 0x00000000001fffff;
x &= T(0x1249249249249249);
x = (x ^ x >> 2) & T(0x10c30c30c30c30c3);
x = (x ^ x >> 4) & T(0x100f00f00f00f00f);
x = (x ^ x >> 8) & T(0x001f0000ff0000ff);
x = (x ^ x >> 16) & T(0x001f00000000ffff);
x = (x ^ x >> 32) & T(0x00000000001fffff);
}
return x;
@ -190,7 +198,6 @@ void decode(T code, T& x, T& y, T& z) noexcept
z = compress(code >> 2);
}
} // namespace morton
} // namespace geom
#endif // ANTKEEPER_GEOM_MORTON_HPP

+ 5
- 5
src/engine/geom/primitives/hyperrectangle.hpp View File

@ -22,7 +22,6 @@
#include <engine/math/vector.hpp>
#include <algorithm>
#include <cmath>
namespace geom {
namespace primitives {
@ -156,18 +155,19 @@ struct hyperrectangle
}
/**
* Returns `false` if any coordinates of `min` are greater than `max`.
* Returns `true` if any coordinates of `min` are greater than `max`, `false` otherwise.
*/
[[nodiscard]] constexpr bool valid() const noexcept
[[nodiscard]] constexpr bool degenerate() const noexcept
{
for (std::size_t i = 0; i < N; ++i)
{
if (min[i] > max[i])
{
return false;
return true;
}
}
return true;
return false;
}
/// Calculates the volume of the hyperrectangle.

+ 2
- 2
src/engine/geom/primitives/view-frustum.hpp View File

@ -38,13 +38,13 @@ template
struct view_frustum
{
/// Vector type.
using vector_type = math::vector<T, 3>;
using vector_type = math::vec3<T>;
/// Plane type.
using plane_type = geom::plane<T>;
/// View-projection matrix type.
using matrix_type = math::matrix<T, 4, 4>;
using matrix_type = math::mat4<T>;
/// Box type.
using box_type = geom::box<T>;

+ 1
- 1
src/engine/geom/projection.hpp View File

@ -25,7 +25,7 @@
namespace geom {
template <class T>
math::vector<T, 3> project_on_plane(const math::vector<T, 3>& v, const math::vector<T, 3>& p, const math::vector<T, 3>& n)
math::vec3<T> project_on_plane(const math::vec3<T>& v, const math::vec3<T>& p, const math::vec3<T>& n)
{
return v - n * math::dot(v - p, n);
}

+ 5
- 5
src/engine/geom/sdf.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_GEOM_SDF_HPP
#define ANTKEEPER_GEOM_SDF_HPP
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
#include <algorithm>
namespace geom {
@ -28,21 +28,21 @@ namespace geom {
/// Signed distance functions.
namespace sdf {
inline float3 translate(const float3& sample, const float3& offset)
inline math::fvec3 translate(const math::fvec3& sample, const math::fvec3& offset)
{
return sample - offset;
}
inline float sphere(const float3& p, float r)
inline float sphere(const math::fvec3& p, float r)
{
return math::length(p) - r;
}
inline float cylinder(const float3& p, float r, float h)
inline float cylinder(const math::fvec3& p, float r, float h)
{
float dx = std::abs(math::length(math::swizzle<0, 2>(p))) - r;
float dy = std::abs(p[1]) - h;
return std::min<float>(std::max<float>(dx, dy), 0.0f) + math::length(float2{std::max<float>(dx, 0.0f), std::max<float>(dy, 0.0f)});
return std::min<float>(std::max<float>(dx, dy), 0.0f) + math::length(math::fvec2{std::max<float>(dx, 0.0f), std::max<float>(dy, 0.0f)});
}
inline float op_union(float a, float b)

+ 4
- 4
src/engine/geom/spherical.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_GEOM_SPHERICAL_HPP
#define ANTKEEPER_GEOM_SPHERICAL_HPP
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
#include <cmath>
namespace geom {
@ -37,14 +37,14 @@ namespace spherical {
* @see geom::coordinates::cartesian
*/
template <class T>
math::vector3<T> to_cartesian(const math::vector3<T>& v);
math::vec3<T> to_cartesian(const math::vec3<T>& v);
template <class T>
math::vector3<T> to_cartesian(const math::vector3<T>& v)
math::vec3<T> to_cartesian(const math::vec3<T>& v)
{
const T x = v[0] * std::cos(v[1]);
return math::vector3<T>
return math::vec3<T>
{
x * std::cos(v[2]),
x * std::sin(v[2]),

+ 60
- 60
src/engine/gl/opengl/gl-shader-variables.cpp View File

@ -52,23 +52,23 @@ void gl_shader_bool::update(std::span values, std::size_t index) con
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data());
}
gl_shader_bool2::gl_shader_bool2(std::size_t size, GLint gl_uniform_location):
gl_shader_bvec2::gl_shader_bvec2(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location},
ivalues(size * 2)
{}
void gl_shader_bool2::update(const bool2& value) const noexcept
void gl_shader_bvec2::update(const math::bvec2& value) const noexcept
{
glUniform2i(gl_uniform_location, static_cast<GLint>(value[0]), static_cast<GLint>(value[1]));
}
void gl_shader_bool2::update(const bool2& value, std::size_t index) const
void gl_shader_bvec2::update(const math::bvec2& value, std::size_t index) const
{
glUniform2i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value[0]), static_cast<GLint>(value[1]));
}
void gl_shader_bool2::update(std::span<const bool2> values, std::size_t index) const
void gl_shader_bvec2::update(std::span<const math::bvec2> values, std::size_t index) const
{
GLint* ivalue = ivalues.data();
for (const auto& value: values)
@ -80,23 +80,23 @@ void gl_shader_bool2::update(std::span values, std::size_t index) c
glUniform2iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data());
}
gl_shader_bool3::gl_shader_bool3(std::size_t size, GLint gl_uniform_location):
gl_shader_bvec3::gl_shader_bvec3(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location},
ivalues(size * 3)
{}
void gl_shader_bool3::update(const bool3& value) const noexcept
void gl_shader_bvec3::update(const math::bvec3& value) const noexcept
{
glUniform3i(gl_uniform_location, static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2]));
}
void gl_shader_bool3::update(const bool3& value, std::size_t index) const
void gl_shader_bvec3::update(const math::bvec3& value, std::size_t index) const
{
glUniform3i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2]));
}
void gl_shader_bool3::update(std::span<const bool3> values, std::size_t index) const
void gl_shader_bvec3::update(std::span<const math::bvec3> values, std::size_t index) const
{
GLint* ivalue = ivalues.data();
for (const auto& value: values)
@ -109,23 +109,23 @@ void gl_shader_bool3::update(std::span values, std::size_t index) c
glUniform3iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), ivalues.data());
}
gl_shader_bool4::gl_shader_bool4(std::size_t size, GLint gl_uniform_location):
gl_shader_bvec4::gl_shader_bvec4(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location},
ivalues(size * 4)
{}
void gl_shader_bool4::update(const bool4& value) const noexcept
void gl_shader_bvec4::update(const math::bvec4& value) const noexcept
{
glUniform4i(gl_uniform_location, static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2]), static_cast<GLint>(value[3]));
}
void gl_shader_bool4::update(const bool4& value, std::size_t index) const
void gl_shader_bvec4::update(const math::bvec4& value, std::size_t index) const
{
glUniform4i(gl_uniform_location + static_cast<GLint>(index), static_cast<GLint>(value[0]), static_cast<GLint>(value[1]), static_cast<GLint>(value[2]), static_cast<GLint>(value[3]));
}
void gl_shader_bool4::update(std::span<const bool4> values, std::size_t index) const
void gl_shader_bvec4::update(std::span<const math::bvec4> values, std::size_t index) const
{
GLint* ivalue = ivalues.data();
for (const auto& value: values)
@ -159,62 +159,62 @@ void gl_shader_int::update(std::span values, std::size_t index) const
glUniform1iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data());
}
gl_shader_int2::gl_shader_int2(std::size_t size, GLint gl_uniform_location):
gl_shader_ivec2::gl_shader_ivec2(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_int2::update(const int2& value) const noexcept
void gl_shader_ivec2::update(const math::ivec2& value) const noexcept
{
glUniform2iv(gl_uniform_location, 1, value.data());
}
void gl_shader_int2::update(const int2& value, std::size_t index) const
void gl_shader_ivec2::update(const math::ivec2& value, std::size_t index) const
{
glUniform2iv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
}
void gl_shader_int2::update(std::span<const int2> values, std::size_t index) const
void gl_shader_ivec2::update(std::span<const math::ivec2> values, std::size_t index) const
{
glUniform2iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
}
gl_shader_int3::gl_shader_int3(std::size_t size, GLint gl_uniform_location):
gl_shader_ivec3::gl_shader_ivec3(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_int3::update(const int3& value) const noexcept
void gl_shader_ivec3::update(const math::ivec3& value) const noexcept
{
glUniform3iv(gl_uniform_location, 1, value.data());
}
void gl_shader_int3::update(const int3& value, std::size_t index) const
void gl_shader_ivec3::update(const math::ivec3& value, std::size_t index) const
{
glUniform3iv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
}
void gl_shader_int3::update(std::span<const int3> values, std::size_t index) const
void gl_shader_ivec3::update(std::span<const math::ivec3> values, std::size_t index) const
{
glUniform3iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
}
gl_shader_int4::gl_shader_int4(std::size_t size, GLint gl_uniform_location):
gl_shader_ivec4::gl_shader_ivec4(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_int4::update(const int4& value) const noexcept
void gl_shader_ivec4::update(const math::ivec4& value) const noexcept
{
glUniform4iv(gl_uniform_location, 1, value.data());
}
void gl_shader_int4::update(const int4& value, std::size_t index) const
void gl_shader_ivec4::update(const math::ivec4& value, std::size_t index) const
{
glUniform4iv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
}
void gl_shader_int4::update(std::span<const int4> values, std::size_t index) const
void gl_shader_ivec4::update(std::span<const math::ivec4> values, std::size_t index) const
{
glUniform4iv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
}
@ -239,62 +239,62 @@ void gl_shader_uint::update(std::span values, std::size_t in
glUniform1uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data());
}
gl_shader_uint2::gl_shader_uint2(std::size_t size, GLint gl_uniform_location):
gl_shader_uvec2::gl_shader_uvec2(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_uint2::update(const uint2& value) const noexcept
void gl_shader_uvec2::update(const math::uvec2& value) const noexcept
{
glUniform2uiv(gl_uniform_location, 1, value.data());
}
void gl_shader_uint2::update(const uint2& value, std::size_t index) const
void gl_shader_uvec2::update(const math::uvec2& value, std::size_t index) const
{
glUniform2uiv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
}
void gl_shader_uint2::update(std::span<const uint2> values, std::size_t index) const
void gl_shader_uvec2::update(std::span<const math::uvec2> values, std::size_t index) const
{
glUniform2uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
}
gl_shader_uint3::gl_shader_uint3(std::size_t size, GLint gl_uniform_location):
gl_shader_uvec3::gl_shader_uvec3(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_uint3::update(const uint3& value) const noexcept
void gl_shader_uvec3::update(const math::uvec3& value) const noexcept
{
glUniform3uiv(gl_uniform_location, 1, value.data());
}
void gl_shader_uint3::update(const uint3& value, std::size_t index) const
void gl_shader_uvec3::update(const math::uvec3& value, std::size_t index) const
{
glUniform3uiv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
}
void gl_shader_uint3::update(std::span<const uint3> values, std::size_t index) const
void gl_shader_uvec3::update(std::span<const math::uvec3> values, std::size_t index) const
{
glUniform3uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
}
gl_shader_uint4::gl_shader_uint4(std::size_t size, GLint gl_uniform_location):
gl_shader_uvec4::gl_shader_uvec4(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_uint4::update(const uint4& value) const noexcept
void gl_shader_uvec4::update(const math::uvec4& value) const noexcept
{
glUniform4uiv(gl_uniform_location, 1, value.data());
}
void gl_shader_uint4::update(const uint4& value, std::size_t index) const
void gl_shader_uvec4::update(const math::uvec4& value, std::size_t index) const
{
glUniform4uiv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
}
void gl_shader_uint4::update(std::span<const uint4> values, std::size_t index) const
void gl_shader_uvec4::update(std::span<const math::uvec4> values, std::size_t index) const
{
glUniform4uiv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
}
@ -319,122 +319,122 @@ void gl_shader_float::update(std::span values, std::size_t index) c
glUniform1fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data());
}
gl_shader_float2::gl_shader_float2(std::size_t size, GLint gl_uniform_location):
gl_shader_fvec2::gl_shader_fvec2(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_float2::update(const float2& value) const noexcept
void gl_shader_fvec2::update(const math::fvec2& value) const noexcept
{
glUniform2fv(gl_uniform_location, 1, value.data());
}
void gl_shader_float2::update(const float2& value, std::size_t index) const
void gl_shader_fvec2::update(const math::fvec2& value, std::size_t index) const
{
glUniform2fv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
}
void gl_shader_float2::update(std::span<const float2> values, std::size_t index) const
void gl_shader_fvec2::update(std::span<const math::fvec2> values, std::size_t index) const
{
glUniform2fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
}
gl_shader_float3::gl_shader_float3(std::size_t size, GLint gl_uniform_location):
gl_shader_fvec3::gl_shader_fvec3(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_float3::update(const float3& value) const noexcept
void gl_shader_fvec3::update(const math::fvec3& value) const noexcept
{
glUniform3fv(gl_uniform_location, 1, value.data());
}
void gl_shader_float3::update(const float3& value, std::size_t index) const
void gl_shader_fvec3::update(const math::fvec3& value, std::size_t index) const
{
glUniform3fv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
}
void gl_shader_float3::update(std::span<const float3> values, std::size_t index) const
void gl_shader_fvec3::update(std::span<const math::fvec3> values, std::size_t index) const
{
glUniform3fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
}
gl_shader_float4::gl_shader_float4(std::size_t size, GLint gl_uniform_location):
gl_shader_fvec4::gl_shader_fvec4(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_float4::update(const float4& value) const noexcept
void gl_shader_fvec4::update(const math::fvec4& value) const noexcept
{
glUniform4fv(gl_uniform_location, 1, value.data());
}
void gl_shader_float4::update(const float4& value, std::size_t index) const
void gl_shader_fvec4::update(const math::fvec4& value, std::size_t index) const
{
glUniform4fv(gl_uniform_location + static_cast<GLint>(index), 1, value.data());
}
void gl_shader_float4::update(std::span<const float4> values, std::size_t index) const
void gl_shader_fvec4::update(std::span<const math::fvec4> values, std::size_t index) const
{
glUniform4fv(gl_uniform_location + static_cast<GLint>(index), static_cast<GLsizei>(values.size()), values.data()->data());
}
gl_shader_float2x2::gl_shader_float2x2(std::size_t size, GLint gl_uniform_location):
gl_shader_fmat2::gl_shader_fmat2(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_float2x2::update(const float2x2& value) const noexcept
void gl_shader_fmat2::update(const math::fmat2& value) const noexcept
{
glUniformMatrix2fv(gl_uniform_location, 1, GL_FALSE, value.data());
}
void gl_shader_float2x2::update(const float2x2& value, std::size_t index) const
void gl_shader_fmat2::update(const math::fmat2& value, std::size_t index) const
{
glUniformMatrix2fv(gl_uniform_location + static_cast<GLint>(index) * 2, 1, GL_FALSE, value.data());
}
void gl_shader_float2x2::update(std::span<const float2x2> values, std::size_t index) const
void gl_shader_fmat2::update(std::span<const math::fmat2> values, std::size_t index) const
{
glUniformMatrix2fv(gl_uniform_location + static_cast<GLint>(index) * 2, static_cast<GLsizei>(values.size()), GL_FALSE, values.data()->data());
}
gl_shader_float3x3::gl_shader_float3x3(std::size_t size, GLint gl_uniform_location):
gl_shader_fmat3::gl_shader_fmat3(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_float3x3::update(const float3x3& value) const noexcept
void gl_shader_fmat3::update(const math::fmat3& value) const noexcept
{
glUniformMatrix3fv(gl_uniform_location, 1, GL_FALSE, value.data());
}
void gl_shader_float3x3::update(const float3x3& value, std::size_t index) const
void gl_shader_fmat3::update(const math::fmat3& value, std::size_t index) const
{
glUniformMatrix3fv(gl_uniform_location + static_cast<GLint>(index) * 3, 1, GL_FALSE, value.data());
}
void gl_shader_float3x3::update(std::span<const float3x3> values, std::size_t index) const
void gl_shader_fmat3::update(std::span<const math::fmat3> values, std::size_t index) const
{
glUniformMatrix3fv(gl_uniform_location + static_cast<GLint>(index) * 3, static_cast<GLsizei>(values.size()), GL_FALSE, values.data()->data());
}
gl_shader_float4x4::gl_shader_float4x4(std::size_t size, GLint gl_uniform_location):
gl_shader_fmat4::gl_shader_fmat4(std::size_t size, GLint gl_uniform_location):
shader_variable(size),
gl_uniform_location{gl_uniform_location}
{}
void gl_shader_float4x4::update(const float4x4& value) const noexcept
void gl_shader_fmat4::update(const math::fmat4& value) const noexcept
{
glUniformMatrix4fv(gl_uniform_location, 1, GL_FALSE, value.data());
}
void gl_shader_float4x4::update(const float4x4& value, std::size_t index) const
void gl_shader_fmat4::update(const math::fmat4& value, std::size_t index) const
{
glUniformMatrix4fv(gl_uniform_location + static_cast<GLint>(index) * 4, 1, GL_FALSE, value.data());
}
void gl_shader_float4x4::update(std::span<const float4x4> values, std::size_t index) const
void gl_shader_fmat4::update(std::span<const math::fmat4> values, std::size_t index) const
{
glUniformMatrix4fv(gl_uniform_location + static_cast<GLint>(index) * 4, static_cast<GLsizei>(values.size()), GL_FALSE, values.data()->data());
}

+ 94
- 94
src/engine/gl/opengl/gl-shader-variables.hpp View File

@ -36,7 +36,7 @@ public:
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::bool1;
return shader_variable_type::bvec1;
}
void update(bool value) const noexcept override;
@ -51,19 +51,19 @@ private:
/**
* 2-dimensional boolean vector shader variable implementation using OpenGL.
*/
class gl_shader_bool2: public shader_variable
class gl_shader_bvec2: public shader_variable
{
public:
gl_shader_bool2(std::size_t size, GLint gl_uniform_location);
gl_shader_bvec2(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::bool2;
return shader_variable_type::bvec2;
}
void update(const bool2& value) const noexcept override;
void update(const bool2& value, std::size_t index) const override;
void update(std::span<const bool2> values, std::size_t index = 0) const override;
void update(const math::bvec2& value) const noexcept override;
void update(const math::bvec2& value, std::size_t index) const override;
void update(std::span<const math::bvec2> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -73,19 +73,19 @@ private:
/**
* 3-dimensional boolean vector shader variable implementation using OpenGL.
*/
class gl_shader_bool3: public shader_variable
class gl_shader_bvec3: public shader_variable
{
public:
gl_shader_bool3(std::size_t size, GLint gl_uniform_location);
gl_shader_bvec3(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::bool3;
return shader_variable_type::bvec3;
}
void update(const bool3& value) const noexcept override;
void update(const bool3& value, std::size_t index) const override;
void update(std::span<const bool3> values, std::size_t index = 0) const override;
void update(const math::bvec3& value) const noexcept override;
void update(const math::bvec3& value, std::size_t index) const override;
void update(std::span<const math::bvec3> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -95,19 +95,19 @@ private:
/**
* 4-dimensional boolean vector shader variable implementation using OpenGL.
*/
class gl_shader_bool4: public shader_variable
class gl_shader_bvec4: public shader_variable
{
public:
gl_shader_bool4(std::size_t size, GLint gl_uniform_location);
gl_shader_bvec4(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::bool4;
return shader_variable_type::bvec4;
}
void update(const bool4& value) const noexcept override;
void update(const bool4& value, std::size_t index) const override;
void update(std::span<const bool4> values, std::size_t index = 0) const override;
void update(const math::bvec4& value) const noexcept override;
void update(const math::bvec4& value, std::size_t index) const override;
void update(std::span<const math::bvec4> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -124,7 +124,7 @@ public:
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::int1;
return shader_variable_type::ivec1;
}
void update(int value) const noexcept override;
@ -138,19 +138,19 @@ private:
/**
* 2-dimensional signed integer vector shader variable implementation using OpenGL.
*/
class gl_shader_int2: public shader_variable
class gl_shader_ivec2: public shader_variable
{
public:
gl_shader_int2(std::size_t size, GLint gl_uniform_location);
gl_shader_ivec2(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::int2;
return shader_variable_type::ivec2;
}
void update(const int2& value) const noexcept override;
void update(const int2& value, std::size_t index) const override;
void update(std::span<const int2> values, std::size_t index = 0) const override;
void update(const math::ivec2& value) const noexcept override;
void update(const math::ivec2& value, std::size_t index) const override;
void update(std::span<const math::ivec2> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -159,19 +159,19 @@ private:
/**
* 3-dimensional signed integer vector shader variable implementation using OpenGL.
*/
class gl_shader_int3: public shader_variable
class gl_shader_ivec3: public shader_variable
{
public:
gl_shader_int3(std::size_t size, GLint gl_uniform_location);
gl_shader_ivec3(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::int3;
return shader_variable_type::ivec3;
}
void update(const int3& value) const noexcept override;
void update(const int3& value, std::size_t index) const override;
void update(std::span<const int3> values, std::size_t index = 0) const override;
void update(const math::ivec3& value) const noexcept override;
void update(const math::ivec3& value, std::size_t index) const override;
void update(std::span<const math::ivec3> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -180,19 +180,19 @@ private:
/**
* 4-dimensional signed integer vector shader variable implementation using OpenGL.
*/
class gl_shader_int4: public shader_variable
class gl_shader_ivec4: public shader_variable
{
public:
gl_shader_int4(std::size_t size, GLint gl_uniform_location);
gl_shader_ivec4(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::int4;
return shader_variable_type::ivec4;
}
void update(const int4& value) const noexcept override;
void update(const int4& value, std::size_t index) const override;
void update(std::span<const int4> values, std::size_t index = 0) const override;
void update(const math::ivec4& value) const noexcept override;
void update(const math::ivec4& value, std::size_t index) const override;
void update(std::span<const math::ivec4> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -208,7 +208,7 @@ public:
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::uint1;
return shader_variable_type::uvec1;
}
void update(unsigned int value) const noexcept override;
@ -222,19 +222,19 @@ private:
/**
* 2-dimensional unsigned integer vector shader variable implementation using OpenGL.
*/
class gl_shader_uint2: public shader_variable
class gl_shader_uvec2: public shader_variable
{
public:
gl_shader_uint2(std::size_t size, GLint gl_uniform_location);
gl_shader_uvec2(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::uint2;
return shader_variable_type::uvec2;
}
void update(const uint2& value) const noexcept override;
void update(const uint2& value, std::size_t index) const override;
void update(std::span<const uint2> values, std::size_t index = 0) const override;
void update(const math::uvec2& value) const noexcept override;
void update(const math::uvec2& value, std::size_t index) const override;
void update(std::span<const math::uvec2> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -243,19 +243,19 @@ private:
/**
* 3-dimensional unsigned integer vector shader variable implementation using OpenGL.
*/
class gl_shader_uint3: public shader_variable
class gl_shader_uvec3: public shader_variable
{
public:
gl_shader_uint3(std::size_t size, GLint gl_uniform_location);
gl_shader_uvec3(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::uint3;
return shader_variable_type::uvec3;
}
void update(const uint3& value) const noexcept override;
void update(const uint3& value, std::size_t index) const override;
void update(std::span<const uint3> values, std::size_t index = 0) const override;
void update(const math::uvec3& value) const noexcept override;
void update(const math::uvec3& value, std::size_t index) const override;
void update(std::span<const math::uvec3> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -264,19 +264,19 @@ private:
/**
* 4-dimensional unsigned integer vector shader variable implementation using OpenGL.
*/
class gl_shader_uint4: public shader_variable
class gl_shader_uvec4: public shader_variable
{
public:
gl_shader_uint4(std::size_t size, GLint gl_uniform_location);
gl_shader_uvec4(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::uint4;
return shader_variable_type::uvec4;
}
void update(const uint4& value) const noexcept override;
void update(const uint4& value, std::size_t index) const override;
void update(std::span<const uint4> values, std::size_t index = 0) const override;
void update(const math::uvec4& value) const noexcept override;
void update(const math::uvec4& value, std::size_t index) const override;
void update(std::span<const math::uvec4> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -292,7 +292,7 @@ public:
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::float1;
return shader_variable_type::fvec1;
}
void update(float value) const noexcept override;
@ -306,19 +306,19 @@ private:
/**
* 2-dimensional floating-point vector shader variable implementation using OpenGL.
*/
class gl_shader_float2: public shader_variable
class gl_shader_fvec2: public shader_variable
{
public:
gl_shader_float2(std::size_t size, GLint gl_uniform_location);
gl_shader_fvec2(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::float2;
return shader_variable_type::fvec2;
}
void update(const float2& value) const noexcept override;
void update(const float2& value, std::size_t index) const override;
void update(std::span<const float2> values, std::size_t index = 0) const override;
void update(const math::fvec2& value) const noexcept override;
void update(const math::fvec2& value, std::size_t index) const override;
void update(std::span<const math::fvec2> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -327,19 +327,19 @@ private:
/**
* 3-dimensional floating-point vector shader variable implementation using OpenGL.
*/
class gl_shader_float3: public shader_variable
class gl_shader_fvec3: public shader_variable
{
public:
gl_shader_float3(std::size_t size, GLint gl_uniform_location);
gl_shader_fvec3(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::float3;
return shader_variable_type::fvec3;
}
void update(const float3& value) const noexcept override;
void update(const float3& value, std::size_t index) const override;
void update(std::span<const float3> values, std::size_t index = 0) const override;
void update(const math::fvec3& value) const noexcept override;
void update(const math::fvec3& value, std::size_t index) const override;
void update(std::span<const math::fvec3> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -348,19 +348,19 @@ private:
/**
* 4-dimensional floating-point vector shader variable implementation using OpenGL.
*/
class gl_shader_float4: public shader_variable
class gl_shader_fvec4: public shader_variable
{
public:
gl_shader_float4(std::size_t size, GLint gl_uniform_location);
gl_shader_fvec4(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::float4;
return shader_variable_type::fvec4;
}
void update(const float4& value) const noexcept override;
void update(const float4& value, std::size_t index) const override;
void update(std::span<const float4> values, std::size_t index = 0) const override;
void update(const math::fvec4& value) const noexcept override;
void update(const math::fvec4& value, std::size_t index) const override;
void update(std::span<const math::fvec4> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -369,19 +369,19 @@ private:
/**
* 2x2 floating-point matrix shader variable implementation using OpenGL.
*/
class gl_shader_float2x2: public shader_variable
class gl_shader_fmat2: public shader_variable
{
public:
gl_shader_float2x2(std::size_t size, GLint gl_uniform_location);
gl_shader_fmat2(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::float2x2;
return shader_variable_type::fmat2;
}
void update(const float2x2& value) const noexcept override;
void update(const float2x2& value, std::size_t index) const override;
void update(std::span<const float2x2> values, std::size_t index = 0) const override;
void update(const math::fmat2& value) const noexcept override;
void update(const math::fmat2& value, std::size_t index) const override;
void update(std::span<const math::fmat2> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -390,19 +390,19 @@ private:
/**
* 3x3 floating-point matrix shader variable implementation using OpenGL.
*/
class gl_shader_float3x3: public shader_variable
class gl_shader_fmat3: public shader_variable
{
public:
gl_shader_float3x3(std::size_t size, GLint gl_uniform_location);
gl_shader_fmat3(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::float3x3;
return shader_variable_type::fmat3;
}
void update(const float3x3& value) const noexcept override;
void update(const float3x3& value, std::size_t index) const override;
void update(std::span<const float3x3> values, std::size_t index = 0) const override;
void update(const math::fmat3& value) const noexcept override;
void update(const math::fmat3& value, std::size_t index) const override;
void update(std::span<const math::fmat3> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;
@ -411,19 +411,19 @@ private:
/**
* 4x4 floating-point matrix shader variable implementation using OpenGL.
*/
class gl_shader_float4x4: public shader_variable
class gl_shader_fmat4: public shader_variable
{
public:
gl_shader_float4x4(std::size_t size, GLint gl_uniform_location);
gl_shader_fmat4(std::size_t size, GLint gl_uniform_location);
[[nodiscard]] inline constexpr shader_variable_type type() const noexcept override
{
return shader_variable_type::float4x4;
return shader_variable_type::fmat4;
}
void update(const float4x4& value) const noexcept override;
void update(const float4x4& value, std::size_t index) const override;
void update(std::span<const float4x4> values, std::size_t index = 0) const override;
void update(const math::fmat4& value) const noexcept override;
void update(const math::fmat4& value, std::size_t index) const override;
void update(std::span<const math::fmat4> values, std::size_t index = 0) const override;
private:
GLint gl_uniform_location;

+ 15
- 15
src/engine/gl/shader-program.cpp View File

@ -234,62 +234,62 @@ void shader_program::load_variables()
variable = std::make_unique<const gl_shader_bool>(variable_size, uniform_location);
break;
case GL_BOOL_VEC2:
variable = std::make_unique<const gl_shader_bool2>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_bvec2>(variable_size, uniform_location);
break;
case GL_BOOL_VEC3:
variable = std::make_unique<const gl_shader_bool3>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_bvec3>(variable_size, uniform_location);
break;
case GL_BOOL_VEC4:
variable = std::make_unique<const gl_shader_bool4>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_bvec4>(variable_size, uniform_location);
break;
case GL_INT:
variable = std::make_unique<const gl_shader_int>(variable_size, uniform_location);
break;
case GL_INT_VEC2:
variable = std::make_unique<const gl_shader_int2>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_ivec2>(variable_size, uniform_location);
break;
case GL_INT_VEC3:
variable = std::make_unique<const gl_shader_int3>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_ivec3>(variable_size, uniform_location);
break;
case GL_INT_VEC4:
variable = std::make_unique<const gl_shader_int4>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_ivec4>(variable_size, uniform_location);
break;
case GL_UNSIGNED_INT:
variable = std::make_unique<const gl_shader_uint>(variable_size, uniform_location);
break;
case GL_UNSIGNED_INT_VEC2:
variable = std::make_unique<const gl_shader_uint2>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_uvec2>(variable_size, uniform_location);
break;
case GL_UNSIGNED_INT_VEC3:
variable = std::make_unique<const gl_shader_uint3>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_uvec3>(variable_size, uniform_location);
break;
case GL_UNSIGNED_INT_VEC4:
variable = std::make_unique<const gl_shader_uint4>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_uvec4>(variable_size, uniform_location);
break;
case GL_FLOAT:
variable = std::make_unique<const gl_shader_float>(variable_size, uniform_location);
break;
case GL_FLOAT_VEC2:
variable = std::make_unique<const gl_shader_float2>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_fvec2>(variable_size, uniform_location);
break;
case GL_FLOAT_VEC3:
variable = std::make_unique<const gl_shader_float3>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_fvec3>(variable_size, uniform_location);
break;
case GL_FLOAT_VEC4:
variable = std::make_unique<const gl_shader_float4>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_fvec4>(variable_size, uniform_location);
break;
case GL_FLOAT_MAT2:
variable = std::make_unique<const gl_shader_float2x2>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_fmat2>(variable_size, uniform_location);
break;
case GL_FLOAT_MAT3:
variable = std::make_unique<const gl_shader_float3x3>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_fmat3>(variable_size, uniform_location);
break;
case GL_FLOAT_MAT4:
variable = std::make_unique<const gl_shader_float4x4>(variable_size, uniform_location);
variable = std::make_unique<const gl_shader_fmat4>(variable_size, uniform_location);
break;
case GL_SAMPLER_1D:

+ 19
- 19
src/engine/gl/shader-variable-type.hpp View File

@ -29,25 +29,25 @@ namespace gl {
*/
enum class shader_variable_type: std::uint8_t
{
bool1,
bool2,
bool3,
bool4,
int1,
int2,
int3,
int4,
uint1,
uint2,
uint3,
uint4,
float1,
float2,
float3,
float4,
float2x2,
float3x3,
float4x4,
bvec1,
bvec2,
bvec3,
bvec4,
ivec1,
ivec2,
ivec3,
ivec4,
uvec1,
uvec2,
uvec3,
uvec4,
fvec1,
fvec2,
fvec3,
fvec4,
fmat2,
fmat3,
fmat4,
texture_1d,
texture_2d,
texture_3d,

+ 45
- 45
src/engine/gl/shader-variable.cpp View File

@ -33,17 +33,17 @@ void shader_variable::update(bool value) const
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const bool2& value) const
void shader_variable::update(const math::bvec2& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const bool3& value) const
void shader_variable::update(const math::bvec3& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const bool4& value) const
void shader_variable::update(const math::bvec4& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -53,17 +53,17 @@ void shader_variable::update(int value) const
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const int2& value) const
void shader_variable::update(const math::ivec2& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const int3& value) const
void shader_variable::update(const math::ivec3& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const int4& value) const
void shader_variable::update(const math::ivec4& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -73,17 +73,17 @@ void shader_variable::update(unsigned int value) const
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const uint2& value) const
void shader_variable::update(const math::uvec2& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const uint3& value) const
void shader_variable::update(const math::uvec3& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const uint4& value) const
void shader_variable::update(const math::uvec4& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -93,32 +93,32 @@ void shader_variable::update(float value) const
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float2& value) const
void shader_variable::update(const math::fvec2& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float3& value) const
void shader_variable::update(const math::fvec3& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float4& value) const
void shader_variable::update(const math::fvec4& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float2x2& value) const
void shader_variable::update(const math::fmat2& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float3x3& value) const
void shader_variable::update(const math::fmat3& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float4x4& value) const
void shader_variable::update(const math::fmat4& value) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -148,17 +148,17 @@ void shader_variable::update(bool value, std::size_t index) const
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const bool2& value, std::size_t index) const
void shader_variable::update(const math::bvec2& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const bool3& value, std::size_t index) const
void shader_variable::update(const math::bvec3& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const bool4& value, std::size_t index) const
void shader_variable::update(const math::bvec4& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -168,17 +168,17 @@ void shader_variable::update(int value, std::size_t index) const
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const int2& value, std::size_t index) const
void shader_variable::update(const math::ivec2& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const int3& value, std::size_t index) const
void shader_variable::update(const math::ivec3& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const int4& value, std::size_t index) const
void shader_variable::update(const math::ivec4& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -188,17 +188,17 @@ void shader_variable::update(unsigned int value, std::size_t index) const
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const uint2& value, std::size_t index) const
void shader_variable::update(const math::uvec2& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const uint3& value, std::size_t index) const
void shader_variable::update(const math::uvec3& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const uint4& value, std::size_t index) const
void shader_variable::update(const math::uvec4& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -208,32 +208,32 @@ void shader_variable::update(float value, std::size_t index) const
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float2& value, std::size_t index) const
void shader_variable::update(const math::fvec2& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float3& value, std::size_t index) const
void shader_variable::update(const math::fvec3& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float4& value, std::size_t index) const
void shader_variable::update(const math::fvec4& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float2x2& value, std::size_t index) const
void shader_variable::update(const math::fmat2& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float3x3& value, std::size_t index) const
void shader_variable::update(const math::fmat3& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(const float4x4& value, std::size_t index) const
void shader_variable::update(const math::fmat4& value, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -263,17 +263,17 @@ void shader_variable::update(std::span values, std::size_t index) co
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const bool2> values, std::size_t index) const
void shader_variable::update(std::span<const math::bvec2> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const bool3> values, std::size_t index) const
void shader_variable::update(std::span<const math::bvec3> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const bool4> values, std::size_t index) const
void shader_variable::update(std::span<const math::bvec4> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -283,17 +283,17 @@ void shader_variable::update(std::span values, std::size_t index) con
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const int2> values, std::size_t index) const
void shader_variable::update(std::span<const math::ivec2> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const int3> values, std::size_t index) const
void shader_variable::update(std::span<const math::ivec3> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const int4> values, std::size_t index) const
void shader_variable::update(std::span<const math::ivec4> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -303,17 +303,17 @@ void shader_variable::update(std::span values, std::size_t i
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const uint2> values, std::size_t index) const
void shader_variable::update(std::span<const math::uvec2> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const uint3> values, std::size_t index) const
void shader_variable::update(std::span<const math::uvec3> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const uint4> values, std::size_t index) const
void shader_variable::update(std::span<const math::uvec4> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
@ -323,32 +323,32 @@ void shader_variable::update(std::span values, std::size_t index) c
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const float2> values, std::size_t index) const
void shader_variable::update(std::span<const math::fvec2> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const float3> values, std::size_t index) const
void shader_variable::update(std::span<const math::fvec3> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const float4> values, std::size_t index) const
void shader_variable::update(std::span<const math::fvec4> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const float2x2> values, std::size_t index) const
void shader_variable::update(std::span<const math::fmat2> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const float3x3> values, std::size_t index) const
void shader_variable::update(std::span<const math::fmat3> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}
void shader_variable::update(std::span<const float4x4> values, std::size_t index) const
void shader_variable::update(std::span<const math::fmat4> values, std::size_t index) const
{
throw std::invalid_argument(type_mismatch_error);
}

+ 47
- 46
src/engine/gl/shader-variable.hpp View File

@ -20,7 +20,8 @@
#ifndef ANTKEEPER_GL_SHADER_INPUT_HPP
#define ANTKEEPER_GL_SHADER_INPUT_HPP
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
#include <engine/math/matrix.hpp>
#include <engine/gl/shader-variable-type.hpp>
#include <cstdint>
#include <span>
@ -61,28 +62,28 @@ public:
*/
///@{
virtual void update(bool value) const;
virtual void update(const bool2& value) const;
virtual void update(const bool3& value) const;
virtual void update(const bool4& value) const;
virtual void update(const math::bvec2& value) const;
virtual void update(const math::bvec3& value) const;
virtual void update(const math::bvec4& value) const;
virtual void update(int value) const;
virtual void update(const int2& value) const;
virtual void update(const int3& value) const;
virtual void update(const int4& value) const;
virtual void update(const math::ivec2& value) const;
virtual void update(const math::ivec3& value) const;
virtual void update(const math::ivec4& value) const;
virtual void update(unsigned int value) const;
virtual void update(const uint2& value) const;
virtual void update(const uint3& value) const;
virtual void update(const uint4& value) const;
virtual void update(const math::uvec2& value) const;
virtual void update(const math::uvec3& value) const;
virtual void update(const math::uvec4& value) const;
virtual void update(float value) const;
virtual void update(const float2& value) const;
virtual void update(const float3& value) const;
virtual void update(const float4& value) const;
virtual void update(const math::fvec2& value) const;
virtual void update(const math::fvec3& value) const;
virtual void update(const math::fvec4& value) const;
virtual void update(const float2x2& value) const;
virtual void update(const float3x3& value) const;
virtual void update(const float4x4& value) const;
virtual void update(const math::fmat2& value) const;
virtual void update(const math::fmat3& value) const;
virtual void update(const math::fmat4& value) const;
virtual void update(const texture_1d& value) const;
virtual void update(const texture_2d& value) const;
@ -100,28 +101,28 @@ public:
*/
/// @{
virtual void update(bool value, std::size_t index) const;
virtual void update(const bool2& value, std::size_t index) const;
virtual void update(const bool3& value, std::size_t index) const;
virtual void update(const bool4& value, std::size_t index) const;
virtual void update(const math::bvec2& value, std::size_t index) const;
virtual void update(const math::bvec3& value, std::size_t index) const;
virtual void update(const math::bvec4& value, std::size_t index) const;
virtual void update(int value, std::size_t index) const;
virtual void update(const int2& value, std::size_t index) const;
virtual void update(const int3& value, std::size_t index) const;
virtual void update(const int4& value, std::size_t index) const;
virtual void update(const math::ivec2& value, std::size_t index) const;
virtual void update(const math::ivec3& value, std::size_t index) const;
virtual void update(const math::ivec4& value, std::size_t index) const;
virtual void update(unsigned int value, std::size_t index) const;
virtual void update(const uint2& value, std::size_t index) const;
virtual void update(const uint3& value, std::size_t index) const;
virtual void update(const uint4& value, std::size_t index) const;
virtual void update(const math::uvec2& value, std::size_t index) const;
virtual void update(const math::uvec3& value, std::size_t index) const;
virtual void update(const math::uvec4& value, std::size_t index) const;
virtual void update(float value, std::size_t index) const;
virtual void update(const float2& value, std::size_t index) const;
virtual void update(const float3& value, std::size_t index) const;
virtual void update(const float4& value, std::size_t index) const;
virtual void update(const math::fvec2& value, std::size_t index) const;
virtual void update(const math::fvec3& value, std::size_t index) const;
virtual void update(const math::fvec4& value, std::size_t index) const;
virtual void update(const float2x2& value, std::size_t index) const;
virtual void update(const float3x3& value, std::size_t index) const;
virtual void update(const float4x4& value, std::size_t index) const;
virtual void update(const math::fmat2& value, std::size_t index) const;
virtual void update(const math::fmat3& value, std::size_t index) const;
virtual void update(const math::fmat4& value, std::size_t index) const;
virtual void update(const texture_1d& value, std::size_t index) const;
virtual void update(const texture_2d& value, std::size_t index) const;
@ -139,28 +140,28 @@ public:
*/
///@{
virtual void update(std::span<const bool> values, std::size_t index = 0) const;
virtual void update(std::span<const bool2> values, std::size_t index = 0) const;
virtual void update(std::span<const bool3> values, std::size_t index = 0) const;
virtual void update(std::span<const bool4> values, std::size_t index = 0) const;
virtual void update(std::span<const math::bvec2> values, std::size_t index = 0) const;
virtual void update(std::span<const math::bvec3> values, std::size_t index = 0) const;
virtual void update(std::span<const math::bvec4> values, std::size_t index = 0) const;
virtual void update(std::span<const int> values, std::size_t index = 0) const;
virtual void update(std::span<const int2> values, std::size_t index = 0) const;
virtual void update(std::span<const int3> values, std::size_t index = 0) const;
virtual void update(std::span<const int4> values, std::size_t index = 0) const;
virtual void update(std::span<const math::ivec2> values, std::size_t index = 0) const;
virtual void update(std::span<const math::ivec3> values, std::size_t index = 0) const;
virtual void update(std::span<const math::ivec4> values, std::size_t index = 0) const;
virtual void update(std::span<const unsigned int> values, std::size_t index = 0) const;
virtual void update(std::span<const uint2> values, std::size_t index = 0) const;
virtual void update(std::span<const uint3> values, std::size_t index = 0) const;
virtual void update(std::span<const uint4> values, std::size_t index = 0) const;
virtual void update(std::span<const math::uvec2> values, std::size_t index = 0) const;
virtual void update(std::span<const math::uvec3> values, std::size_t index = 0) const;
virtual void update(std::span<const math::uvec4> values, std::size_t index = 0) const;
virtual void update(std::span<const float> values, std::size_t index = 0) const;
virtual void update(std::span<const float2> values, std::size_t index = 0) const;
virtual void update(std::span<const float3> values, std::size_t index = 0) const;
virtual void update(std::span<const float4> values, std::size_t index = 0) const;
virtual void update(std::span<const math::fvec2> values, std::size_t index = 0) const;
virtual void update(std::span<const math::fvec3> values, std::size_t index = 0) const;
virtual void update(std::span<const math::fvec4> values, std::size_t index = 0) const;
virtual void update(std::span<const float2x2> values, std::size_t index = 0) const;
virtual void update(std::span<const float3x3> values, std::size_t index = 0) const;
virtual void update(std::span<const float4x4> values, std::size_t index = 0) const;
virtual void update(std::span<const math::fmat2> values, std::size_t index = 0) const;
virtual void update(std::span<const math::fmat3> values, std::size_t index = 0) const;
virtual void update(std::span<const math::fmat4> values, std::size_t index = 0) const;
virtual void update(std::span<const texture_1d* const> values, std::size_t index = 0) const;
virtual void update(std::span<const texture_2d* const> values, std::size_t index = 0) const;

+ 6
- 6
src/engine/input/mouse-events.hpp View File

@ -39,10 +39,10 @@ struct mouse_moved_event
mouse* mouse{nullptr};
/// Mouse position, in pixels, relative to the window.
math::vector<std::int32_t, 2> position{0, 0};
math::vec2<std::int32_t> position{0, 0};
/// Relative movement of the mouse, in pixels.
math::vector<std::int32_t, 2> difference{0, 0};
math::vec2<std::int32_t> difference{0, 0};
};
/**
@ -54,7 +54,7 @@ struct mouse_button_pressed_event
mouse* mouse{nullptr};
/// Mouse position, in pixels, relative to the window, when the button was pressed.
math::vector<std::int32_t, 2> position{0, 0};
math::vec2<std::int32_t> position{0, 0};
/// Mouse button being pressed.
mouse_button button{0};
@ -69,7 +69,7 @@ struct mouse_button_released_event
mouse* mouse{nullptr};
/// Mouse position, in pixels, relative to the window, when the button was released.
math::vector<std::int32_t, 2> position{0, 0};
math::vec2<std::int32_t> position{0, 0};
/// Mouse button being released.
mouse_button button{0};
@ -84,10 +84,10 @@ struct mouse_scrolled_event
mouse* mouse{nullptr};
/// Mouse position, in pixels, relative to the window, when the mouse was scrolled.
math::vector<std::int32_t, 2> position{0, 0};
math::vec2<std::int32_t> position{0, 0};
/// Scroll velocity.
math::vector<float, 2> velocity{0.0f, 0.0f};
math::fvec2 velocity{0.0f, 0.0f};
};
} // namespace input

+ 2
- 2
src/engine/input/mouse.cpp View File

@ -31,13 +31,13 @@ void mouse::release(mouse_button button)
button_released_publisher.publish({this, position, button});
}
void mouse::move(const math::vector<std::int32_t, 2>& position, const math::vector<std::int32_t, 2>& difference)
void mouse::move(const math::vec2<std::int32_t>& position, const math::vec2<std::int32_t>& difference)
{
this->position = position;
moved_publisher.publish({this, position, difference});
}
void mouse::scroll(const math::vector<float, 2>& velocity)
void mouse::scroll(const math::fvec2& velocity)
{
scrolled_publisher.publish({this, position, velocity});
}

+ 4
- 4
src/engine/input/mouse.hpp View File

@ -55,17 +55,17 @@ public:
* @param position Mouse position, in pixels, relative to the window.
* @param difference Relative movement of the mouse, in pixels.
*/
void move(const math::vector<std::int32_t, 2>& position, const math::vector<std::int32_t, 2>& difference);
void move(const math::vec2<std::int32_t>& position, const math::vec2<std::int32_t>& difference);
/**
* Simulates mouse scrolling.
*
* @param velocity Scroll velocity.
*/
void scroll(const math::vector<float, 2>& velocity);
void scroll(const math::fvec2& velocity);
/// Returns the current mouse position, in pixels, relative to the window.
[[nodiscard]] inline const math::vector<std::int32_t, 2>& get_position() const noexcept
[[nodiscard]] inline const math::vec2<std::int32_t>& get_position() const noexcept
{
return position;
}
@ -101,7 +101,7 @@ public:
}
private:
math::vector<std::int32_t, 2> position{0, 0};
math::vec2<std::int32_t> position{0, 0};
::event::publisher<mouse_button_pressed_event> button_pressed_publisher;
::event::publisher<mouse_button_released_event> button_released_publisher;

+ 0
- 217
src/engine/math/glsl.hpp View File

@ -1,217 +0,0 @@
/*
* Copyright (C) 2023 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_MATH_GLSL_HPP
#define ANTKEEPER_MATH_GLSL_HPP
#include <engine/math/vector.hpp>
#include <engine/math/matrix.hpp>
#include <engine/math/quaternion.hpp>
namespace math {
namespace glsl {
/**
* Linear algebra data types with GLSL naming conventions.
*/
namespace types
{
/// @name Vector types
/// @{
/**
* *n*-dimensional vector of booleans.
*
* @tparam N Number of elements
*/
/// @{
template <std::size_t N>
using bvec = math::vector<bool, N>;
using bvec2 = bvec<2>;
using bvec3 = bvec<3>;
using bvec4 = bvec<4>;
/// @}
/**
* *n*-dimensional vector of signed integers.
*
* @tparam N Number of elements
*/
/// @{
template <std::size_t N>
using ivec = math::vector<int, N>;
using ivec2 = ivec<2>;
using ivec3 = ivec<3>;
using ivec4 = ivec<4>;
/// @}
/**
* *n*-dimensional vector of unsigned integers.
*
* @tparam N Number of elements
*/
/// @{
template <std::size_t N>
using uvec = math::vector<unsigned int, N>;
using uvec2 = uvec<2>;
using uvec3 = uvec<3>;
using uvec4 = uvec<4>;
/// @}
/**
* *n*-dimensional vector of floating-point numbers.
*
* @tparam N Number of elements
*/
/// @{
template <std::size_t N>
using fvec = math::vector<float, N>;
using fvec2 = fvec<2>;
using fvec3 = fvec<3>;
using fvec4 = fvec<4>;
using vec2 = fvec2;
using vec3 = fvec3;
using vec4 = fvec4;
/// @}
/**
* *n*-dimensional vector of double-precision floating-point numbers.
*
* @tparam N Number of elements
*/
/// @{
template <std::size_t N>
using dvec = math::vector<double, N>;
using dvec2 = dvec<2>;
using dvec3 = dvec<3>;
using dvec4 = dvec<4>;
/// @}
/// @}
/// @name Matrix types
/// @{
/**
* *n* by *m* matrix of floating-point numbers.
*
* @tparam N Number of columns.
* @tparam M Number of rows.
*/
/// @{
template <std::size_t N, std::size_t M>
using fmat = math::matrix<float, N, M>;
using fmat2x2 = fmat<2, 2>;
using fmat2x3 = fmat<2, 3>;
using fmat2x4 = fmat<2, 4>;
using fmat3x2 = fmat<3, 2>;
using fmat3x3 = fmat<3, 3>;
using fmat3x4 = fmat<3, 4>;
using fmat4x2 = fmat<4, 2>;
using fmat4x3 = fmat<4, 3>;
using fmat4x4 = fmat<4, 4>;
using mat2x2 = fmat2x2;
using mat2x3 = fmat2x3;
using mat2x4 = fmat2x4;
using mat3x2 = fmat3x2;
using mat3x3 = fmat3x3;
using mat3x4 = fmat3x4;
using mat4x2 = fmat4x2;
using mat4x3 = fmat4x3;
using mat4x4 = fmat4x4;
/// @}
/**
* *n* by *n* square matrix of floating-point numbers.
*
* @tparam N Number of columns and rows.
*/
/// @{
using fmat2 = fmat2x2;
using fmat3 = fmat3x3;
using fmat4 = fmat4x4;
using mat2 = fmat2;
using mat3 = fmat3;
using mat4 = fmat4;
/// @}
/**
* *n* by *m* matrix of double-precision floating-point numbers.
*
* @tparam N Number of columns.
* @tparam M Number of rows.
*/
/// @{
template <std::size_t N, std::size_t M>
using dmat = math::matrix<double, N, M>;
using dmat2x2 = dmat<2, 2>;
using dmat2x3 = dmat<2, 3>;
using dmat2x4 = dmat<2, 4>;
using dmat3x2 = dmat<3, 2>;
using dmat3x3 = dmat<3, 3>;
using dmat3x4 = dmat<3, 4>;
using dmat4x2 = dmat<4, 2>;
using dmat4x3 = dmat<4, 3>;
using dmat4x4 = dmat<4, 4>;
/// @}
/**
* *n* by *n* square matrix of double-precision floating-point numbers.
*
* @tparam N Number of columns and rows.
*/
/// @{
using dmat2 = dmat2x2;
using dmat3 = dmat3x3;
using dmat4 = dmat4x4;
/// @}
/// @}
/// @name Quaternion types
/// @{
/**
* Quaternion with floating-point scalars.
*
* @tparam T Scalar type.
*/
/// @{
using fquat = math::quaternion<float>;
using quat = fquat;
/// @}
/**
* Quaternion with double-precision floating-point scalars.
*
* @tparam T Scalar type.
*/
using dquat = math::quaternion<double>;
/// @}
} // namespace types
// Bring GLSL types into glsl namespace
using namespace types;
} // namespace glsl
} // namespace math
#endif // ANTKEEPER_MATH_GLSL_HPP

+ 122
- 40
src/engine/math/matrix.hpp View File

@ -28,6 +28,9 @@
namespace math {
/// Matrix types.
namespace matrix_types {
/**
* *n* by *m* column-major matrix.
*
@ -356,29 +359,107 @@ struct matrix
/// @}
};
/// 2x2 matrix.
/**
* *n* by *m* matrix.
*
* @tparam T Element type.
*/
/// @{
template <class T>
using matrix2 = matrix<T, 2, 2>;
/// 2x2 matrix.
using mat2x2 = matrix<T, 2, 2>;
template <class T>
using matrix2x2 = matrix<T, 2, 2>;
/// 3x3 matrix.
using mat2x3 = matrix<T, 2, 3>;
template <class T>
using matrix3 = matrix<T, 3, 3>;
/// 3x3 matrix.
using mat2x4 = matrix<T, 2, 4>;
template <class T>
using matrix3x3 = matrix<T, 3, 3>;
/// 4x4 matrix.
using mat3x2 = matrix<T, 3, 2>;
template <class T>
using mat3x3 = matrix<T, 3, 3>;
template <class T>
using mat3x4 = matrix<T, 3, 4>;
template <class T>
using matrix4 = matrix<T, 4, 4>;
using mat4x2 = matrix<T, 4, 2>;
template <class T>
using mat4x3 = matrix<T, 4, 3>;
template <class T>
using mat4x4 = matrix<T, 4, 4>;
/// @}
/// 4x4 matrix.
/**
* *n* by *n* square matrix.
*
* @tparam T Element type.
*/
/// @{
template <class T>
using mat2 = mat2x2<T>;
template <class T>
using matrix4x4 = matrix<T, 4, 4>;
using mat3 = mat3x3<T>;
template <class T>
using mat4 = mat4x4<T>;
/// @}
/**
* *n* by *m* matrix of single-precision floating-point numbers.
*
* @tparam N Number of columns.
* @tparam M Number of rows.
*/
/// @{
template <std::size_t N, std::size_t M>
using fmat = matrix<float, N, M>;
using fmat2x2 = fmat<2, 2>;
using fmat2x3 = fmat<2, 3>;
using fmat2x4 = fmat<2, 4>;
using fmat3x2 = fmat<3, 2>;
using fmat3x3 = fmat<3, 3>;
using fmat3x4 = fmat<3, 4>;
using fmat4x2 = fmat<4, 2>;
using fmat4x3 = fmat<4, 3>;
using fmat4x4 = fmat<4, 4>;
/// @}
/// *n* by *n* square matrix of single-precision floating-point numbers.
/// @{
using fmat2 = fmat2x2;
using fmat3 = fmat3x3;
using fmat4 = fmat4x4;
/// @}
/**
* *n* by *m* matrix of double-precision floating-point numbers.
*
* @tparam N Number of columns.
* @tparam M Number of rows.
*/
/// @{
template <std::size_t N, std::size_t M>
using dmat = matrix<double, N, M>;
using dmat2x2 = dmat<2, 2>;
using dmat2x3 = dmat<2, 3>;
using dmat2x4 = dmat<2, 4>;
using dmat3x2 = dmat<3, 2>;
using dmat3x3 = dmat<3, 3>;
using dmat3x4 = dmat<3, 4>;
using dmat4x2 = dmat<4, 2>;
using dmat4x3 = dmat<4, 3>;
using dmat4x4 = dmat<4, 4>;
/// @}
/// *n* by *n* square matrix of double-precision floating-point numbers.
/// @{
using dmat2 = dmat2x2;
using dmat3 = dmat3x3;
using dmat4 = dmat4x4;
/// @}
} // namespace matrix_types
// Bring matrix types into math namespace
using namespace matrix_types;
// Bring matrix types into math::types namespace
namespace types { using namespace matrix_types; }
/**
* Adds two matrices.
@ -472,13 +553,13 @@ template
*/
/// @{
template<std::size_t I, class T, std::size_t N, std::size_t M>
[[nodiscard]] constexpr typename matrix<T, N, M>::column_vector_type& get(math::matrix<T, N, M>& m) noexcept;
[[nodiscard]] constexpr typename matrix<T, N, M>::column_vector_type& get(matrix<T, N, M>& m) noexcept;
template<std::size_t I, class T, std::size_t N, std::size_t M>
[[nodiscard]] constexpr typename matrix<T, N, M>::column_vector_type&& get(math::matrix<T, N, M>&& m) noexcept;
[[nodiscard]] constexpr typename matrix<T, N, M>::column_vector_type&& get(matrix<T, N, M>&& m) noexcept;
template<std::size_t I, class T, std::size_t N, std::size_t M>
[[nodiscard]] constexpr const typename matrix<T, N, M>::column_vector_type& get(const math::matrix<T, N, M>& m) noexcept;
[[nodiscard]] constexpr const typename matrix<T, N, M>::column_vector_type& get(const matrix<T, N, M>& m) noexcept;
template<std::size_t I, class T, std::size_t N, std::size_t M>
[[nodiscard]] constexpr const typename matrix<T, N, M>::column_vector_type&& get(const math::matrix<T, N, M>&& m) noexcept;
[[nodiscard]] constexpr const typename matrix<T, N, M>::column_vector_type&& get(const matrix<T, N, M>&& m) noexcept;
/// @}
/**
@ -563,7 +644,7 @@ template
* @return Rotation matrix.
*/
template <class T>
[[nodiscard]] matrix<T, 3, 3> rotate(T angle, const vector<T, 3>& axis);
[[nodiscard]] mat3<T> rotate(T angle, const vector<T, 3>& axis);
/**
* Produces a matrix which rotates Cartesian coordinates about the x-axis by a given angle.
@ -573,7 +654,7 @@ template
* @return Rotation matrix.
*/
template <class T>
[[nodiscard]] matrix3<T> rotate_x(T angle);
[[nodiscard]] mat3<T> rotate_x(T angle);
/**
* Produces a matrix which rotates Cartesian coordinates about the y-axis by a given angle.
@ -583,7 +664,7 @@ template
* @return Rotation matrix.
*/
template <class T>
[[nodiscard]] matrix3<T> rotate_y(T angle);
[[nodiscard]] mat3<T> rotate_y(T angle);
/**
* Produces a matrix which rotates Cartesian coordinates about the z-axis by a given angle.
@ -593,7 +674,7 @@ template
* @return Rotation matrix.
*/
template <class T>
[[nodiscard]] matrix3<T> rotate_z(T angle);
[[nodiscard]] mat3<T> rotate_z(T angle);
/**
* Scales a matrix.
@ -707,7 +788,7 @@ constexpr T determinant(const matrix& m) noexcept
/// @private
template <class T>
constexpr T determinant(const matrix<T, 3, 3>& m) noexcept
constexpr T determinant(const mat3<T>& m) noexcept
{
return
m[0][0] * m[1][1] * m[2][2] +
@ -790,28 +871,28 @@ constexpr matrix div(T a, const matrix& b) noexcept
}
template<std::size_t I, class T, std::size_t N, std::size_t M>
inline constexpr typename matrix<T, N, M>::column_vector_type& get(math::matrix<T, N, M>& m) noexcept
inline constexpr typename matrix<T, N, M>::column_vector_type& get(matrix<T, N, M>& m) noexcept
{
static_assert(I < N);
return m.columns[I];
}
template<std::size_t I, class T, std::size_t N, std::size_t M>
inline constexpr typename matrix<T, N, M>::column_vector_type&& get(math::matrix<T, N, M>&& m) noexcept
inline constexpr typename matrix<T, N, M>::column_vector_type&& get(matrix<T, N, M>&& m) noexcept
{
static_assert(I < N);
return std::move(m.columns[I]);
}
template<std::size_t I, class T, std::size_t N, std::size_t M>
inline constexpr const typename matrix<T, N, M>::column_vector_type& get(const math::matrix<T, N, M>& m) noexcept
inline constexpr const typename matrix<T, N, M>::column_vector_type& get(const matrix<T, N, M>& m) noexcept
{
static_assert(I < N);
return m.columns[I];
}
template<std::size_t I, class T, std::size_t N, std::size_t M>
inline constexpr const typename matrix<T, N, M>::column_vector_type&& get(const math::matrix<T, N, M>&& m) noexcept
inline constexpr const typename matrix<T, N, M>::column_vector_type&& get(const matrix<T, N, M>&& m) noexcept
{
static_assert(I < N);
return std::move(m.columns[I]);
@ -834,7 +915,7 @@ constexpr matrix inverse(const matrix& m) noexcept
/// @private
template <class T>
constexpr matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m) noexcept
constexpr mat3<T> inverse(const mat3<T>& m) noexcept
{
const T inv_det = T{1} / determinant(m);
@ -961,13 +1042,13 @@ constexpr typename matrix::row_vector_type mul(const typename matrix
}
template <class T>
matrix<T, 3, 3> rotate(T angle, const vector<T, 3>& axis)
mat3<T> rotate(T angle, const vector<T, 3>& axis)
{
const T c = std::cos(angle);
const T s = std::sin(angle);
const vector<T, 3> temp = mul(axis, T{1} - c);
matrix<T, 3, 3> rotation;
mat3<T> rotation;
rotation[0][0] = axis[0] * temp[0] + c;
rotation[0][1] = axis[1] * temp[0] + axis[2] * s;
rotation[0][2] = axis[2] * temp[0] - axis[1] * s;
@ -982,12 +1063,12 @@ matrix rotate(T angle, const vector& axis)
}
template <class T>
matrix3<T> rotate_x(T angle)
mat3<T> rotate_x(T angle)
{
const T c = std::cos(angle);
const T s = std::sin(angle);
return matrix3<T>
return mat3<T>
{
T{1}, T{0}, T{0},
T{0}, c, s,
@ -996,12 +1077,12 @@ matrix3 rotate_x(T angle)
}
template <class T>
matrix3<T> rotate_y(T angle)
mat3<T> rotate_y(T angle)
{
const T c = std::cos(angle);
const T s = std::sin(angle);
return matrix3<T>
return mat3<T>
{
c, T{0}, -s,
T{0}, T{1}, T{0},
@ -1010,12 +1091,12 @@ matrix3 rotate_y(T angle)
}
template <class T>
matrix3<T> rotate_z(T angle)
mat3<T> rotate_z(T angle)
{
const T c = std::cos(angle);
const T s = std::sin(angle);
return matrix3<T>
return mat3<T>
{
c, s, T{0},
-s, c, T{0},
@ -1311,13 +1392,14 @@ inline constexpr matrix& operator/=(matrix& a, T b) noexcept
} // namespace math
// Bring matrix operators into global namespace
using namespace math::operators;
// Structured binding support
namespace std
{
/**
* Provides access to the number of columns in a math::matrix as a compile-time constant expression.
* Provides access to the number of columns in a matrix as a compile-time constant expression.
*
* @tparam T Element type.
* @tparam N Number of columns.
@ -1331,7 +1413,7 @@ namespace std
};
/**
* Provides compile-time indexed access to the type of the columns in a math::matrix using a tuple-like interface.
* Provides compile-time indexed access to the type of the columns in a matrix using a tuple-like interface.
*
* @tparam I Index of a column.
* @tparam T Element type.

+ 54
- 24
src/engine/math/quaternion.hpp View File

@ -27,6 +27,9 @@
namespace math {
/// Quaternion types.
namespace quaternion_types {
/**
* Quaternion composed of a real scalar part and imaginary vector part.
*
@ -39,10 +42,10 @@ struct quaternion
using scalar_type = T;
/// Vector type.
using vector_type = vector<T, 3>;
using vector_type = vec3<T>;
/// Rotation matrix type.
using matrix_type = matrix<T, 3, 3>;
using matrix_type = mat3<T>;
/// Quaternion real part.
scalar_type r;
@ -143,7 +146,7 @@ struct quaternion
template <class U>
[[nodiscard]] inline constexpr explicit operator quaternion<U>() const noexcept
{
return {static_cast<U>(r), vector<U, 3>(i)};
return {static_cast<U>(r), vec3<U>(i)};
}
/**
@ -183,7 +186,7 @@ struct quaternion
*
* @return Vector containing the real and imaginary parts of the quaternion.
*/
[[nodiscard]] inline constexpr explicit operator vector<T, 4>() const noexcept
[[nodiscard]] inline constexpr explicit operator vec4<T>() const noexcept
{
return {r, i.x(), i.y(), i.z()};
}
@ -201,6 +204,32 @@ struct quaternion
}
};
/// @copydoc math::quaternion_types::quaternion
template <class T>
using quat = quaternion<T>;
/**
* Quaternion with single-precision floating-point scalars.
*
* @tparam T Scalar type.
*/
using fquat = quat<float>;
/**
* Quaternion with double-precision floating-point scalars.
*
* @tparam T Scalar type.
*/
using dquat = quat<double>;
} // namespace quaternion_types
// Bring quaternion types into math namespace
using namespace quaternion_types;
// Bring quaternion types into math::types namespace
namespace types { using namespace math::quaternion_types; }
/**
* Adds two quaternions.
*
@ -318,7 +347,7 @@ template
* @return Unit rotation quaternion.
*/
template <class T>
[[nodiscard]] quaternion<T> look_rotation(const vector<T, 3>& forward, vector<T, 3> up);
[[nodiscard]] quaternion<T> look_rotation(const vec3<T>& forward, vec3<T> up);
/**
* Multiplies two quaternions.
@ -355,7 +384,7 @@ template
* @see https://fgiesen.wordpress.com/2019/02/09/rotating-a-single-vector-using-a-quaternion/
*/
template <class T>
[[nodiscard]] constexpr vector<T, 3> mul(const quaternion<T>& q, const vector<T, 3>& v) noexcept;
[[nodiscard]] constexpr vec3<T> mul(const quaternion<T>& q, const vec3<T>& v) noexcept;
/**
* Rotates a vector by the inverse of a unit quaternion.
@ -368,7 +397,7 @@ template
* @warning @p q must be a unit quaternion.
*/
template <class T>
[[nodiscard]] constexpr vector<T, 3> mul(const vector<T, 3>& v, const quaternion<T>& q) noexcept;
[[nodiscard]] constexpr vec3<T> mul(const vec3<T>& v, const quaternion<T>& q) noexcept;
/**
* Negates a quaternion.
@ -411,7 +440,7 @@ template
* @return Quaternion representing the rotation.
*/
template <class T>
[[nodiscard]] quaternion<T> angle_axis(T angle, const vector<T, 3>& axis);
[[nodiscard]] quaternion<T> angle_axis(T angle, const vec3<T>& axis);
/**
* Calculates a quaternion representing the minimum rotation from one direction to another directions.
@ -425,7 +454,7 @@ template
* @warning @p from and @p to must be unit vectors.
*/
template <class T>
[[nodiscard]] quaternion<T> rotation(const vector<T, 3>& from, const vector<T, 3>& to, T tolerance = T{1e-6});
[[nodiscard]] quaternion<T> rotation(const vec3<T>& from, const vec3<T>& to, T tolerance = T{1e-6});
/**
* Performs spherical linear interpolation between two quaternions.
@ -491,7 +520,7 @@ template
* @see https://www.euclideanspace.com/maths/geometry/rotations/for/decomposition/
*/
template <class T>
void swing_twist(const quaternion<T>& q, const vector<T, 3>& twist_axis, quaternion<T>& swing, quaternion<T>& twist, T tolerance = T{1e-6});
void swing_twist(const quaternion<T>& q, const vec3<T>& twist_axis, quaternion<T>& swing, quaternion<T>& twist, T tolerance = T{1e-6});
/**
* Converts a 3x3 rotation matrix to a quaternion.
@ -501,7 +530,7 @@ void swing_twist(const quaternion& q, const vector& twist_axis, quatern
* @return Unit quaternion representing the rotation described by @p m.
*/
template <class T>
[[nodiscard]] quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m);
[[nodiscard]] quaternion<T> quaternion_cast(const mat3<T>& m);
template <class T>
inline constexpr quaternion<T> add(const quaternion<T>& a, const quaternion<T>& b) noexcept
@ -568,12 +597,12 @@ inline constexpr quaternion lerp(const quaternion& a, const quaternion&
}
template <class T>
quaternion<T> look_rotation(const vector<T, 3>& forward, vector<T, 3> up)
quaternion<T> look_rotation(const vec3<T>& forward, vec3<T> up)
{
const vector<T, 3> right = normalize(cross(forward, up));
const vec3<T> right = normalize(cross(forward, up));
up = cross(right, forward);
const matrix<T, 3, 3> m =
const mat3<T> m =
{
right,
up,
@ -603,14 +632,14 @@ inline constexpr quaternion mul(const quaternion& a, T b) noexcept
}
template <class T>
constexpr vector<T, 3> mul(const quaternion<T>& q, const vector<T, 3>& v) noexcept
constexpr vec3<T> mul(const quaternion<T>& q, const vec3<T>& v) noexcept
{
const auto t = cross(q.i, v) * T{2};
return v + q.r * t + cross(q.i, t);
}
template <class T>
inline constexpr vector<T, 3> mul(const vector<T, 3>& v, const quaternion<T>& q) noexcept
inline constexpr vec3<T> mul(const vec3<T>& v, const quaternion<T>& q) noexcept
{
return mul(conjugate(q), v);
}
@ -634,13 +663,13 @@ inline quaternion normalize(const quaternion& q)
}
template <class T>
quaternion<T> angle_axis(T angle, const vector<T, 3>& axis)
quaternion<T> angle_axis(T angle, const vec3<T>& axis)
{
return {std::cos(angle * T{0.5}), axis * std::sin(angle * T{0.5})};
}
template <class T>
quaternion<T> rotation(const vector<T, 3>& from, const vector<T, 3>& to, T tolerance)
quaternion<T> rotation(const vec3<T>& from, const vec3<T>& to, T tolerance)
{
const auto cos_theta = dot(from, to);
@ -709,7 +738,7 @@ inline constexpr quaternion sub(T a, const quaternion& b) noexcept
}
template <class T>
void swing_twist(const quaternion<T>& q, const vector<T, 3>& twist_axis, quaternion<T>& swing, quaternion<T>& twist, T tolerance)
void swing_twist(const quaternion<T>& q, const vec3<T>& twist_axis, quaternion<T>& swing, quaternion<T>& twist, T tolerance)
{
if (sqr_length(q.i) <= tolerance)
{
@ -740,7 +769,7 @@ void swing_twist(const quaternion& q, const vector& twist_axis, quatern
}
template <class T>
quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m)
quaternion<T> quaternion_cast(const mat3<T>& m)
{
const T t = trace(m);
@ -859,16 +888,16 @@ inline constexpr quaternion operator*(T a, const quaternion& b) noexcept
}
/// @}
/// @copydoc mul(const quaternion<T>&, const vector<T, 3>&)
/// @copydoc mul(const quaternion<T>&, const vec3<T>&)
template <class T>
inline constexpr vector<T, 3> operator*(const quaternion<T>& q, const vector<T, 3>& v) noexcept
inline constexpr vec3<T> operator*(const quaternion<T>& q, const vec3<T>& v) noexcept
{
return mul(q, v);
}
/// @copydoc mul(const vector<T, 3>&, const quaternion<T>&)
/// @copydoc mul(const vec3<T>&, const quaternion<T>&)
template <class T>
inline constexpr vector<T, 3> operator*(const vector<T, 3>& v, const quaternion<T>& q) noexcept
inline constexpr vec3<T> operator*(const vec3<T>& v, const quaternion<T>& q) noexcept
{
return mul(v, q);
}
@ -989,6 +1018,7 @@ inline constexpr quaternion& operator/=(quaternion& a, T b) noexcept
} // namespace math
// Bring quaternion operators into global namespace
using namespace math::operators;
#endif // ANTKEEPER_MATH_QUATERNION_HPP

+ 3
- 3
src/engine/math/se3.hpp View File

@ -39,13 +39,13 @@ public:
typedef T scalar_type;
/// Vector type.
typedef math::vector3<T> vector_type;
typedef math::vec3<T> vector_type;
/// Quaternion type.
typedef math::quaternion<T> quaternion_type;
/// Transformation matrix type.
typedef math::matrix<T, 4, 4> matrix_type;
typedef math::mat4<T> matrix_type;
/// Vector representing the translation component of this SE(3) transformation.
vector_type t;
@ -93,7 +93,7 @@ se3 se3::inverse() const
template <class T>
typename se3<T>::matrix_type se3<T>::matrix() const
{
matrix_type m = math::matrix<T, 4, 4>(math::matrix<T, 3, 3>(r));
matrix_type m = math::mat4<T>(math::mat3<T>(r));
m[3].x() = t.x();
m[3].y() = t.y();

+ 4
- 4
src/engine/math/transform.hpp View File

@ -197,16 +197,16 @@ template
return mul(x, y);
}
/// @copydoc math::mul(const math::transform<T>&, const math::vector<T, 3>&)
/// @copydoc math::mul(const math::transform<T>&, const math::vec3<T>&)
template <class T>
[[nodiscard]] inline constexpr math::vector<T, 3> operator*(const math::transform<T>& t, const math::vector<T, 3>& v) noexcept
[[nodiscard]] inline constexpr math::vec3<T> operator*(const math::transform<T>& t, const math::vec3<T>& v) noexcept
{
return mul(t, v);
}
/// @copydoc math::mul(const math::vector<T, 3>&, const math::transform<T>&)
/// @copydoc math::mul(const math::vec3<T>&, const math::transform<T>&)
template <class T>
[[nodiscard]] inline constexpr math::vector<T, 3> operator*(const math::vector<T, 3>& v, const math::transform<T>& t) noexcept
[[nodiscard]] inline constexpr math::vec3<T> operator*(const math::vec3<T>& v, const math::transform<T>& t) noexcept
{
return mul(v, t);
}

+ 36
- 0
src/engine/math/types.hpp View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2023 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_MATH_TYPES_HPP
#define ANTKEEPER_MATH_TYPES_HPP
namespace math {
/**
* Linear algebra data types.
*/
namespace types {}
} // namespace math
#include <engine/math/matrix.hpp>
#include <engine/math/quaternion.hpp>
#include <engine/math/vector.hpp>
#endif // ANTKEEPER_MATH_TYPES_HPP

+ 115
- 8
src/engine/math/vector.hpp View File

@ -25,11 +25,15 @@
#include <cmath>
#include <concepts>
#include <iterator>
#include <limits>
#include <type_traits>
#include <utility>
namespace math {
/// Vector types.
namespace vector_types {
/**
* *n*-dimensional vector.
*
@ -309,10 +313,10 @@ struct vector
template <std::size_t... I>
[[nodiscard]] static constexpr vector one(std::index_sequence<I...>) noexcept
{
//return {T{1}...};
//return {element_type{1}...};
// MSVC bug workaround (I must be referenced for parameter pack expansion)
return {(I ? T{1} : T{1})...};
return {(I ? element_type{1} : element_type{1})...};
}
/**
@ -323,20 +327,123 @@ struct vector
return one(std::make_index_sequence<N>{});
}
/// @private
template <std::size_t... I>
[[nodiscard]] static constexpr vector infinity(std::index_sequence<I...>) noexcept
{
//return {element_type{1}...};
// MSVC bug workaround (I must be referenced for parameter pack expansion)
return {(I ? std::numeric_limits<element_type>::infinity() : std::numeric_limits<element_type>::infinity())...};
}
/**
* Returns a vector of infinities, where every element is equal to infinity.
*/
[[nodiscard]] static constexpr vector infinity() noexcept
{
return infinity(std::make_index_sequence<N>{});
}
/// @}
};
/// Vector with two elements.
/**
* 2-dimensional vector.
*
* @tparam T Element type.
*/
template <class T>
using vector2 = vector<T, 2>;
using vec2 = vector<T, 2>;
/// Vector with three elements.
/**
* 3-dimensional vector.
*
* @tparam T Element type.
*/
template <class T>
using vector3 = vector<T, 3>;
using vec3 = vector<T, 3>;
/// Vector with four elements.
/**
* 4-dimensional vector.
*
* @tparam T Element type.
*/
template <class T>
using vector4 = vector<T, 4>;
using vec4 = vector<T, 4>;
/**
* *n*-dimensional vector of Boolean values.
*
* @tparam N Number of elements
*/
/// @{
template <std::size_t N>
using bvec = vector<bool, N>;
using bvec2 = bvec<2>;
using bvec3 = bvec<3>;
using bvec4 = bvec<4>;
/// @}
/**
* *n*-dimensional vector of signed integers.
*
* @tparam N Number of elements
*/
/// @{
template <std::size_t N>
using ivec = vector<int, N>;
using ivec2 = ivec<2>;
using ivec3 = ivec<3>;
using ivec4 = ivec<4>;
/// @}
/**
* *n*-dimensional vector of unsigned integers.
*
* @tparam N Number of elements
*/
/// @{
template <std::size_t N>
using uvec = vector<unsigned int, N>;
using uvec2 = uvec<2>;
using uvec3 = uvec<3>;
using uvec4 = uvec<4>;
/// @}
/**
* *n*-dimensional vector of single-precision floating-point numbers.
*
* @tparam N Number of elements
*/
/// @{
template <std::size_t N>
using fvec = vector<float, N>;
using fvec2 = fvec<2>;
using fvec3 = fvec<3>;
using fvec4 = fvec<4>;
/// @}
/**
* *n*-dimensional vector of double-precision floating-point numbers.
*
* @tparam N Number of elements
*/
/// @{
template <std::size_t N>
using dvec = vector<double, N>;
using dvec2 = dvec<2>;
using dvec3 = dvec<3>;
using dvec4 = dvec<4>;
/// @}
} // namespace vector_types
// Bring vector types into math namespace
using namespace vector_types;
// Bring vector types into math::types namespace
namespace types { using namespace math::vector_types; }
/**
* Returns the absolute values of each element.

+ 6
- 6
src/engine/physics/gas/atmosphere.hpp View File

@ -134,14 +134,14 @@ T extinction(T scattering, T albedo)
* @return Optical depth between @p a and @p b.
*/
template <class T>
T optical_depth_exp(const math::vector3<T>& a, const math::vector3<T>& b, T r, T sh, std::size_t n)
T optical_depth_exp(const math::vec3<T>& a, const math::vec3<T>& b, T r, T sh, std::size_t n)
{
sh = T(-1) / sh;
const T h = math::length(b - a) / T(n);
math::vector3<T> dy = (b - a) / T(n);
math::vector3<T> y = a + dy;
math::vec3<T> dy = (b - a) / T(n);
math::vec3<T> y = a + dy;
T f_x = std::exp((math::length(a) - r) * sh);
T f_y = std::exp((math::length(y) - r) * sh);
@ -171,15 +171,15 @@ T optical_depth_exp(const math::vector3& a, const math::vector3& b, T r, T
* @return Optical depth between @p a and @p b.
*/
template <class T>
T optical_depth_tri(const math::vector3<T>& p0, const math::vector3<T>& p1, T r, T a, T b, T c, std::size_t n)
T optical_depth_tri(const math::vec3<T>& p0, const math::vec3<T>& p1, T r, T a, T b, T c, std::size_t n)
{
a = T(1) / (a - c);
b = T(1) / (b - c);
const T h = math::length(p1 - p0) / T(n);
math::vector3<T> dy = (p1 - p0) / T(n);
math::vector3<T> y = p0 + dy;
math::vec3<T> dy = (p1 - p0) / T(n);
math::vec3<T> y = p0 + dy;
T z = math::length(p0) - r;
T f_x = std::max(T(0), std::max(T(0), c - z) * a - std::max(T(0), z - c) * b + T(1));

+ 5
- 5
src/engine/physics/kinematics/colliders/box-collider.hpp View File

@ -55,7 +55,7 @@ public:
* @param max Maximum extent of the box, in object space.
*/
/// @{
inline box_collider(const math::vector<float, 3>& min, const math::vector<float, 3>& max) noexcept:
inline box_collider(const math::fvec3& min, const math::fvec3& max) noexcept:
m_box{min, max}
{}
box_collider() noexcept = default;
@ -76,7 +76,7 @@ public:
*
* @param min Minimum extent of the box, in object space.
*/
inline void set_min(const math::vector<float, 3>& min) noexcept
inline void set_min(const math::fvec3& min) noexcept
{
m_box.min = min;
}
@ -86,7 +86,7 @@ public:
*
* @param max Maximum extent of the box, in object space.
*/
inline void set_max(const math::vector<float, 3>& max) noexcept
inline void set_max(const math::fvec3& max) noexcept
{
m_box.max = max;
}
@ -98,13 +98,13 @@ public:
}
/// Returns the minimum extent of the box, in object space.
[[nodiscard]] inline const math::vector<float, 3>& get_min() const noexcept
[[nodiscard]] inline const math::fvec3& get_min() const noexcept
{
return m_box.min;
}
/// Returns the maximum extent of the box, in object space.
[[nodiscard]] inline const math::vector<float, 3>& get_max() const noexcept
[[nodiscard]] inline const math::fvec3& get_max() const noexcept
{
return m_box.max;
}

+ 5
- 5
src/engine/physics/kinematics/colliders/plane-collider.hpp View File

@ -55,10 +55,10 @@ public:
* @param constant Plane constant.
*/
/// @{
inline plane_collider(const math::vector<float, 3>& normal, float constant) noexcept:
inline plane_collider(const math::fvec3& normal, float constant) noexcept:
m_plane{normal, constant}
{}
inline explicit plane_collider(const math::vector<float, 3>& normal) noexcept:
inline explicit plane_collider(const math::fvec3& normal) noexcept:
m_plane{normal, 0.0f}
{}
plane_collider() noexcept = default;
@ -70,7 +70,7 @@ public:
* @param normal Plane normal, in object space.
* @param offset Offset from the origin, in object space.
*/
inline plane_collider(const math::vector<float, 3>& normal, const math::vector<float, 3>& offset) noexcept:
inline plane_collider(const math::fvec3& normal, const math::fvec3& offset) noexcept:
m_plane(normal, offset)
{}
@ -89,7 +89,7 @@ public:
*
* @param normal Plane normal, in object space.
*/
inline void set_normal(const math::vector<float, 3>& normal) noexcept
inline void set_normal(const math::fvec3& normal) noexcept
{
m_plane.normal = normal;
}
@ -111,7 +111,7 @@ public:
}
/// Returns the plane normal, in object space.
[[nodiscard]] inline const math::vector<float, 3>& get_normal() const noexcept
[[nodiscard]] inline const math::fvec3& get_normal() const noexcept
{
return m_plane.normal;
}

+ 3
- 3
src/engine/physics/kinematics/colliders/sphere-collider.hpp View File

@ -55,7 +55,7 @@ public:
* @param radius Sphere radius.
*/
/// @{
inline sphere_collider(const math::vector<float, 3>& center, float radius) noexcept:
inline sphere_collider(const math::fvec3& center, float radius) noexcept:
m_sphere{center, radius}
{}
inline explicit sphere_collider(float radius) noexcept:
@ -79,7 +79,7 @@ public:
*
* @param center Sphere center, in object space.
*/
inline void set_center(const math::vector<float, 3>& center) noexcept
inline void set_center(const math::fvec3& center) noexcept
{
m_sphere.center = center;
}
@ -101,7 +101,7 @@ public:
}
/// Returns the center of the sphere, in object space.
[[nodiscard]] inline const math::vector<float, 3>& get_center() const noexcept
[[nodiscard]] inline const math::fvec3& get_center() const noexcept
{
return m_sphere.center;
}

+ 2
- 2
src/engine/physics/kinematics/collision-contact.hpp View File

@ -30,10 +30,10 @@ namespace physics {
struct collision_contact
{
/// World-space contact point.
math::vector<float, 3> point{math::vector<float, 3>::zero()};
math::fvec3 point{math::fvec3::zero()};
/// Contact normal, pointing from body a to body b.
math::vector<float, 3> normal{math::vector<float, 3>::zero()};
math::fvec3 normal{math::fvec3::zero()};
/// Contact penetration depth.
float depth{0.0f};

+ 7
- 7
src/engine/physics/kinematics/constraints/spring-constraint.cpp View File

@ -29,21 +29,21 @@ void spring_constraint::solve(float dt)
}
// Get radius vectors from centers of mass to spring attachment points
const math::vector<float, 3> radius_a = m_body_a->get_orientation() * m_point_a;
const math::vector<float, 3> radius_b = m_body_b->get_orientation() * m_point_b;
const math::fvec3 radius_a = m_body_a->get_orientation() * m_point_a;
const math::fvec3 radius_b = m_body_b->get_orientation() * m_point_b;
// Get world-space spring attachment points
const math::vector<float, 3> point_a = m_body_a->get_position() + radius_a;
const math::vector<float, 3> point_b = m_body_b->get_position() + radius_b;
const math::fvec3 point_a = m_body_a->get_position() + radius_a;
const math::fvec3 point_b = m_body_b->get_position() + radius_b;
// Calculate relative velocity between the attachment points
const math::vector<float, 3> velocity = m_body_b->get_point_velocity(radius_b) - m_body_a->get_point_velocity(radius_a);
const math::fvec3 velocity = m_body_b->get_point_velocity(radius_b) - m_body_a->get_point_velocity(radius_a);
// Calculate spring force
// F = -k * (|x| - d) * (x / |x|) - bv
const math::vector<float, 3> difference = point_b - point_a;
const math::fvec3 difference = point_b - point_a;
const float distance = std::sqrt(math::dot(difference, difference));
const math::vector<float, 3> force = -m_stiffness * (distance - m_resting_length) * (difference / distance) - velocity * m_damping;
const math::fvec3 force = -m_stiffness * (distance - m_resting_length) * (difference / distance) - velocity * m_damping;
// Apply spring force to bodies at attachment points
m_body_a->apply_force(-force, radius_a);

+ 6
- 6
src/engine/physics/kinematics/constraints/spring-constraint.hpp View File

@ -40,7 +40,7 @@ public:
* @param body_a Body to which the spring should be attached.
* @param point_a Point on body a, in body-space, at which the spring should be attached.
*/
inline void attach_a(rigid_body& body_a, const math::vector<float, 3>& point_a) noexcept
inline void attach_a(rigid_body& body_a, const math::fvec3& point_a) noexcept
{
m_body_a = &body_a;
m_point_a = point_a;
@ -52,7 +52,7 @@ public:
* @param body_b Body to which the spring should be attached.
* @param point_b Point on body b, in body-space, at which the spring should be attached.
*/
inline void attach_b(rigid_body& body_b, const math::vector<float, 3>& point_b) noexcept
inline void attach_b(rigid_body& body_b, const math::fvec3& point_b) noexcept
{
m_body_b = &body_b;
m_point_b = point_b;
@ -126,13 +126,13 @@ public:
}
/// Returns the point at which the spring is attached to body a, in body-space.
[[nodiscard]] inline const math::vector<float, 3>& get_point_a() const noexcept
[[nodiscard]] inline const math::fvec3& get_point_a() const noexcept
{
return m_point_a;
}
/// Returns the point at which the spring is attached to body b, in body-space.
[[nodiscard]] inline const math::vector<float, 3>& get_point_b() const noexcept
[[nodiscard]] inline const math::fvec3& get_point_b() const noexcept
{
return m_point_b;
}
@ -163,10 +163,10 @@ private:
rigid_body* m_body_b{nullptr};
/// Point at which the spring is attached to body a, in body-space.
math::vector<float, 3> m_point_a{0.0f, 0.0f, 0.0f};
math::fvec3 m_point_a{0.0f, 0.0f, 0.0f};
/// Point at which the spring is attached to body b, in body-space.
math::vector<float, 3> m_point_b{0.0f, 0.0f, 0.0f};
math::fvec3 m_point_b{0.0f, 0.0f, 0.0f};
/// Resting length of the spring, in meters.
float m_resting_length{0.0f};

+ 3
- 3
src/engine/physics/kinematics/rigid-body.cpp View File

@ -38,8 +38,8 @@ void rigid_body::integrate_forces(float dt) noexcept
m_angular_velocity = m_inverse_inertia * m_angular_momentum;
// Clear forces
m_applied_force = math::vector<float, 3>::zero();
m_applied_torque = math::vector<float, 3>::zero();
m_applied_force = math::fvec3::zero();
m_applied_torque = math::fvec3::zero();
}
void rigid_body::integrate_velocities(float dt) noexcept
@ -51,7 +51,7 @@ void rigid_body::integrate_velocities(float dt) noexcept
m_current_transform.translation += m_linear_velocity * dt;
// Update orientation
const math::quaternion<float> spin = math::quaternion<float>{0.0f, m_angular_velocity * 0.5f} * m_current_transform.rotation;
const math::fquat spin = math::fquat{0.0f, m_angular_velocity * 0.5f} * m_current_transform.rotation;
m_current_transform.rotation = math::normalize(m_current_transform.rotation + spin * dt);
}

+ 36
- 36
src/engine/physics/kinematics/rigid-body.hpp View File

@ -49,7 +49,7 @@ public:
*
* @param position Position of the rigid body.
*/
inline void set_position(const math::vector<float, 3>& position) noexcept
inline void set_position(const math::fvec3& position) noexcept
{
m_current_transform.translation = position;
}
@ -59,7 +59,7 @@ public:
*
* @param orientation Orientation of the rigid body.
*/
inline void set_orientation(const math::quaternion<float>& orientation) noexcept
inline void set_orientation(const math::fquat& orientation) noexcept
{
m_current_transform.rotation = orientation;
}
@ -79,7 +79,7 @@ public:
*
* @param position Position of the rigid body.
*/
inline void set_previous_position(const math::vector<float, 3>& position) noexcept
inline void set_previous_position(const math::fvec3& position) noexcept
{
m_previous_transform.translation = position;
}
@ -89,7 +89,7 @@ public:
*
* @param orientation Orientation of the rigid body.
*/
inline void set_previous_orientation(const math::quaternion<float>& orientation) noexcept
inline void set_previous_orientation(const math::fquat& orientation) noexcept
{
m_previous_transform.rotation = orientation;
}
@ -99,7 +99,7 @@ public:
*
* @param point World-space center of mass.
*/
inline void set_center_of_mass(const math::vector<float, 3>& point) noexcept
inline void set_center_of_mass(const math::fvec3& point) noexcept
{
m_center_of_mass = point;
}
@ -161,7 +161,7 @@ public:
*
* @param momentum Linear momentum, in kgm/s.
*/
inline void set_linear_momentum(const math::vector<float, 3>& momentum) noexcept
inline void set_linear_momentum(const math::fvec3& momentum) noexcept
{
m_linear_momentum = momentum;
m_linear_velocity = m_inverse_mass * m_linear_momentum;
@ -172,7 +172,7 @@ public:
*
* @param momentum Angular momentum, in kgm^2s^-1.
*/
inline void set_angular_momentum(const math::vector<float, 3>& momentum) noexcept
inline void set_angular_momentum(const math::fvec3& momentum) noexcept
{
m_angular_momentum = momentum;
m_angular_velocity = m_inverse_inertia * m_angular_momentum;
@ -183,7 +183,7 @@ public:
*
* @param velocity Linear velocity, in m/s.
*/
inline void set_linear_velocity(const math::vector<float, 3>& velocity) noexcept
inline void set_linear_velocity(const math::fvec3& velocity) noexcept
{
m_linear_velocity = velocity;
m_linear_momentum = m_mass * m_linear_velocity;
@ -194,7 +194,7 @@ public:
*
* @param velocity Angular velocity, rad/s.
*/
inline void set_angular_velocity(const math::vector<float, 3>& velocity) noexcept
inline void set_angular_velocity(const math::fvec3& velocity) noexcept
{
m_angular_velocity = velocity;
m_angular_momentum = m_inertia * m_angular_velocity;
@ -207,13 +207,13 @@ public:
}
/// Returns the current position of the rigid body.
[[nodiscard]] inline const math::vector<float, 3>& get_position() const noexcept
[[nodiscard]] inline const math::fvec3& get_position() const noexcept
{
return m_current_transform.translation;
}
/// Returns the current orientation of the rigid body.
[[nodiscard]] inline const math::quaternion<float>& get_orientation() const noexcept
[[nodiscard]] inline const math::fquat& get_orientation() const noexcept
{
return m_current_transform.rotation;
}
@ -225,19 +225,19 @@ public:
}
/// Returns the previous position of the rigid body.
[[nodiscard]] inline const math::vector<float, 3>& get_previous_position() const noexcept
[[nodiscard]] inline const math::fvec3& get_previous_position() const noexcept
{
return m_previous_transform.translation;
}
/// Returns the previous orientation of the rigid body.
[[nodiscard]] inline const math::quaternion<float>& get_previous_orientation() const noexcept
[[nodiscard]] inline const math::fquat& get_previous_orientation() const noexcept
{
return m_previous_transform.rotation;
}
/// Returns the center of mass of the rigid body.
[[nodiscard]] inline const math::vector<float, 3>& get_center_of_mass() const noexcept
[[nodiscard]] inline const math::fvec3& get_center_of_mass() const noexcept
{
return m_center_of_mass;
}
@ -285,37 +285,37 @@ public:
}
/// Returns the linear momentum of the rigid body, in kg⋅m/s.
[[nodiscard]] inline const math::vector<float, 3>& get_linear_momentum() const noexcept
[[nodiscard]] inline const math::fvec3& get_linear_momentum() const noexcept
{
return m_linear_momentum;
}
/// Returns the angular momentum of the rigid body, in kg⋅m^2⋅s^-1.
[[nodiscard]] inline const math::vector<float, 3>& get_angular_momentum() const noexcept
[[nodiscard]] inline const math::fvec3& get_angular_momentum() const noexcept
{
return m_angular_momentum;
}
/// Returns the linear velocity of the rigid body, in m/s.
[[nodiscard]] inline const math::vector<float, 3>& get_linear_velocity() const noexcept
[[nodiscard]] inline const math::fvec3& get_linear_velocity() const noexcept
{
return m_linear_velocity;
}
/// Returns the angular velocity of the rigid body, in rad/s.
[[nodiscard]] inline const math::vector<float, 3>& get_angular_velocity() const noexcept
[[nodiscard]] inline const math::fvec3& get_angular_velocity() const noexcept
{
return m_angular_velocity;
}
/// Returns the total pre-integrated force, in N.
[[nodiscard]] inline const math::vector<float, 3>& get_applied_force() const noexcept
[[nodiscard]] inline const math::fvec3& get_applied_force() const noexcept
{
return m_applied_force;
}
/// Returns the total pre-integrated torque, in N⋅m.
[[nodiscard]] inline const math::vector<float, 3>& get_applied_torque() const noexcept
[[nodiscard]] inline const math::fvec3& get_applied_torque() const noexcept
{
return m_applied_torque;
}
@ -327,7 +327,7 @@ public:
*
* @return Point velocity.
*/
[[nodiscard]] inline math::vector<float, 3> get_point_velocity(const math::vector<float, 3>& radius) const noexcept
[[nodiscard]] inline math::fvec3 get_point_velocity(const math::fvec3& radius) const noexcept
{
return m_linear_velocity + math::cross(m_angular_velocity, radius);
}
@ -346,7 +346,7 @@ public:
* @param force Force to apply, in N.
* @param radius Radius vector from the center of mass to the point at which the force should be applied.
*/
inline void apply_force(const math::vector<float, 3>& force, const math::vector<float, 3>& radius) noexcept
inline void apply_force(const math::fvec3& force, const math::fvec3& radius) noexcept
{
m_applied_force += force;
m_applied_torque += math::cross(radius, force);
@ -357,7 +357,7 @@ public:
*
* @param force Force to apply, in N.
*/
inline void apply_central_force(const math::vector<float, 3>& force) noexcept
inline void apply_central_force(const math::fvec3& force) noexcept
{
m_applied_force += force;
}
@ -367,7 +367,7 @@ public:
*
* @param torque Torque to apply.
*/
inline void apply_torque(const math::vector<float, 3>& torque) noexcept
inline void apply_torque(const math::fvec3& torque) noexcept
{
m_applied_torque += torque;
}
@ -378,7 +378,7 @@ public:
* @param impulse Impulse to apply, in Ns.
* @param radius Radius vector from the center of mass to the point at which the impulse should be applied.
*/
inline void apply_impulse(const math::vector<float, 3>& impulse, const math::vector<float, 3>& radius) noexcept
inline void apply_impulse(const math::fvec3& impulse, const math::fvec3& radius) noexcept
{
m_linear_momentum += impulse;
m_angular_momentum += math::cross(radius, impulse);
@ -393,7 +393,7 @@ public:
*
* @param impulse Impulse to apply, in Ns.
*/
inline void apply_central_impulse(const math::vector<float, 3>& impulse) noexcept
inline void apply_central_impulse(const math::fvec3& impulse) noexcept
{
m_linear_momentum += impulse;
@ -406,7 +406,7 @@ public:
*
* @param torque Torque impulse to apply.
*/
inline void apply_torque_impulse(const math::vector<float, 3>& torque) noexcept
inline void apply_torque_impulse(const math::fvec3& torque) noexcept
{
m_angular_momentum += torque;
@ -417,8 +417,8 @@ public:
/// Clears all pre-integrated forces.
inline void clear_applied_forces() noexcept
{
m_applied_force = math::vector<float, 3>::zero();
m_applied_torque = math::vector<float, 3>::zero();
m_applied_force = math::fvec3::zero();
m_applied_torque = math::fvec3::zero();
}
/**
@ -463,7 +463,7 @@ private:
math::transform<float> m_previous_transform{math::transform<float>::identity()};
/// Center of mass.
math::vector<float, 3> m_center_of_mass{math::vector<float, 3>::zero()};
math::fvec3 m_center_of_mass{math::fvec3::zero()};
/// Mass, in kg.
float m_mass{1.0f};
@ -487,22 +487,22 @@ private:
std::shared_ptr<collider> m_collider;
/// Linear momentum, in kg⋅m/s.
math::vector<float, 3> m_linear_momentum{math::vector<float, 3>::zero()};
math::fvec3 m_linear_momentum{math::fvec3::zero()};
/// Angular momentum, in kg⋅m^2⋅s^-1.
math::vector<float, 3> m_angular_momentum{math::vector<float, 3>::zero()};
math::fvec3 m_angular_momentum{math::fvec3::zero()};
/// Linear velocity, in m/s.
math::vector<float, 3> m_linear_velocity{math::vector<float, 3>::zero()};
math::fvec3 m_linear_velocity{math::fvec3::zero()};
/// Angular velocity, in rad/s.
math::vector<float, 3> m_angular_velocity{math::vector<float, 3>::zero()};
math::fvec3 m_angular_velocity{math::fvec3::zero()};
/// Applied force, in N.
math::vector<float, 3> m_applied_force{math::vector<float, 3>::zero()};
math::fvec3 m_applied_force{math::fvec3::zero()};
/// Applied torque, in N⋅m.
math::vector<float, 3> m_applied_torque{math::vector<float, 3>::zero()};
math::fvec3 m_applied_torque{math::fvec3::zero()};
};
} // namespace physics

+ 1
- 1
src/engine/physics/orbit/elements.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_PHYSICS_ORBIT_ELEMENTS_HPP
#define ANTKEEPER_PHYSICS_ORBIT_ELEMENTS_HPP
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
#include <engine/math/numbers.hpp>
#include <cmath>

+ 23
- 23
src/engine/physics/orbit/frame.hpp View File

@ -39,11 +39,11 @@ namespace pqw {
* @return PQW spherical coordinates, in the ISO order of radial distance, inclination (radians), and true anomaly (radians).
*/
template <class T>
math::vector3<T> spherical(const math::vector3<T>& v)
math::vec3<T> spherical(const math::vec3<T>& v)
{
const T xx_yy = v.x() * v.x() + v.y() * v.y();
return math::vector3<T>
return math::vec3<T>
{
std::sqrt(xx_yy + v.z() * v.z()),
std::atan2(v.z(), std::sqrt(xx_yy)),
@ -61,14 +61,14 @@ namespace pqw {
* @return PQW spherical coordinates, in the ISO order of radial distance, inclination (radians), and true anomaly (radians).
*/
template <class T>
math::vector3<T> spherical(T ec, T a, T ea, T b)
math::vec3<T> spherical(T ec, T a, T ea, T b)
{
const T x = a * (std::cos(ea) - ec);
const T y = b * std::sin(ea);
const T d = std::sqrt(x * x + y * y);
const T ta = std::atan2(y, x);
return math::vector3<T>{d, T(0), ta};
return math::vec3<T>{d, T(0), ta};
}
/**
@ -80,7 +80,7 @@ namespace pqw {
* @return PQW spherical coordinates, in the ISO order of radial distance, inclination (radians), and true anomaly (radians).
*/
template <class T>
math::vector3<T> spherical(T ec, T a, T ea)
math::vec3<T> spherical(T ec, T a, T ea)
{
const T b = a * std::sqrt(T(1) - ec * ec);
return spherical<T>(ec, a, ea, b);
@ -93,11 +93,11 @@ namespace pqw {
* @return PQW Cartesian coordinates.
*/
template <class T>
math::vector3<T> cartesian(const math::vector3<T>& v)
math::vec3<T> cartesian(const math::vec3<T>& v)
{
const T x = v[0] * std::cos(v[1]);
return math::vector3<T>
return math::vec3<T>
{
x * std::cos(v[2]),
x * std::sin(v[2]),
@ -115,7 +115,7 @@ namespace pqw {
* @return PQW Cartesian coordinates.
*/
template <class T>
math::vector3<T> cartesian(T ec, T a, T ea, T b)
math::vec3<T> cartesian(T ec, T a, T ea, T b)
{
return cartesian<T>(spherical<T>(ec, a, ea, b));
}
@ -129,7 +129,7 @@ namespace pqw {
* @return PQW Cartesian coordinates.
*/
template <class T>
math::vector3<T> cartesian(T ec, T a, T ea)
math::vec3<T> cartesian(T ec, T a, T ea)
{
return cartesian<T>(spherical<T>(ec, a, ea));
}
@ -167,11 +167,11 @@ namespace bci {
* @return BCI Cartesian coordinates.
*/
template <class T>
math::vector3<T> cartesian(const math::vector3<T>& v)
math::vec3<T> cartesian(const math::vec3<T>& v)
{
const T x = v[0] * std::cos(v[1]);
return math::vector3<T>
return math::vec3<T>
{
x * std::cos(v[2]),
x * std::sin(v[2]),
@ -186,11 +186,11 @@ namespace bci {
* @return BCI spherical coordinates, in the ISO order of radial distance, declination (radians), and right ascension (radians).
*/
template <class T>
math::vector3<T> spherical(const math::vector3<T>& v)
math::vec3<T> spherical(const math::vec3<T>& v)
{
const T xx_yy = v.x() * v.x() + v.y() * v.y();
return math::vector3<T>
return math::vec3<T>
{
std::sqrt(xx_yy + v.z() * v.z()),
std::atan2(v.z(), std::sqrt(xx_yy)),
@ -255,11 +255,11 @@ namespace bcbf {
* @return BCBF Cartesian coordinates.
*/
template <class T>
math::vector3<T> cartesian(const math::vector3<T>& v)
math::vec3<T> cartesian(const math::vec3<T>& v)
{
const T x = v[0] * std::cos(v[1]);
return math::vector3<T>
return math::vec3<T>
{
x * std::cos(v[2]),
x * std::sin(v[2]),
@ -274,11 +274,11 @@ namespace bcbf {
* @return BCBF spherical coordinates, in the ISO order of radial distance, latitude (radians), and longitude (radians).
*/
template <class T>
math::vector3<T> spherical(const math::vector3<T>& v)
math::vec3<T> spherical(const math::vec3<T>& v)
{
const T xx_yy = v.x() * v.x() + v.y() * v.y();
return math::vector3<T>
return math::vec3<T>
{
std::sqrt(xx_yy + v.z() * v.z()),
std::atan2(v.z(), std::sqrt(xx_yy)),
@ -322,7 +322,7 @@ namespace bcbf {
template <typename T>
math::transformation::se3<T> to_enu(T distance, T latitude, T longitude)
{
const math::vector3<T> t = {T(0), T(0), -distance};
const math::vec3<T> t = {T(0), T(0), -distance};
const math::quaternion<T> r = math::normalize
(
math::quaternion<T>::rotate_x(-math::half_pi<T> + latitude) *
@ -344,12 +344,12 @@ namespace enu {
* @return ENU Cartesian coordinates.
*/
template <class T>
math::vector3<T> cartesian(const math::vector3<T>& v)
math::vec3<T> cartesian(const math::vec3<T>& v)
{
const T x = v[0] * std::cos(v[1]);
const T y = math::half_pi<T> - v[2];
return math::vector3<T>
return math::vec3<T>
{
x * std::cos(y),
x * std::sin(y),
@ -364,11 +364,11 @@ namespace enu {
* @return ENU spherical coordinates, in the ISO order of radial distance, elevation (radians), and azimuth (radians).
*/
template <class T>
math::vector3<T> spherical(const math::vector3<T>& v)
math::vec3<T> spherical(const math::vec3<T>& v)
{
const T xx_yy = v.x() * v.x() + v.y() * v.y();
return math::vector3<T>
return math::vec3<T>
{
std::sqrt(xx_yy + v.z() * v.z()),
std::atan2(v.z(), std::sqrt(xx_yy)),
@ -387,7 +387,7 @@ namespace enu {
template <typename T>
math::transformation::se3<T> to_bcbf(T distance, T latitude, T longitude)
{
const math::vector3<T> t = {T(0), T(0), distance};
const math::vec3<T> t = {T(0), T(0), distance};
const math::quaternion<T> r = math::normalize
(
math::quaternion<T>::rotate_z(longitude + math::half_pi<T>) *

+ 2
- 2
src/engine/physics/orbit/state.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_PHYSICS_ORBIT_STATE_HPP
#define ANTKEEPER_PHYSICS_ORBIT_STATE_HPP
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
namespace physics {
namespace orbit {
@ -37,7 +37,7 @@ struct state
typedef T scalar_type;
/// Vector type.
typedef math::vector3<T> vector_type;
typedef math::vec3<T> vector_type;
/// Cartesian orbital position vector (r).
vector_type r;

+ 3
- 3
src/engine/physics/orbit/trajectory.hpp View File

@ -56,11 +56,11 @@ struct trajectory
* @param t Time, on `[t0, t1)`.
* @return Trajectory position at time @p t.
*/
[[nodiscard]] math::vector<T, 3> position(T t) const;
[[nodiscard]] math::vec3<T> position(T t) const;
};
template <class T>
math::vector<T, 3> trajectory<T>::position(T t) const
math::vec3<T> trajectory<T>::position(T t) const
{
t -= t0;
std::size_t i = static_cast<std::size_t>(t / dt);
@ -71,7 +71,7 @@ math::vector trajectory::position(T t) const
t = (t / dt - i) * T(2) - T(1);
math::vector3<T> r;
math::vec3<T> r;
r.x() = math::polynomial::chebyshev::evaluate(ax, ay, t);
r.y() = math::polynomial::chebyshev::evaluate(ay, az, t);
r.z() = math::polynomial::chebyshev::evaluate(az, az + n, t);

+ 1
- 1
src/engine/render/context.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_RENDER_CONTEXT_HPP
#define ANTKEEPER_RENDER_CONTEXT_HPP
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
#include <engine/render/operation.hpp>
#include <vector>

+ 19
- 19
src/engine/render/material-variable-type.hpp View File

@ -29,25 +29,25 @@ namespace render {
*/
enum class material_variable_type: std::uint8_t
{
bool1,
bool2,
bool3,
bool4,
int1,
int2,
int3,
int4,
uint1,
uint2,
uint3,
uint4,
float1,
float2,
float3,
float4,
float2x2,
float3x3,
float4x4,
bvec1,
bvec2,
bvec3,
bvec4,
ivec1,
ivec2,
ivec3,
ivec4,
uvec1,
uvec2,
uvec3,
uvec4,
fvec1,
fvec2,
fvec3,
fvec4,
fmat2,
fmat3,
fmat4,
texture_1d,
texture_2d,
texture_3d,

+ 67
- 66
src/engine/render/material-variable.hpp View File

@ -20,7 +20,8 @@
#ifndef ANTKEEPER_RENDER_MATERIAL_VARIABLE_HPP
#define ANTKEEPER_RENDER_MATERIAL_VARIABLE_HPP
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
#include <engine/math/matrix.hpp>
#include <engine/gl/texture-1d.hpp>
#include <engine/gl/texture-2d.hpp>
#include <engine/gl/texture-3d.hpp>
@ -162,208 +163,208 @@ private:
};
/// Boolean material variable.
using material_bool = material_variable<bool>;
using matvar_bool = material_variable<bool>;
/// 2-dimensional boolean vector material variable.
using material_bool2 = material_variable<bool2>;
using matvar_bvec2 = material_variable<math::bvec2>;
/// 3-dimensional boolean vector material variable.
using material_bool3 = material_variable<bool3>;
using matvar_bvec3 = material_variable<math::bvec3>;
/// 4-dimensional boolean vector material variable.
using material_bool4 = material_variable<bool4>;
using matvar_bvec4 = material_variable<math::bvec4>;
/// Integer material variable.
using material_int = material_variable<int>;
using matvar_int = material_variable<int>;
/// 2-dimensional integer vector material variable.
using material_int2 = material_variable<int2>;
using matvar_ivec2 = material_variable<math::ivec2>;
/// 3-dimensional integer vector material variable.
using material_int3 = material_variable<int3>;
using matvar_ivec3 = material_variable<math::ivec3>;
/// 4-dimensional integer vector material variable.
using material_int4 = material_variable<int4>;
using matvar_ivec4 = material_variable<math::ivec4>;
/// Unsigned integer material variable.
using material_uint = material_variable<unsigned int>;
using matvar_uint = material_variable<unsigned int>;
/// 2-dimensional unsigned integer vector material variable.
using material_uint2 = material_variable<uint2>;
using matvar_uvec2 = material_variable<math::uvec2>;
/// 3-dimensional unsigned integer vector material variable.
using material_uint3 = material_variable<uint3>;
using matvar_uvec3 = material_variable<math::uvec3>;
/// 4-dimensional unsigned integer vector material variable.
using material_uint4 = material_variable<uint4>;
using matvar_uvec4 = material_variable<math::uvec4>;
/// Floating-point material variable.
using material_float = material_variable<float>;
using matvar_float = material_variable<float>;
/// 2-dimensional floating-point vector material variable.
using material_float2 = material_variable<float2>;
using matvar_fvec2 = material_variable<math::fvec2>;
/// 3-dimensional floating-point vector material variable.
using material_float3 = material_variable<float3>;
using matvar_fvec3 = material_variable<math::fvec3>;
/// 4-dimensional floating-point vector material variable.
using material_float4 = material_variable<float4>;
using matvar_fvec4 = material_variable<math::fvec4>;
/// 2x2 floating-point matrix material variable.
using material_float2x2 = material_variable<float2x2>;
using matvar_fmat2 = material_variable<math::fmat2>;
/// 3x3 floating-point matrix material variable.
using material_float3x3 = material_variable<float3x3>;
using matvar_fmat3 = material_variable<math::fmat3>;
/// 4x4 floating-point matrix material variable.
using material_float4x4 = material_variable<float4x4>;
using matvar_fmat4 = material_variable<math::fmat4>;
/// 1-dimensional texture material variable.
using material_texture_1d = material_variable<std::shared_ptr<gl::texture_1d>>;
using matvar_texture_1d = material_variable<std::shared_ptr<gl::texture_1d>>;
/// 2-dimensional texture material variable.
using material_texture_2d = material_variable<std::shared_ptr<gl::texture_2d>>;
using matvar_texture_2d = material_variable<std::shared_ptr<gl::texture_2d>>;
/// 3-dimensional texture material variable.
using material_texture_3d = material_variable<std::shared_ptr<gl::texture_3d>>;
using matvar_texture_3d = material_variable<std::shared_ptr<gl::texture_3d>>;
/// Cube texture material variable.
using material_texture_cube = material_variable<std::shared_ptr<gl::texture_cube>>;
using matvar_texture_cube = material_variable<std::shared_ptr<gl::texture_cube>>;
template <>
inline constexpr material_variable_type material_bool::type() const noexcept
inline constexpr material_variable_type matvar_bool::type() const noexcept
{
return material_variable_type::bool1;
return material_variable_type::bvec1;
}
template <>
inline constexpr material_variable_type material_bool2::type() const noexcept
inline constexpr material_variable_type matvar_bvec2::type() const noexcept
{
return material_variable_type::bool2;
return material_variable_type::bvec2;
}
template <>
inline constexpr material_variable_type material_bool3::type() const noexcept
inline constexpr material_variable_type matvar_bvec3::type() const noexcept
{
return material_variable_type::bool3;
return material_variable_type::bvec3;
}
template <>
inline constexpr material_variable_type material_bool4::type() const noexcept
inline constexpr material_variable_type matvar_bvec4::type() const noexcept
{
return material_variable_type::bool4;
return material_variable_type::bvec4;
}
template <>
inline constexpr material_variable_type material_int::type() const noexcept
inline constexpr material_variable_type matvar_int::type() const noexcept
{
return material_variable_type::int1;
return material_variable_type::ivec1;
}
template <>
inline constexpr material_variable_type material_int2::type() const noexcept
inline constexpr material_variable_type matvar_ivec2::type() const noexcept
{
return material_variable_type::int2;
return material_variable_type::ivec2;
}
template <>
inline constexpr material_variable_type material_int3::type() const noexcept
inline constexpr material_variable_type matvar_ivec3::type() const noexcept
{
return material_variable_type::int3;
return material_variable_type::ivec3;
}
template <>
inline constexpr material_variable_type material_int4::type() const noexcept
inline constexpr material_variable_type matvar_ivec4::type() const noexcept
{
return material_variable_type::int4;
return material_variable_type::ivec4;
}
template <>
inline constexpr material_variable_type material_uint::type() const noexcept
inline constexpr material_variable_type matvar_uint::type() const noexcept
{
return material_variable_type::uint1;
return material_variable_type::uvec1;
}
template <>
inline constexpr material_variable_type material_uint2::type() const noexcept
inline constexpr material_variable_type matvar_uvec2::type() const noexcept
{
return material_variable_type::uint2;
return material_variable_type::uvec2;
}
template <>
inline constexpr material_variable_type material_uint3::type() const noexcept
inline constexpr material_variable_type matvar_uvec3::type() const noexcept
{
return material_variable_type::uint3;
return material_variable_type::uvec3;
}
template <>
inline constexpr material_variable_type material_uint4::type() const noexcept
inline constexpr material_variable_type matvar_uvec4::type() const noexcept
{
return material_variable_type::uint4;
return material_variable_type::uvec4;
}
template <>
inline constexpr material_variable_type material_float::type() const noexcept
inline constexpr material_variable_type matvar_float::type() const noexcept
{
return material_variable_type::float1;
return material_variable_type::fvec1;
}
template <>
inline constexpr material_variable_type material_float2::type() const noexcept
inline constexpr material_variable_type matvar_fvec2::type() const noexcept
{
return material_variable_type::float2;
return material_variable_type::fvec2;
}
template <>
inline constexpr material_variable_type material_float3::type() const noexcept
inline constexpr material_variable_type matvar_fvec3::type() const noexcept
{
return material_variable_type::float3;
return material_variable_type::fvec3;
}
template <>
inline constexpr material_variable_type material_float4::type() const noexcept
inline constexpr material_variable_type matvar_fvec4::type() const noexcept
{
return material_variable_type::float4;
return material_variable_type::fvec4;
}
template <>
inline constexpr material_variable_type material_float2x2::type() const noexcept
inline constexpr material_variable_type matvar_fmat2::type() const noexcept
{
return material_variable_type::float2x2;
return material_variable_type::fmat2;
}
template <>
inline constexpr material_variable_type material_float3x3::type() const noexcept
inline constexpr material_variable_type matvar_fmat3::type() const noexcept
{
return material_variable_type::float3x3;
return material_variable_type::fmat3;
}
template <>
inline constexpr material_variable_type material_float4x4::type() const noexcept
inline constexpr material_variable_type matvar_fmat4::type() const noexcept
{
return material_variable_type::float4x4;
return material_variable_type::fmat4;
}
template <>
inline constexpr material_variable_type material_texture_1d::type() const noexcept
inline constexpr material_variable_type matvar_texture_1d::type() const noexcept
{
return material_variable_type::texture_1d;
}
template <>
inline constexpr material_variable_type material_texture_2d::type() const noexcept
inline constexpr material_variable_type matvar_texture_2d::type() const noexcept
{
return material_variable_type::texture_2d;
}
template <>
inline constexpr material_variable_type material_texture_3d::type() const noexcept
inline constexpr material_variable_type matvar_texture_3d::type() const noexcept
{
return material_variable_type::texture_3d;
}
template <>
inline constexpr material_variable_type material_texture_cube::type() const noexcept
inline constexpr material_variable_type matvar_texture_cube::type() const noexcept
{
return material_variable_type::texture_cube;
}

+ 23
- 23
src/engine/render/material.cpp View File

@ -141,7 +141,7 @@ static bool load_texture_1d_property(resource_manager& resource_manager, render:
if (json.is_array())
{
// Create variable
auto variable = std::make_shared<render::material_texture_1d>(json.size());
auto variable = std::make_shared<render::matvar_texture_1d>(json.size());
// Load textures
std::size_t i = 0;
@ -156,7 +156,7 @@ static bool load_texture_1d_property(resource_manager& resource_manager, render:
else
{
// Create variable
auto variable = std::make_shared<render::material_texture_1d>(json.size());
auto variable = std::make_shared<render::matvar_texture_1d>(json.size());
// Load texture
variable->set(resource_manager.load<gl::texture_1d>(json.get<std::string>()));
@ -173,7 +173,7 @@ static bool load_texture_2d_property(resource_manager& resource_manager, render:
if (json.is_array())
{
// Create variable
auto variable = std::make_shared<render::material_texture_2d>(json.size());
auto variable = std::make_shared<render::matvar_texture_2d>(json.size());
// Load textures
std::size_t i = 0;
@ -188,7 +188,7 @@ static bool load_texture_2d_property(resource_manager& resource_manager, render:
else
{
// Create variable
auto variable = std::make_shared<render::material_texture_2d>(json.size());
auto variable = std::make_shared<render::matvar_texture_2d>(json.size());
// Load texture
variable->set(resource_manager.load<gl::texture_2d>(json.get<std::string>()));
@ -205,7 +205,7 @@ static bool load_texture_3d_property(resource_manager& resource_manager, render:
if (json.is_array())
{
// Create variable
auto variable = std::make_shared<render::material_texture_3d>(json.size());
auto variable = std::make_shared<render::matvar_texture_3d>(json.size());
// Load textures
std::size_t i = 0;
@ -220,7 +220,7 @@ static bool load_texture_3d_property(resource_manager& resource_manager, render:
else
{
// Create variable
auto variable = std::make_shared<render::material_texture_3d>(json.size());
auto variable = std::make_shared<render::matvar_texture_3d>(json.size());
// Load texture
variable->set(resource_manager.load<gl::texture_3d>(json.get<std::string>()));
@ -237,7 +237,7 @@ static bool load_texture_cube_property(resource_manager& resource_manager, rende
if (json.is_array())
{
// Create variable
auto variable = std::make_shared<render::material_texture_cube>(json.size());
auto variable = std::make_shared<render::matvar_texture_cube>(json.size());
// Load textures
std::size_t i = 0;
@ -252,7 +252,7 @@ static bool load_texture_cube_property(resource_manager& resource_manager, rende
else
{
// Create variable
auto variable = std::make_shared<render::material_texture_cube>(json.size());
auto variable = std::make_shared<render::matvar_texture_cube>(json.size());
// Load texture
variable->set(resource_manager.load<gl::texture_cube>(json.get<std::string>()));
@ -523,11 +523,11 @@ std::unique_ptr resource_loader::load(::reso
if (type.find("float") != std::string::npos)
{
if (columns == 2 && rows == 2)
load_matrix_property<float2x2>(*material, key, columns, rows, value_element.value());
load_matrix_property<math::fmat2>(*material, key, columns, rows, value_element.value());
else if (columns == 3 && rows == 3)
load_matrix_property<float3x3>(*material, key, columns, rows, value_element.value());
load_matrix_property<math::fmat3>(*material, key, columns, rows, value_element.value());
else if (columns == 4 && rows == 4)
load_matrix_property<float4x4>(*material, key, columns, rows, value_element.value());
load_matrix_property<math::fmat4>(*material, key, columns, rows, value_element.value());
}
}
// If variable type is a vector
@ -538,38 +538,38 @@ std::unique_ptr resource_loader::load(::reso
if (type.find("float") != std::string::npos)
{
if (size == 2)
load_vector_property<float2>(*material, key, size, value_element.value());
load_vector_property<math::fvec2>(*material, key, size, value_element.value());
else if (size == 3)
load_vector_property<float3>(*material, key, size, value_element.value());
load_vector_property<math::fvec3>(*material, key, size, value_element.value());
else if (size == 4)
load_vector_property<float4>(*material, key, size, value_element.value());
load_vector_property<math::fvec4>(*material, key, size, value_element.value());
}
else if (type.find("uint") != std::string::npos)
{
if (size == 2)
load_vector_property<uint2>(*material, key, size, value_element.value());
load_vector_property<math::uvec2>(*material, key, size, value_element.value());
else if (size == 3)
load_vector_property<uint3>(*material, key, size, value_element.value());
load_vector_property<math::uvec3>(*material, key, size, value_element.value());
else if (size == 4)
load_vector_property<uint4>(*material, key, size, value_element.value());
load_vector_property<math::uvec4>(*material, key, size, value_element.value());
}
else if (type.find("int") != std::string::npos)
{
if (size == 2)
load_vector_property<int2>(*material, key, size, value_element.value());
load_vector_property<math::ivec2>(*material, key, size, value_element.value());
else if (size == 3)
load_vector_property<int3>(*material, key, size, value_element.value());
load_vector_property<math::ivec3>(*material, key, size, value_element.value());
else if (size == 4)
load_vector_property<int4>(*material, key, size, value_element.value());
load_vector_property<math::ivec4>(*material, key, size, value_element.value());
}
else if (type.find("bool") != std::string::npos)
{
if (size == 2)
load_vector_property<bool2>(*material, key, size, value_element.value());
load_vector_property<math::bvec2>(*material, key, size, value_element.value());
else if (size == 3)
load_vector_property<bool3>(*material, key, size, value_element.value());
load_vector_property<math::bvec3>(*material, key, size, value_element.value());
else if (size == 4)
load_vector_property<bool4>(*material, key, size, value_element.value());
load_vector_property<math::bvec4>(*material, key, size, value_element.value());
}
}
// If variable type is a scalar

+ 3
- 3
src/engine/render/operation.hpp View File

@ -20,7 +20,7 @@
#ifndef ANTKEEPER_RENDER_OPERATION_HPP
#define ANTKEEPER_RENDER_OPERATION_HPP
#include <engine/utility/fundamental-types.hpp>
#include <engine/math/vector.hpp>
#include <engine/gl/vertex-array.hpp>
#include <engine/gl/drawing-mode.hpp>
#include <engine/render/material.hpp>
@ -41,11 +41,11 @@ struct operation
std::size_t index_count{0};
std::shared_ptr<render::material> material;
float4x4 transform{float4x4::identity()};
math::fmat4 transform{math::fmat4::identity()};
float depth{0.0f};
std::size_t instance_count{0};
std::span<const float4x4> matrix_palette{};
std::span<const math::fmat4> matrix_palette{};
};
} // namespace render

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save