Physics Simulation & Visualization Tool 0.1
A C++ physics simulation engine with real-time 3D visualization
Loading...
Searching...
No Matches
ResourceManager.cpp
Go to the documentation of this file.
1#include "ResourceManager.h"
2#include <math/MathUtils.h>
3#include <fstream>
4#include <sstream>
5#include <unordered_map>
6#include <glm/ext/scalar_constants.hpp>
7#include <glm/gtc/constants.hpp>
8
9void ResourceManager::initialize(QOpenGLFunctions_4_5_Core *funcs) {
10 glFuncs = funcs;
11}
12
13Shader* ResourceManager::loadShader(const std::string &vShaderPath, const std::string &fShaderPath, const std::string &name) {
14 assert(glFuncs && "QOpenGLFunctions not initialized!");
15 return &shaders.try_emplace(name, vShaderPath, fShaderPath, glFuncs).first->second;
16}
17
18Mesh* ResourceManager::loadMesh(const std::vector<Vertex>& verts, const std::vector<unsigned int>& idx, const std::string &name) {
19 assert(glFuncs && "QOpenGLFunctions not initialized!");
20 return &meshes.try_emplace(name, verts, idx, glFuncs).first->second;
21}
22
23Mesh *ResourceManager::loadMeshFromOBJ(const std::string &path, const std::string &name) {
24 std::vector<Vertex> vertices;
25 std::vector<unsigned int> indices;
26 if (loadOBJ(path, vertices, indices)) {
27 return loadMesh(vertices, indices, name);
28 }
29 return nullptr;
30}
31
32
33Shader* ResourceManager::getShader(const std::string &name) {
34 auto it = shaders.find(name);
35 if (it != shaders.end()) {
36 return &it->second;
37 } else {
38 return nullptr;
39 }
40}
41
42std::string ResourceManager::getShaderName(const Shader *target) {
43 for (const auto& [name, shader] : shaders) {
44 if (&shader == target) return name;
45 }
46 assert(false && "Shader not found in ResourceManager!");
47}
48
49Mesh* ResourceManager::getMesh(const std::string &name) {
50 auto it = meshes.find(name);
51 if (it != meshes.end()) {
52 return &it->second;
53 } else {
54 return nullptr;
55 }
56}
57
58// Expects triangulated obj files!
59bool ResourceManager::loadOBJ(const std::string &path, std::vector<Vertex> &outVertices, std::vector<unsigned int> &outIndices) {
60 std::ifstream file(path);
61 if (!file.is_open()) return false;
62
63 std::vector<glm::vec3> positions;
64 std::vector<glm::vec3> normals;
65
66 std::unordered_map<Vertex, unsigned int> vertexToIndex;
67
68 std::string line;
69 while (std::getline(file, line)) {
70 std::istringstream iss(line);
71 std::string type;
72 iss >> type;
73
74 if (type == "v") {
75 glm::vec3 pos;
76 iss >> pos.x >> pos.y >> pos.z;
77 positions.push_back(pos);
78 } else if (type == "vt") {
79 // glm::vec2 uv;
80 // iss >> uv.x >> uv.y;
81 // texCoords.push_back(uv);
82 } else if (type == "vn") {
83 glm::vec3 norm;
84 iss >> norm.x >> norm.y >> norm.z;
85 normals.push_back(norm);
86 } else if (type == "f") {
87 std::string vertexStr;
88 while (iss >> vertexStr) {
89 std::istringstream vss(vertexStr);
90 std::string idxStr;
91 int posIdx = 0, uvIdx = 0, normIdx = 0;
92
93 std::getline(vss, idxStr, '/');
94 posIdx = std::stoi(idxStr);
95
96 if (std::getline(vss, idxStr, '/') && !idxStr.empty())
97 uvIdx = std::stoi(idxStr);
98 if (std::getline(vss, idxStr, '/'))
99 normIdx = std::stoi(idxStr);
100
101 Vertex vertex{};
102 vertex.pos = positions[posIdx - 1];
103 //if (uvIdx) vertex.texCoord = texCoords[uvIdx - 1];
104 if (normIdx) vertex.normal = normals[normIdx - 1];
105
106 if (vertexToIndex.count(vertex) == 0) {
107 vertexToIndex[vertex] = static_cast<unsigned int>(outVertices.size());
108 outVertices.push_back(vertex);
109 }
110
111 outIndices.push_back(vertexToIndex[vertex]);
112 }
113 }
114 }
115
116 return true;
117}
118
119// Primitive loading
121 loadPrimCube();
122 loadPrimSphere();
123 loadMeshFromOBJ("assets/models/Arrow.obj", "gizmo_translate");
124 loadMeshFromOBJ("assets/models/Scale.obj", "gizmo_scale");
125 loadMeshFromOBJ("assets/models/Rotate.obj", "gizmo_rotate");
126}
127
128void ResourceManager::loadPrimCube() {
129 std::vector<Vertex> vertices = {
130 { {-0.5f, -0.5f, -0.5f}, {0.0f,0.0f,0.0f}},
131 { {0.5f, -0.5f, -0.5f}, {0.0f,0.0f,0.0f}},
132 { {0.5f, 0.5f, -0.5f}, {0.0f,0.0f,0.0f}},
133 { {-0.5f, 0.5f, -0.5f}, {0.0f,0.0f,0.0f}},
134 { {-0.5f, -0.5f, 0.5f}, {0.0f,0.0f,0.0f}},
135 { {0.5f, -0.5f, 0.5f}, {0.0f,0.0f,0.0f}},
136 { {0.5f, 0.5f, 0.5f}, {0.0f,0.0f,0.0f}},
137 { {-0.5f, 0.5f, 0.5f}, {0.0f,0.0f,0.0f}}
138 };
139
140 std::vector<unsigned int> indices {
141 0, 1, 2,
142 0, 3, 2,
143 0, 1, 5,
144 0, 4, 5,
145 0, 4, 7,
146 0, 3, 7,
147 1, 2, 6,
148 1, 5, 6,
149 2, 3, 7,
150 2, 6, 7,
151 4, 5, 6,
152 4, 7, 6
153 };
154
155 loadMesh(vertices, indices, "prim_cube");
156}
157
158void ResourceManager::loadPrimSphere() {
159 std::vector<Vertex> vertices;
160 std::vector<unsigned int> indices;
161
162 unsigned int latitudeSegments = 64;
163 unsigned int longitudeSegments = 64;
164
165 // 1) Generate vertices
166 for (unsigned int y = 0; y <= latitudeSegments; ++y) {
167 float v = float(y) / latitudeSegments;
168 float theta = v * glm::pi<float>();
169
170 for (unsigned int x = 0; x <= longitudeSegments; ++x) {
171 float u = float(x) / longitudeSegments;
172 float phi = u * glm::two_pi<float>();
173
174 // spherical to Cartesian
175 float sinT = std::sin(theta);
176 auto pos = glm::vec3(sinT * std::cos(phi), std::cos(theta), sinT * std::sin(phi)) * 0.5f;
177
178 glm::vec3 normal = glm::normalize(pos);
179
180 vertices.push_back({ pos, normal });
181 }
182 }
183
184 // 2) Generate indices
185 // we create quads between each (y, x) and (y+1, x+1) and split each quad into two tris
186 for (unsigned int y = 0; y < latitudeSegments; ++y) {
187 for (unsigned int x = 0; x < longitudeSegments; ++x) {
188 // indices to the four corners of this quad
189 unsigned int i0 = y * (longitudeSegments + 1) + x;
190 unsigned int i1 = (y + 1) * (longitudeSegments + 1) + x;
191 unsigned int i2 = (y + 1) * (longitudeSegments + 1) + (x + 1);
192 unsigned int i3 = y * (longitudeSegments + 1) + (x + 1);
193
194 // lower‐left triangle (i0, i1, i2)
195 indices.push_back(i0);
196 indices.push_back(i1);
197 indices.push_back(i2);
198
199 // upper‐right triangle (i0, i2, i3)
200 indices.push_back(i0);
201 indices.push_back(i2);
202 indices.push_back(i3);
203 }
204 }
205 loadMesh(vertices, indices, "prim_sphere");
206}
Mathematical utility functions for 3D graphics and physics.
GPU mesh representation with support for instanced rendering.
Definition Mesh.h:58
static void initialize(QOpenGLFunctions_4_5_Core *funcs)
static Mesh * loadMesh(const std::vector< Vertex > &verts, const std::vector< unsigned int > &idx, const std::string &name)
static Shader * getShader(const std::string &name)
static void loadPrimitives()
static Mesh * getMesh(const std::string &name)
static Shader * loadShader(const std::string &vShaderPath, const std::string &fShaderPath, const std::string &name)
static std::string getShaderName(const Shader *shader)
static Mesh * loadMeshFromOBJ(const std::string &path, const std::string &name)
Definition Shader.h:6
Vertex data for a single vertex in a mesh.
Definition Mesh.h:13
glm::vec3 pos
Position in local/model space.
Definition Mesh.h:14