Fx2D
A C++20 2D rigid-body physics engine
Loading...
Searching...
No Matches
Entity.h
Go to the documentation of this file.
1
2#pragma once
3
4#include <memory>
5#include <stdexcept>
6#include <string>
7
8#include "Fx2D/Geometry.h"
9
10inline bool is_valid_name(const std::string& s) {
11 if (s.empty()) return false;
12 return std::all_of(s.begin(), s.end(), [](unsigned char c) {
13 return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
14 c == '_';
15 });
16}
17
18// container for visual shape
19struct FxVisualShape : public FxShape {
20 private:
21 FxVec4ui8 m_fillColor{200, 200, 200, 255}; // Fill color (RGBA)
22 FxVec4ui8 m_outlineColor{10, 10, 10, 255}; // Outline color (RGBA)
23 float m_outlineThickness = 2.5f; // Outline thickness in pixels
24 std::string m_fillTexturePath = ""; // File path to texture file (empty = no texture)
25 public:
26 // 1. "Inherit" all of FxShape's ctors
27 using FxShape::FxShape;
28 // 2. Conversion‐style ctor: build a VisualShape from any Shape
29 FxVisualShape(const FxShape& base) : FxShape(base) {}
30 // Method to set a fillColor, outlineColor and texture
31 void set_fillColor(const FxVec4ui8& color) {
32 m_fillColor = color;
33 m_fillTexturePath = "";
34 }
35 void set_outlineColor(const FxVec4ui8& color) { m_outlineColor = color; }
36 void set_outlineThickness(const float& thickness) { m_outlineThickness = thickness; }
37 void set_fillTexture(const std::string& filePath) { m_fillTexturePath = filePath; }
38 // getters for all the attributes
39 const FxVec4ui8& fillColor() const { return m_fillColor; }
40 const std::string& fillTexture() const { return m_fillTexturePath; }
41 const FxVec4ui8& outlineColor() const { return m_outlineColor; }
42 float outlineThickness() const { return m_outlineThickness; }
43};
44
45// container for collision shape
47
48// Class for entity attributes and methods
49class FxEntity {
50 private:
51 // unique identifier assigned by scene or registry
52 uint32_t m_entity_id = 0;
53
54 // unique name for an entity
55 std::string m_name;
56
57 // mass and inertia
58 float _mass = 1.0f;
59 float _inertia = 1.0f; // around center of mass
60 float _inv_mass = 1.0f;
61 float _inv_inertia = 1.0f;
62
63 // store initial state for reset
64 FxVec3f _init_pose{0, 0, 0};
65 FxVec3f _init_velocity{0, 0, 0};
66 FxVec3d m_pose_carry{0, 0, 0};
67 // Constraint-correction residual, separate so it cannot borrow the integration leftover.
68 FxVec3d m_correction_carry{0, 0, 0};
69
70 // visual and collision shapes
71 std::shared_ptr<FxCollisionShape> m_collision;
72 std::shared_ptr<FxVisualShape> m_visual = std::make_shared<FxVisualShape>();
73
74 // total resultant force and moment on the body
75 float m_eff_moment = 0.0f;
76 FxVec2f m_eff_force{0, 0};
77
78 // accumulated impulses for the current step
79 float m_eff_impulse_moment = 0.0f;
80 FxVec2f m_eff_impulse{0, 0};
81
82 // axis aligned bounding box in world coordinates
83 FxArray<float> m_bounding_box{-1.0f, -1.0f, -1.0f, -1.0f};
84
85 // sleep state tracking
86 float m_sleep_timer = 0.0f;
87 bool m_sleeping = false;
88
89 // Broad-phase bookkeeping, owned by FxEntityRegistry. Held on the entity rather than in a
90 // side map because the broad phase reads them once per entity per substep, and a hash
91 // lookup there is pure overhead on a value the entity can just carry.
92 int32_t m_broad_phase_node = -1; // leaf index in the registry's AABB tree, -1 = not in tree
93 int32_t m_packed_index = -1; // position in the registry's packed storage, -1 = unregistered
94
95 // update pose from velocity
96 void __update_pose(const double& step_dt);
97
98 public:
99 // current state (public interface - single precision)
100 FxVec3f pose{0, 0, 0}; // x, y, theta
101 FxVec3f velocity{0, 0, 0}; // velocity along x, y axis and angular velocity along z axis
102
103 // previous pose and velocity for tracking changes (public interface)
106
107 // physics config
108 float elasticity = 0.1f; // restitution mixes by max, so 1.0 made every
109 // unconfigured body a perfect trampoline
110 float vel_damping = 0.0f;
111 float gravity_scale = 1.0f;
112 float static_friction = 0.0f;
113 float dynamic_friction = 0.0f;
114
115 // entity state
116 bool enabled = true; // If false, entity is skipped in physics updates, collisions, and
117 // rendering
118 bool enable_ccd = false; // If true, speculative contacts are generated for this entity to
119 // prevent tunneling
120 bool is_sensor = false; // Detects overlaps but exchanges no impulses; reported as events
121 int32_t collision_group = 0; // Entities sharing a negative value never collide with each
122 // other; 0 means no group filtering
123
124 // sleep configuration
125 float sleep_threshold_linear = 0.01f; // linear speed below which entity may sleep
126 float sleep_threshold_angular = 0.05f; // angular speed below which entity may sleep
127 float sleep_time_required = 0.5f; // seconds of low motion before sleeping
128 bool is_sleeping() const { return m_sleeping; }
129 void wake() {
130 m_sleeping = false;
131 m_sleep_timer = 0.0f;
132 }
133 void sleep() { m_sleeping = true; }
134 void tick_sleep(float dt); // advance sleep timer; called by FxScene each step
135
136 // contructor with name validation
137 explicit FxEntity(const std::string& entityName);
138
139 // getter for the name and ID
140 const std::string& get_name() const { return m_name; }
141 uint32_t get_entity_id() const { return m_entity_id; }
142 void set_entity_id(uint32_t id) { m_entity_id = id; }
143
144 // Registry-owned broad-phase bookkeeping. These are written by FxEntityRegistry as entities
145 // are added, removed and inserted into the tree; nothing else should set them.
146 int32_t broad_phase_node() const { return m_broad_phase_node; }
147 void set_broad_phase_node(int32_t node) { m_broad_phase_node = node; }
148 int32_t packed_index() const { return m_packed_index; }
149 void set_packed_index(int32_t index) { m_packed_index = index; }
150
151 // resets current state to inital state
152 void reset();
153
154 // methods to set mass and inertia
155 void set_mass(const float& mass);
156 void set_inertia(); // calculate based on shape
157 void set_inertia(const float& inertia);
158 // methods to get mass and inertia
159 float mass() const { return _mass; }
160 float inertia() const { return _inertia; }
161 float inv_mass() const { return _inv_mass; }
162 float inv_inertia() const { return _inv_inertia; }
163
164 // methods to set initial pose and velocity
165 void set_init_pose(const FxVec3f& o_pose);
166 void set_init_velocity(const FxVec3f& o_velocity);
167 // Enable or disable external forces and torques, including effects due to collisions
168 void enable_external_forces(bool enable);
169
170 // clear existing visual and collison shapes and assign new
172 m_visual = std::make_shared<FxVisualShape>(std::move(visual));
173 m_visual->set_world_pose(pose);
174 }
176 m_collision = std::make_shared<FxCollisionShape>(std::move(collision));
177 // Filled here, not left to the first integration: an immovable body may never
178 // integrate at all, and a box still at its {-1,-1,-1,-1} default is rejected by the
179 // broad phase and silently collides with nothing.
180 m_collision->set_world_pose(pose, m_bounding_box);
181 }
182 // getters for visual and collison shapes
183 // By reference: returning by value cost an atomic pair per call, and the broad and narrow
184 // phases call these several times per pair per substep. Valid until the shape is replaced.
185 const std::shared_ptr<FxVisualShape>& visual_geometry() const { return m_visual; }
186 const std::shared_ptr<FxCollisionShape>& collision_geometry() const { return m_collision; }
187 // methods to delete visual and collision shapes
188 void del_visual_geometry() { m_visual.reset(); };
189 void del_collision_geometry() { m_collision.reset(); };
190
191 // collision detection methods
192 // By reference: returning the FxArray by value made every narrow-phase pair allocate.
194 bool aabb_overlap_check(const FxEntity& other) const;
195 bool aabb_overlap_check(const std::shared_ptr<FxEntity>& other) const;
196
197 // apply external influences
198 void apply_torque(float torque);
199 void apply_force(const FxVec2f& force);
200 void apply_force(const FxVec2f& force, const FxVec2f& contact_point);
201 void apply_impulse(const FxVec2f& impulse);
202 void apply_impulse(const FxVec2f& impulse, const FxVec2f& contact_point);
203
204 // Get instantaneous velocity at a specific position
206 FxVec2f velocity_at_local_point(const FxVec2f& local_position) const;
207 // Vector implementations of above
210
211 // Convert local point to world coordinates and vice-versa
212 FxVec2f to_world_frame(const FxVec2f& local_point) const;
213 FxVec2f to_entity_frame(const FxVec2f& world_point) const;
214
215 // resolve the forces and torques and calculate acceleration;
218
219 // Mixed-precision positional correction, returning the delta that landed so prev_pose can
220 // be shifted to match. Sub-ulp corrections are banked in double rather than rounded away.
222
223 void step(const FxVec2f& gravity, const double& step_dt);
224
226};
bool is_valid_name(const std::string &s)
Definition Entity.h:10
Fixed-size, aligned value array.
Definition Math.h:694
A named rigid body with state, material properties, geometry, and forces.
Definition Entity.h:49
void set_init_pose(const FxVec3f &o_pose)
void apply_impulse(const FxVec2f &impulse)
int32_t packed_index() const
Definition Entity.h:148
FxVec3f apply_pose_correction(const FxVec3f &delta)
void step(const FxVec2f &gravity, const double &step_dt)
float gravity_scale
Definition Entity.h:111
float vel_damping
Definition Entity.h:110
float inv_mass() const
Definition Entity.h:161
bool enable_ccd
Definition Entity.h:118
void reset()
~FxEntity()
Definition Entity.h:225
FxVec2f velocity_at_local_point(const FxVec2f &local_position) const
void set_mass(const float &mass)
const std::shared_ptr< FxCollisionShape > & collision_geometry() const
Definition Entity.h:186
void set_inertia(const float &inertia)
bool aabb_overlap_check(const std::shared_ptr< FxEntity > &other) const
void sleep()
Definition Entity.h:133
float sleep_threshold_linear
Definition Entity.h:125
int32_t broad_phase_node() const
Definition Entity.h:146
float sleep_threshold_angular
Definition Entity.h:126
FxVec2f to_entity_frame(const FxVec2f &world_point) const
void set_packed_index(int32_t index)
Definition Entity.h:149
void apply_force(const FxVec2f &force)
FxVec2fArray velocity_at_local_point(const FxVec2fArray &local_position) const
void set_entity_id(uint32_t id)
Definition Entity.h:142
float mass() const
Definition Entity.h:159
const std::shared_ptr< FxVisualShape > & visual_geometry() const
Definition Entity.h:185
bool is_sensor
Definition Entity.h:120
bool aabb_overlap_check(const FxEntity &other) const
void del_visual_geometry()
Definition Entity.h:188
FxVec2f to_world_frame(const FxVec2f &local_point) const
float inertia() const
Definition Entity.h:160
void set_inertia()
void del_collision_geometry()
Definition Entity.h:189
void set_collision_geometry(FxCollisionShape collision)
Definition Entity.h:175
float sleep_time_required
Definition Entity.h:127
FxVec2fArray velocity_at_world_point(const FxVec2fArray &position) const
float elasticity
Definition Entity.h:108
void enable_external_forces(bool enable)
FxVec3f prev_velocity
Definition Entity.h:105
float dynamic_friction
Definition Entity.h:113
FxVec3f calc_acceleration()
void wake()
Definition Entity.h:129
uint32_t get_entity_id() const
Definition Entity.h:141
FxVec3f pose
Definition Entity.h:100
const FxArray< float > & bounding_box() const
FxEntity(const std::string &entityName)
int32_t collision_group
Definition Entity.h:121
void apply_force(const FxVec2f &force, const FxVec2f &contact_point)
void set_init_velocity(const FxVec3f &o_velocity)
void set_visual_geometry(FxVisualShape visual)
Definition Entity.h:171
FxVec3f calc_acceleration(const FxVec2f &gravity)
const std::string & get_name() const
Definition Entity.h:140
FxVec2f velocity_at_world_point(const FxVec2f &position) const
FxVec3f velocity
Definition Entity.h:101
void set_broad_phase_node(int32_t node)
Definition Entity.h:147
float static_friction
Definition Entity.h:112
FxVec3f prev_pose
Definition Entity.h:104
float inv_inertia() const
Definition Entity.h:162
void tick_sleep(float dt)
void apply_impulse(const FxVec2f &impulse, const FxVec2f &contact_point)
bool is_sleeping() const
Definition Entity.h:128
bool enabled
Definition Entity.h:116
void apply_torque(float torque)
Single-precision 2D vector.
Definition Math.h:47
Double-precision three-component vector.
Definition Math.h:195
Single-precision three-component vector, including poses.
Definition Math.h:159
Unified circle, capsule, polygon, edge, and chain representation.
Definition Geometry.h:46
FxShape()
Definition Geometry.h:86
const std::string & fillTexture() const
Definition Entity.h:40
void set_fillTexture(const std::string &filePath)
Definition Entity.h:37
void set_outlineThickness(const float &thickness)
Definition Entity.h:36
float outlineThickness() const
Definition Entity.h:42
FxVisualShape(const FxShape &base)
Definition Entity.h:29
void set_fillColor(const FxVec4ui8 &color)
Definition Entity.h:31
const FxVec4ui8 & fillColor() const
Definition Entity.h:39
void set_outlineColor(const FxVec4ui8 &color)
Definition Entity.h:35
const FxVec4ui8 & outlineColor() const
Definition Entity.h:41