vOOlkan
An object oriented approach to Vulkan
Universe.h
Go to the documentation of this file.
1#ifndef VULKAN_UNIVERSE
2#define VULKAN_UNIVERSE
3
4#include <vector>
5#include <variant>
6#include <typeinfo>
7
8#include "Hitbox.h"
9
10
11namespace Vulkan::Physics {
12
13
18 class Universe {
19 public:
20
27 template<typename... Hitboxes> requires (std::derived_from<Hitboxes, Hitbox> && ...)
28 Universe(std::vector<Field*> fields, Hitboxes&... hitboxes) : fields{ fields } {
29 (bodies.push_back(&hitboxes), ...);
30 }
31
32
33
39 void calculate(float elapsedSeconds) {
40 // 1. calculate forces for each object (i.e. fields)
41 calculateFieldForces();
42
43 // 2. collisions (detection and response)
44 collisionDetection(elapsedSeconds);
45
46 // 3. call move on each body
47 applyForces(elapsedSeconds);
48 }
49
50
51 void addBody(Hitbox& body) {
52 bodies.push_back(&body);
53 }
54
55 void removeBody(Hitbox& body) {
56 bodies.erase(std::remove(bodies.begin(), bodies.end(), &body), bodies.end());
57 }
58
59
60 private:
61
62 //Calculates the forces applied by the fields on the objects.
63 void calculateFieldForces() {
64 for (auto body : bodies) {
65 for (auto field : fields) {
66 body->addExternalForce(field->calculateAppliedForce(*body));
67 }
68 }
69 }
70
71
72 //Detects if there is any collision between 2 objects and in case resolves such collision.
73 void collisionDetection(Time elapsedSeconds) {
74 for (int i = 0; i < bodies.size(); ++i) {
75 for (int j = i + 1; j < bodies.size(); ++j) {
76 //if only C++ had multiple dynamic dispatch we wouldn't have to do this shit. Visitor is even worse.
77
78 //circle - circle collision
79 if (typeid(*bodies[i]) == typeid(CircleHitbox) && typeid(*bodies[j]) == typeid(CircleHitbox)) {
80 CircleHitbox& c1 = static_cast<CircleHitbox&>(*bodies[i]);
81 CircleHitbox& c2 = static_cast<CircleHitbox&>(*bodies[j]);
82 collisionDetection(c2, c1, elapsedSeconds);
83 }
84
85 //frame - circle collision
86 else if (typeid(*bodies[i]) == typeid(FrameHitbox) && typeid(*bodies[j]) == typeid(CircleHitbox)) {
87 FrameHitbox& f1 = static_cast<FrameHitbox&>(*bodies[i]);
88 CircleHitbox& c2 = static_cast<CircleHitbox&>(*bodies[j]);
89 collisionDetection(f1, c2, elapsedSeconds);
90 }
91
92 //circle - frame collision
93 else if (typeid(*bodies[i]) == typeid(CircleHitbox) && typeid(*bodies[j]) == typeid(FrameHitbox)) {
94 CircleHitbox& c1 = static_cast<CircleHitbox&>(*bodies[i]);
95 FrameHitbox& f2 = static_cast<FrameHitbox&>(*bodies[j]);
96 collisionDetection(f2, c1, elapsedSeconds);
97 }
98 }
99 }
100 }
101
102
103 //Applies all of the forces calculated till now.
104 void applyForces(Time elapsedSeconds) {
105 for (auto body : bodies) {
106 body->move(elapsedSeconds);
107 }
108 }
109
110
111
112 //Collider between 2 circles
113 static void collisionDetection(CircleHitbox& c1, CircleHitbox& c2, Time elapsedSeconds) {
114 auto distance = c1.getPosition() - c2.getPosition();
115 if ( distance <= c1.getRadius() + c2.getRadius()) {
116 //get speeds and masses (to simplify the writing of the equation
117 auto s1 = c1.getSpeed(); auto s2 = c2.getSpeed();
118 auto m1 = c1.getMass(); auto m2 = c2.getMass();
119 float e = 1.0f; //we simulate an elastic collision for now. This can vary based on materials.
120 auto n = glm::normalize(glm::vec3(c1.getPosition() - c2.getPosition())); //versor pointing the direction between the 2 centers
121
122 auto impulse = float((s2 - s1) * n * (-e - 1) * ((m1 * m2) / (m1 + m2)));
123 impulse *= 1.01; //FIXTHIS to avoid compenetration due to rounding errors
124
125 c1.addExternalForce(-(impulse * n) / elapsedSeconds);
126 c2.addExternalForce((impulse * n) / elapsedSeconds);
127
128 c1.onCollision(c2);
129 c2.onCollision(c1);
130 }
131 }
132
133
134 static void collisionDetection(FrameHitbox& f, CircleHitbox& c, Time elapsedSeconds) {
135 bool haveCollided = false; //turns true when at least one segment collided with the circle
136
137 for (int i = 0; i < f.getNumberOfSegments(); ++i) {
138 auto segment = f[i];
139 if (segment.distance(c.getPosition()) <= c.getRadius()) {
140 //get speeds and masses (to simplify the writing of the equation
141 auto s1 = c.getSpeed(); auto s2 = f.getSpeed();
142 auto m1 = c.getMass(); auto m2 = f.getMass();
143 float e = 1.0f; //we simulate an elastic collision for now. This can vary based on materials.
144 auto n = segment.normal(c.getPosition()); //normal to the segment, pointing to the segment
145
146 //very simplified rotation dynamics
147 auto sr2 = f.getAngularSpeed(); //in this simplified simulation, only frame hitboxes can rotate
148 auto distanceFromCenterOfRotation = glm::length(glm::vec3((c.getPosition() + n * c.getRadius()) - f.getPosition())); //distance of the colliding point from the center of rotation
149
150 auto tangentialSpeed = Speed(-segment.normal() * (sr2 * distanceFromCenterOfRotation)) * 1.1f; //"linear" speed of the point of the frame that touched the circle
151 auto massCoefficient = (m1 * m2) / (m1 + m2);
152 auto impulse = float(((s2 + tangentialSpeed - s1) * n) * (-e - 1) * massCoefficient);
153
154 f.addExternalForce((impulse * glm::vec3(n)) / elapsedSeconds); //rotational speed of the frame is not affected (simplification that can create problems)
155 c.addExternalForce(-(impulse * glm::vec3(n)) / elapsedSeconds);
156
157 haveCollided = true;
158 }
159 }
160
161 if (haveCollided) {
162 f.onCollision(c);
163 c.onCollision(f);
164 }
165 }
166
167
168
169
170 std::vector<Hitbox*> bodies;
171 std::vector<Field*> fields;
172
173 };
174}
175
176#endif
A Hitbox is a Cinematicable object which can directly interact with other objects upon collision.
Definition: Hitbox.h:19
A Universe is a container of Hitbox(es) and Field(s).
Definition: Universe.h:18
Universe(std::vector< Field * > fields, Hitboxes &... hitboxes)
Builds an isolated Universe.
Definition: Universe.h:28
void removeBody(Hitbox &body)
Definition: Universe.h:55
void calculate(float elapsedSeconds)
Calculates the new position of all the objects in the universe, their interaction with the other obje...
Definition: Universe.h:39
void addBody(Hitbox &body)
Definition: Universe.h:51
Definition: Cinematicable.h:9