Physics Simulation & Visualization Tool 0.1
A C++ physics simulation engine with real-time 3D visualization
Loading...
Searching...
No Matches
SceneObject.cpp
Go to the documentation of this file.
1#include "SceneObject.h"
2
3#include <iostream>
4#include <glm/gtc/matrix_transform.hpp>
5#include <glm/gtc/type_ptr.hpp>
7#include <math/Ray.h>
8#include "physics/PointMass.h"
11#include <QOpenGLVersionFunctionsFactory>
12#include <QOpenGLFunctions_4_5_Core>
13
14#include "ResourceManager.h"
16
17SceneObject::SceneObject(SceneManager* sceneMgr, const std::string &nameOfMesh, Shader *sdr, const CreationOptions &options, QObject* objectParent)
18 : shader(sdr), ownerScene(sceneMgr->scene), sceneManager(sceneMgr), objectID(sceneMgr->scene->allocateObjectID()), parent(objectParent), meshName(nameOfMesh) {
19 shader->use();
20 shader->setBool("isHovered", false);
21
22 assert((mesh = ResourceManager::getMesh(nameOfMesh)));
23
24 creationOptions = options;
25 std::visit([&](auto&& o) {
26 using T = std::decay_t<decltype(o)>;
27
28 if constexpr (std::is_same_v<T, ObjectOptions>) {
29 position = o.position;
30 scale = o.scale;
31 rotation = o.rotation;
32 } else if constexpr (std::is_same_v<T, PointMassOptions>) {
33 position = o.base.position;
34 scale = o.base.scale;
35 rotation = o.base.rotation;
36 physicsBody = std::make_unique<Physics::PointMass>(objectID, o.mass, o.base.position, o.isStatic);
37 physicsBody->setVelocity(o.velocity, BodyLock::LOCK);
38 //physicsBody->setUnknown("v0", true);
39 sceneManager->addToPhysicsSystem(physicsBody.get());
40 } else if constexpr (std::is_same_v<T, RigidBodyOptions>) {
41 position = o.base.position;
42 scale = o.base.scale;
43 rotation = o.base.rotation;
44 physicsBody = std::make_unique<Physics::RigidBody>(objectID, o.mass, o.createCollider(o.base), o.base.position, o.isStatic);
45 auto rb = static_cast<Physics::RigidBody*>(physicsBody.get());
46
47 std::span<const Vertex> meshVerts = mesh->getVertices();
48 std::vector<glm::vec3> verts(meshVerts.size());
49 for (size_t i = 0; i < meshVerts.size(); ++i) {
50 verts[i] = meshVerts[i].pos;
51 }
52
53 std::span<const unsigned int> meshInds = mesh->getIndices();
54 std::vector<unsigned int> inds(meshInds.data(), meshInds.data() + meshInds.size());
55
56 rb->setGeometry(verts, inds);
57 rb->setScale(o.base.scale);
58 physicsBody->setVelocity(o.velocity, BodyLock::LOCK);
59 sceneManager->addToPhysicsSystem(physicsBody.get());
60 } else {
61 std::cout << "Problem with CreationOptions on SceneObject construction!" << std::endl;
62 }
63 }, options);
64
65 orientation = glm::quat(rotation);
66 if (physicsBody) {
67 physicsBody->setWorldTransform(getModelMatrix(), BodyLock::LOCK);
68 }
69}
70
72 ownerScene->freeObjectID(objectID);
73 if (physicsBody) {
74 sceneManager->removeFromPhysicsSystem(physicsBody.get());
75 }
76}
77
78glm::mat4 SceneObject::getModelMatrix() const {
79 return buildModelMatrix(false);
80}
81
82glm::mat4 SceneObject::getRenderModelMatrix() const {
83 return buildModelMatrix(true);
84}
85
86glm::mat4 SceneObject::buildModelMatrix(bool relativeToRenderOrigin) const{
87 glm::vec3 currentPosition = position;
88 glm::vec3 origin(0.0f);
89 bool hasMappedPhysicsPosition = false;
90
91 {
92 std::lock_guard<std::mutex> lk(posMapMutex);
93 origin = renderOrigin;
94 if (physicsBody) {
95 auto it = posMap.find(physicsBody.get());
96 if (it != posMap.end()) {
97 currentPosition = it->second;
98 hasMappedPhysicsPosition = true;
99 }
100 }
101 }
102
103 if (physicsBody) {
104 if (!hasMappedPhysicsPosition) {
105 currentPosition = physicsBody->getPosition(BodyLock::LOCK);
106 }
107 }
108
109 if (relativeToRenderOrigin) {
110 currentPosition -= origin;
111 }
112
113 glm::mat4 model(1.0f);
114 model = glm::translate(model, currentPosition);
115 model = model * glm::mat4_cast(orientation);
116 model = glm::scale(model, scale);
117 return model;
118}
119
120std::optional<float> SceneObject::intersectsAABB(const Math::Ray& ray) const {
122 auto worldAABB = localAABB.getTransformed(getModelMatrix());
123
124 if (auto t = worldAABB->intersectRay(ray)) {
125 return t;
126 }
127
128 return std::nullopt;
129}
130
131std::optional<float> SceneObject::intersectsMesh(const Math::Ray& ray) const {
132 std::span<const Vertex> verts = mesh->getVertices();
133 std::vector<glm::vec3> vertPositions;
134 vertPositions.reserve(verts.size());
135 for (const auto& vert : verts) {
136 vertPositions.push_back({vert.pos});
137 }
138 const size_t triCount = verts.size() / 3;
139
140 std::span<const unsigned int> indices = mesh->getIndices();
141 auto *glFuncs = QOpenGLVersionFunctionsFactory::get<QOpenGLFunctions_4_5_Core>(QOpenGLContext::currentContext());
142 ComputeShader compute("assets/shaders/meshIntersection.comp", glFuncs);
143 (void) compute.createSSBO(vertPositions.data(), vertPositions.size() * sizeof(glm::vec3), 0);
144 (void) compute.createSSBO(indices.data(), indices.size() * sizeof(unsigned int), 1);
145 std::vector<float> initDists(triCount, -1.0f);
146 unsigned int distancesSSBO = compute.createSSBO(initDists.data(), initDists.size() * sizeof(float), 2);
147 compute.use();
148 compute.setVec3("rayOrig", ray.origin);
149 compute.setVec3("rayDir", ray.dir);
150 compute.setMat4("modelMatrix", getModelMatrix());
151
152 constexpr unsigned int groupSize = 64;
153 unsigned int groups = (triCount + groupSize - 1) / groupSize;
154 compute.dispatch(groups);
155
156 auto distances = compute.readSSBO<float>(distancesSSBO, triCount);
157 auto minIt = std::min_element(distances.begin(), distances.end());
158 if (minIt == distances.end()) {
159 return std::nullopt;
160 }
161 return *minIt;
162}
163
164
165
166std::optional<float> SceneObject::intersectsRay(const Math::Ray& ray) const {
167 auto tAABB = intersectsAABB(ray);
168 if (!tAABB)
169 return std::nullopt;
170
171 auto tTri = intersectsMesh(ray);
172 if (tTri) {
173 return *tTri;
174 }
175
176 return std::nullopt;
177}
178
179void SceneObject::handleClick(const Math::Ray& ray, float distance) {
180 sceneManager->setGizmoFor(this);
181}
182
183void SceneObject::setPosition(const glm::vec3 &pos) {
184 if (physicsBody) {
185 physicsBody->setPosition(pos, BodyLock::LOCK);
186 {
187 std::lock_guard<std::mutex> lk(posMapMutex);
188 posMap[physicsBody.get()] = pos;
189 }
190 physicsBody->setWorldTransform(getModelMatrix(), BodyLock::LOCK);
191 } else {
192 position = pos;
193 }
194}
195
196void SceneObject::setRotation(const glm::vec3 &euler) {
197 orientation = glm::quat(euler);
198 if (physicsBody)
199 physicsBody->setWorldTransform(getModelMatrix(), BodyLock::LOCK);
200}
201
202void SceneObject::setScale(const glm::vec3 &scl) {
203 scale = scl;
204 if (physicsBody) {
205 physicsBody->setWorldTransform(getModelMatrix(), BodyLock::LOCK);
206 auto rb = dynamic_cast<Physics::RigidBody*>(physicsBody.get());
207 if (rb) {
208 rb->setScale(scl);
209 }
210 }
211}
212
213glm::vec3 SceneObject::getPosition() const{
214 if (physicsBody)
215 return physicsBody->getPosition(BodyLock::NOLOCK);
216 return position;
217}
218
219glm::vec3 SceneObject::getRotation() const {
220 return glm::eulerAngles(orientation);
221}
222
224 return shader;
225}
226
227void SceneObject::setRotationQuat(const glm::quat &q) {
228 orientation = q;
229 if (physicsBody)
230 physicsBody->setWorldTransform(getModelMatrix(), BodyLock::LOCK);
231}
233 return orientation;
234}
235
236glm::vec3 SceneObject::getScale() const {
237 return scale;
238}
239
240void SceneObject::setHovered(bool hovered) {
241 isHovered = hovered;
242}
243
245 return isHovered;
246}
247
248uint32_t SceneObject::getObjectID() const {
249 return objectID;
250}
251
253 return {getRenderModelMatrix(), getObjectID(), glm::vec3(1.0f, 1.0f, 0.0f)};
254}
std::variant< ObjectOptions, PointMassOptions, RigidBodyOptions > CreationOptions
std::span< const Vertex > getVertices() const
Provides read-only view of vertex data without copying.
Definition Mesh.cpp:91
const Physics::Bounding::AABB & getLocalAABB() const
Gets the local-space axis-aligned bounding box.
Definition Mesh.h:163
std::span< const unsigned int > getIndices() const
Provides read-only view of index data without copying.
Definition Mesh.cpp:95
std::unique_ptr< ICollider > getTransformed(const glm::mat4 &modelMatrix) const override
Creates a transformed copy of this collider in world space.
Definition AABB.cpp:11
void setScale(const glm::vec3 &newScale)
Definition RigidBody.cpp:16
static Mesh * getMesh(const std::string &name)
void setGizmoFor(SceneObject *newTarget, bool redraw=false)
void removeFromPhysicsSystem(Physics::PhysicsBody *body) const
void addToPhysicsSystem(Physics::PhysicsBody *body) const
void setHovered(bool hovered) override
Sets the hover state of this object.
glm::mat4 getModelMatrix() const override
Gets the model transformation matrix for this instance.
glm::vec3 getRotation() const
void setScale(const glm::vec3 &scl)
glm::vec3 getPosition() const
glm::vec3 getScale() const
void handleClick(const Math::Ray &ray, float distance) override
Handles a mouse click on this object.
Rendering::InstanceData getInstanceData() const override
Gets the complete per-instance data for GPU upload.
void setRotation(const glm::vec3 &rot)
void setRotationQuat(const glm::quat &q)
SceneObject(SceneManager *sceneManager, const std::string &meshName, Shader *sdr, const CreationOptions &options, QObject *parent=nullptr)
glm::quat getRotationQuat() const
Shader * getShader() const override
Gets the shader used to render this object.
uint32_t getObjectID() const override
Gets the unique identifier for this object.
Mesh * getMesh() const override
Gets the mesh geometry for this object.
Definition SceneObject.h:46
void setPosition(const glm::vec3 &pos)
std::optional< float > intersectsRay(const Math::Ray &ray) const override
Tests if a ray intersects this object's geometry.
bool getHovered() const override
Gets the current hover state of this object.
void freeObjectID(uint32_t objID)
Definition Scene.cpp:87
Definition Shader.h:6
void use() const
Definition Shader.cpp:55
void setBool(const std::string &name, bool value) const
Definition Shader.cpp:59
glm::vec3 origin
Starting point of the ray in world space.
Definition Ray.h:12
glm::vec3 dir
Direction vector (should be normalized)
Definition Ray.h:13
Represents a ray in 3D space.
Definition Ray.h:11
Per-instance data for instanced rendering.