1 #include "hx3d/physics/2d/world.hpp" 3 #include "hx3d/graphics/sprite.hpp" 5 #include "hx3d/math/vector_utils.hpp" 6 #include "hx3d/utils/algorithm.hpp" 13 World::World(
const glm::vec2 globalGravity,
const unsigned int iterations,
const float physRatio):
14 _iterations(iterations), _physRatio(physRatio)
16 _attractors.emplace_back(Make<GlobalAttractor>(globalGravity));
20 _attractors.push_back(attractor);
24 _colliders.push_back(collider);
28 _listeners.push_back(listener);
32 _colliders.erase(std::remove(_colliders.begin(), _colliders.end(), collider), _colliders.end());
40 for (
unsigned int i = 0; i < _colliders.size(); ++i) {
43 for (
unsigned int j = i+1; j < _colliders.size(); ++j) {
45 if (a->massData.invMass == 0 && b->massData.invMass == 0)
56 if ((m.
a->mask & m.
b->category) || (m.
b->mask & m.
a->category)) {
59 if (m.
a->category != 0 && m.
b->category != 0)
63 if (prevContactExists(m)) {
67 listener->duringCollision(m);
74 listener->beginCollision(m);
79 _contacts.push_back(m);
88 _inPrevContact.clear();
92 for (
unsigned int i = 0; i < _colliders.size(); ++i) {
93 integrateForces(_colliders[i], dt);
96 for (
unsigned int i = 0; i < _contacts.size(); ++i) {
97 _contacts[i].initialize();
100 for (
unsigned int j = 0; j < _iterations; ++j) {
101 for (
unsigned int i = 0; i < _contacts.size(); ++i) {
102 _contacts[i].applyImpulse();
106 for (
unsigned int i = 0; i < _colliders.size(); ++i) {
107 integrateVelocity(_colliders[i], dt);
110 for (
unsigned int i = 0; i < _contacts.size(); ++i) {
111 _contacts[i].positionalCorrection();
114 for (
unsigned int i = 0; i < _colliders.size(); ++i) {
117 c->gravityForce = {0.f, 0.f};
124 for (
unsigned int i = 0; i < _attractors.size(); ++i) {
131 sprite.transform.position.x = zone->position.x * _physRatio;
132 sprite.transform.position.y = zone->position.y * _physRatio;
133 sprite.transform.position.z = -0.25f;
134 sprite.transform.size.x = zone->width * _physRatio;
135 sprite.transform.size.y = zone->height * _physRatio;
137 sprite.setTint(
Color(240, 20, 201));
145 sprite.transform.position.x = point->position.x * _physRatio;
146 sprite.transform.position.y = point->position.y * _physRatio;
147 sprite.transform.position.z = -0.25f;
148 sprite.transform.size.x = point->radius * 2 * _physRatio;
149 sprite.transform.size.y = point->radius * 2 * _physRatio;
151 sprite.setTint(
Color(20, 240, 201));
156 for (
unsigned int i = 0; i < _colliders.size(); ++i) {
168 float h = b->vertices[2].y * 2;
190 for (
unsigned int i = 0; i < _contacts.size(); ++i) {
193 for (
unsigned int j = 0; j < m.
contacts.size(); ++j) {
194 const glm::vec2& contact = m.
contacts[j];
209 for (
unsigned int i = 0; i < _contacts.size(); ++i) {
212 for (
unsigned int j = 0; j < m.
contacts.size(); ++j) {
213 const glm::vec2& contact = m.
contacts[j];
239 return _collisionMatrix;
244 void World::integrateForces(
const Ptr<Collider>& c,
float dt) {
245 if (c->massData.invMass == 0.f)
248 for (
auto attractor: _attractors) {
253 c->velocity += ((c->force * c->massData.invMass) + (c->gravityForce * 2.f)) * (dt / 2.f);
254 if (!c->fixedRotation) {
255 c->angularVelocity += c->torque * c->massData.invInertia * (dt / 2.f);
259 void World::integrateVelocity(
const Ptr<Collider>& c,
float dt) {
263 c->position += c->velocity * dt;
280 if (!c->fixedRotation) {
281 c->orientation += c->angularVelocity * dt;
282 c->setOrientation(c->orientation);
285 integrateForces(c, dt);
288 bool World::prevContactExists(
Manifold& m) {
290 for (
auto& ma: _inPrevContact) {
291 if (ma.a == m.
a && ma.b == m.
b)
301 void World::checkOldContacts() {
302 std::set<Manifold> diffSet;
303 for (
auto& manif: _inPrevContact) {
305 for (
auto& curr: _contacts) {
306 if (curr.a == manif.a && curr.b == manif.b) {
312 diffSet.insert(manif);
318 listener->endCollision(manif);
void clone(Source &src, Dest &dst)
Clone a container.
Static: no forces or velocity.
void setTint(Color tint)
Set the mesh tint.
void addListener(const Ptr< CollisionListener > &listener)
Add a collision listener.
virtual void draw(Mesh &mesh)=0
Draw the mesh.
Four [0..255] components defined color.
void setTexture(const Ptr< Texture > &texture)
Set the sprite texture.
static void applyForce(const Ptr< Collider > &collider, const Ptr< Attractor > &attractor, const float dt)
Apply an attractor force on a collider.
Kinematic: no forces but velocity.
void addAttractor(const Ptr< Attractor > &attractor)
Add an attractor.
std::vector< glm::vec2 > contacts
Contact points.
2D and 3D graphics components.
CollisionMatrix & getCollisionMatrix()
Get the collision matrix.
Ptr< Collider > b
Second collider.
void render(graphics::BaseBatch &batch)
Render a debug view of the physical simulation.
std::vector< glm::vec2 > vertices
Vertices.
Collision matrix with masks and category.
bool disabled
Is the contact disabled ?
bool solve()
Solve the contact.
Contact manifold definition.
Transform transform
Mesh transformation.
Ptr< Collider > a
First collider.
float angleBetweenVecs(const glm::vec2 vec1, const glm::vec2 vec2)
Compute the angle between two 2D vectors.
void apply(Container &container, Function func)
Function application helper on a container.
const Ptr< GlobalAttractor > getGlobalGravity()
Get the global attractor.
float getPhysRatio() const
Get the physical ratio.
Draw meshes and texts on screen.
Polygon or box shaped collider.
void removeCollider(const Ptr< Collider > &collider)
Remove a collider.
void step(float dt=1.f/60.f)
Step the physical simulation.
std::shared_ptr< T > Ptr
Quick-typing shared ptr.
glm::vec2 normal
Normal vector.
void addCollider(const Ptr< Collider > &collider)
Add a collider.