Physics Simulation & Visualization Tool 0.1
A C++ physics simulation engine with real-time 3D visualization
Loading...
Searching...
No Matches
PointMass.cpp
Go to the documentation of this file.
1#include "PointMass.h"
2#include <algorithm>
3#include <iostream>
4
5#include "RigidBody.h"
7
8namespace {
9constexpr float kPointMassCollisionDistance = 0.01f;
10constexpr double kContactAreaFraction = 0.01;
11constexpr double kContactConductionDistance = 0.01;
12}
13
14Physics::PointMass::PointMass(uint32_t id, double m, glm::vec3 pos, bool bodyStatic) : PhysicsBody(id) {
15 std::lock_guard<std::mutex> lock(stateMutex);
18 setIsStatic(bodyStatic, BodyLock::NOLOCK);
19 setVelocity(glm::vec3(0.0f), BodyLock::NOLOCK);
20 recomputeSurfaceArea();
21}
22
23Physics::PointMass::PointMass(uint32_t id, glm::vec3 pos, bool bodyStatic) : PhysicsBody(id) {
24 std::lock_guard<std::mutex> lock(stateMutex);
26 setIsStatic(bodyStatic, BodyLock::NOLOCK);
28 recomputeSurfaceArea();
29}
30
31void Physics::PointMass::setMass(double newMass, BodyLock lock) {
32 std::unique_lock<std::mutex> maybeLock;
33 if (lock == BodyLock::LOCK)
34 maybeLock = std::unique_lock<std::mutex>(stateMutex);
35
37 recomputeSurfaceArea();
38}
39
41 std::unique_lock<std::mutex> maybeLock;
42 if (lock == BodyLock::LOCK)
43 maybeLock = std::unique_lock<std::mutex>(stateMutex);
44
46 recomputeSurfaceArea();
47}
48
49void Physics::PointMass::recomputeSurfaceArea() {
50 double curMass = getMass(BodyLock::NOLOCK);
51 const ThermalProperties props = getThermalProperties(BodyLock::NOLOCK);
52 double density = Physics::Thermal::effectiveDensity(props, props.tempK);
53 if (density > 0.0f) {
54 double volume = curMass / density;
55 float radius = std::cbrt((3.0f * volume) / (4.0f * glm::pi<float>()));
56 surfaceArea = 4.0f * glm::pi<float>() * radius * radius;
57 }
58}
59
60void Physics::PointMass::applyImpulse(const glm::vec3 &impulse, BodyLock lock) {
61 glm::vec3 curVel;
62 double curMass;
63
64 std::unique_lock<std::mutex> maybeLock;
65 if (lock == BodyLock::LOCK)
66 maybeLock = std::unique_lock<std::mutex>(stateMutex);
67
68 curVel = getVelocity(BodyLock::NOLOCK);
69 curMass = getMass(BodyLock::NOLOCK);
70
71 setVelocity(curVel + impulse * static_cast<float>(1.0 / curMass), BodyLock::NOLOCK);
72}
73
75 std::unique_lock<std::mutex> maybeLock;
76 if (lock == BodyLock::LOCK)
77 maybeLock = std::unique_lock<std::mutex>(stateMutex);
78
79 frames.push_back( {this, t, getPosition(BodyLock::NOLOCK), getVelocity(BodyLock::NOLOCK), static_cast<float>(getThermalProperties(BodyLock::NOLOCK).tempK)} );
80}
81
83 std::unique_lock<std::mutex> maybeLock;
84 if (lock == BodyLock::LOCK)
85 maybeLock = std::unique_lock<std::mutex>(stateMutex);
86
87 setPosition(snapshot.position, BodyLock::NOLOCK);
88 setVelocity(snapshot.velocity, BodyLock::NOLOCK);
89 ThermalProperties props = getThermalProperties(BodyLock::NOLOCK);
90 props.tempK = snapshot.temperature;
91 setThermalProperty(props, BodyLock::NOLOCK);
92}
93
94void Physics::PointMass::step(float dt, BodyLock lock) {
95 std::unique_lock<std::mutex> maybeLock;
96 if (lock == BodyLock::LOCK)
97 maybeLock = std::unique_lock<std::mutex>(stateMutex);
98
99 glm::vec3 acceleration = getNetForce(BodyLock::NOLOCK) / static_cast<float>(getMass(BodyLock::NOLOCK));
100 setPosition(getPosition(BodyLock::NOLOCK) + (getVelocity(BodyLock::NOLOCK) * dt + 0.5f * acceleration * dt * dt), BodyLock::NOLOCK);
101 glm::vec3 newAcceleration = getNetForce(BodyLock::NOLOCK) / static_cast<float>(getMass(BodyLock::NOLOCK)); // if netForce changed during the step
102 setVelocity(getVelocity(BodyLock::NOLOCK) + 0.5f * (acceleration + newAcceleration) * dt, BodyLock::NOLOCK);
103}
104
106 return other.collidesWithPointMass(*this);
107}
108
110 return glm::distance(getPosition(BodyLock::LOCK), pm.getPosition(BodyLock::LOCK)) <= kPointMassCollisionDistance;
111}
112
114 return rb.collidesWithPointMass(*this);
115}
116
118 return other.resolveCollisionWithPointMass(dt, *this);
119}
120
122 // elastic collision
123 // compute normal and relative velocity
124 std::lock_guard<std::mutex> lock(stateMutex);
125 glm::vec3 normal = glm::normalize(pm.getPosition(BodyLock::NOLOCK) - getPosition(BodyLock::NOLOCK));
126 glm::vec3 relVel = pm.getVelocity(BodyLock::NOLOCK) - getVelocity(BodyLock::NOLOCK);
127 float velNorm = glm::dot(relVel, normal);
128
129 if (velNorm <= 0.0f)
130 return false; // moving apart, nothing applied
131
132 float j = (2.0f * velNorm) / static_cast<float>(getMass(BodyLock::NOLOCK) + pm.getMass(BodyLock::NOLOCK)); // collision impulse scalar
133 glm::vec3 impulse = j * normal;
134
135 // newton's third law
136 applyImpulse(impulse, BodyLock::NOLOCK);
137 pm.applyImpulse(-impulse, BodyLock::NOLOCK);
138
139 // Contact conduction
140 ThermalProperties myProps = getThermalProperties(BodyLock::NOLOCK);
142 const double contactArea = kContactAreaFraction * std::min(getSurfaceArea(), pm.getSurfaceArea());
143 const double distance = kContactConductionDistance;
145 myProps, getMass(BodyLock::NOLOCK),
146 pmProps, pm.getMass(BodyLock::NOLOCK),
147 contactArea, distance, dt
148 );
149
150 setThermalProperty(myProps, BodyLock::NOLOCK);
152
153 return true;
154}
155
glm::vec3 velocity
Definition PhysicsBody.h:38
BodyLock
Definition PhysicsBody.h:25
glm::vec3 position
Definition PhysicsBody.h:37
virtual double getMass(BodyLock lock) const
virtual bool collidesWithPointMass(const PointMass &pm) const =0
void setPosition(const glm::vec3 &pos, BodyLock lock)
float getSurfaceArea() const
Definition PhysicsBody.h:71
glm::vec3 getVelocity(BodyLock lock) const
virtual ThermalProperties getThermalProperties(BodyLock lock) const
void setVelocity(const glm::vec3 &vel, BodyLock lock)
glm::vec3 getPosition(BodyLock lock) const
std::mutex stateMutex
Definition PhysicsBody.h:96
virtual void setMass(double newMass, BodyLock lock)
virtual void setThermalProperty(const ThermalProperties &newProps, BodyLock lock)
virtual bool resolveCollisionWithPointMass(float dt, PointMass &pm)=0
void setIsStatic(bool newStatic, BodyLock lock)
void recordFrame(float t, BodyLock lock) override
Definition PointMass.cpp:74
void step(float dt, BodyLock lock) override
Definition PointMass.cpp:94
void setMass(double newMass, BodyLock lock) override
Definition PointMass.cpp:31
bool collidesWithRigidBody(const RigidBody &rb) const override
bool collidesWith(const PhysicsBody &other) const override
bool resolveCollisionWithRigidBody(float dt, RigidBody &rb) override
bool resolveCollisionWith(float dt, PhysicsBody &other) override
void loadFrame(const ObjectSnapshot &snapshot, BodyLock lock) override
Definition PointMass.cpp:82
bool resolveCollisionWithPointMass(float dt, PointMass &pm) override
void applyImpulse(const glm::vec3 &impulse, BodyLock lock)
Definition PointMass.cpp:60
void setThermalProperty(const ThermalProperties &newProps, BodyLock lock) override
Definition PointMass.cpp:40
bool collidesWithPointMass(const PointMass &pm) const override
PointMass(uint32_t id, double m, glm::vec3 pos=glm::vec3(0.0f), bool isStatic=false)
Definition PointMass.cpp:14
bool collidesWithPointMass(const PointMass &pm) const override
Definition RigidBody.cpp:98
bool resolveCollisionWithPointMass(float dt, PointMass &pm) override
void applyConductiveExchange(ThermalProperties &a, double massA, ThermalProperties &b, double massB, double areaM2, double distanceM, double dt)
double effectiveDensity(const ThermalProperties &props, double tempK)