-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparticle.cpp
More file actions
95 lines (78 loc) · 2.55 KB
/
particle.cpp
File metadata and controls
95 lines (78 loc) · 2.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "particle.h"
#include <cmath>
float bgRadius = 295.0f;
sf::Vector2f bgPosition;
particle::particle(const sf::Vector2f &initialPosition, float r)
: currentPosition(initialPosition), oldPosition(initialPosition), acceleration(0.0f, 0.0f), radius(r) {
}
void particle::updatePosition(float dt) {
const sf::Vector2f velocity = currentPosition - oldPosition;
oldPosition = currentPosition;
currentPosition += velocity + acceleration * dt * dt;
acceleration = {};
}
void particle::accelerate(const sf::Vector2f &a) {
acceleration += a;
}
solver::solver() : gravity(0.0f, 500.0f) {
}
void solver::update(float dt) {
const uint32_t subSteps = 8;
const float sub_dt = dt / subSteps;
for (uint32_t i = subSteps; i > 0; --i) {
applyGravity();
applyConstraint();
solveCollisions();
updatePositions(sub_dt);
}
}
void solver::applyGravity() {
for (auto &obj : m_objects) {
obj.accelerate(gravity);
}
}
void solver::updatePositions(float dt) {
for (auto &obj : m_objects) {
obj.updatePosition(dt);
}
}
void solver::applyConstraint() {
for (auto &obj : m_objects) {
const sf::Vector2f v = obj.currentPosition - bgPosition;
const float distance = std::sqrt(v.x * v.x + v.y * v.y);
if (distance > bgRadius - obj.radius + 0.01f) {
const sf::Vector2f n = v / distance;
obj.currentPosition = bgPosition + n * (bgRadius - obj.radius);
}
}
}
void solver::solveCollisions() {
const uint64_t objsCount = m_objects.size();
for (uint64_t i = 0; i < objsCount; ++i) {
particle &object1 = m_objects[i];
for (uint64_t j = i + 1; j < objsCount; ++j) {
particle &object2 = m_objects[j];
const sf::Vector2f collisionAxis = object1.currentPosition - object2.currentPosition;
const float dist2 = (collisionAxis.x * collisionAxis.x + collisionAxis.y * collisionAxis.y);
const float minDist = object1.radius + object2.radius;
if (dist2 < minDist * minDist) {
const float dist = std::sqrt(dist2);
const sf::Vector2f n = collisionAxis / dist;
const float delta = minDist - dist;
object1.currentPosition += 0.5f * delta * n;
object2.currentPosition -= 0.5f * delta * n;
}
}
}
}
void solver::addParticle(const sf::Vector2f &position, float radius) {
m_objects.emplace_back(position, radius);
}
sf::CircleShape newParticle(solver &simulationSolver, const sf::Vector2f &position, float radius, sf::Color color) {
simulationSolver.addParticle(position, radius);
sf::CircleShape particleShape(radius);
particleShape.setFillColor(color);
particleShape.setOrigin(10.0f, 10.0f);
particleShape.setPosition(position);
return particleShape;
}