-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimulator.cpp
More file actions
237 lines (189 loc) · 8.12 KB
/
simulator.cpp
File metadata and controls
237 lines (189 loc) · 8.12 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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <GLFW/glfw3.h>
#include "engine.h"
#include "objects.h"
#include "camera.h"
#include "imgui/imgui.h"
#include "imgui/imgui_impl_glfw.h"
#include "imgui/imgui_impl_opengl3.h"
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#define WIN_WIDTH 1080
#define WIN_HEIGHT 720
#define WIN_TITLE "3D Engine"
void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) {
Camera* cameraInstance = static_cast<Camera*>(glfwGetWindowUserPointer(window));
if (!cameraInstance) return;
cameraInstance->changefov(yoffset);
}
void mouse_callback(GLFWwindow *window, double xpos, double ypos) {
Camera* cameraInstance = static_cast<Camera*>(glfwGetWindowUserPointer(window));
if (!cameraInstance) return;
if (cameraInstance->firstMouse) {
cameraInstance->lastX = xpos;
cameraInstance->lastY = ypos;
cameraInstance->firstMouse = false;
}
// get the change in (x,y)
float xOffset = xpos - cameraInstance->lastX;
float yOffset = cameraInstance->lastY - ypos; // y is inverse
cameraInstance->lastX = xpos;
cameraInstance->lastY = ypos;
if (glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) {
cameraInstance->rotateCamera(xOffset * cameraInstance->sensitivity, yOffset * cameraInstance->sensitivity);
}
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
int main() {
// Initialize GLFW
if (!glfwInit()) return -1;
GLFWwindow* window = glfwCreateWindow(WIN_WIDTH, WIN_HEIGHT, WIN_TITLE, NULL, NULL);
if (!window) return -1;
glfwMakeContextCurrent(window);
glEnable(GL_DEPTH_TEST); // Enable depth testing
// Create Camera (Positioned initially to view the cube)
Camera camera(glm::vec3(0.0f, 0.0f, 5.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f), 60.0f, 0.1f, 100.0f, 1.5f, 0.1f);
// scrollwheel actions for fov
glfwSetWindowUserPointer(window, &camera);
glfwSetScrollCallback(window, scroll_callback);
// mouse actions for rotation
glfwSetCursorPosCallback(window, mouse_callback);
// update for when screen size changes
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// Setup IMGUI
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 130");
// Create the engine and add a rigid body (the cube)
PhysicsEngine engine;
RigidBody cubeA = {glm::vec3(-4.0f, 5.0f, -5.0f), glm::vec3(3.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f,1.0f,1.0f), ShapeType::Cuboid, glm::vec3(1.0f, 0.0f, 0.0f), 1.0f};
cubeA.angularVelocity = glm::vec3(2.0f, 5.0f, 1.0f);
engine.addRigidObject(cubeA);
RigidBody cubeB = {glm::vec3(4.0f, -1.0f, -5.0f), glm::vec3(-3.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f,1.0f,1.0f), ShapeType::Cuboid, glm::vec3(0.0f, 0.0f, 1.0f), 1.0f};
engine.addRigidObject(cubeB);
RigidBody floor = {glm::vec3(0.0f, -2.0f, -5.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(20.0f,1.0f,10.0f), ShapeType::Cuboid, glm::vec3(0.3f, 0.3f, 0.3f), 0.0f};
engine.addRigidObject(floor);
// Hide and lock cursor
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// The timing rates of the function
float prevTime = glfwGetTime();
float deltaTime = 0.0f;
// Pause state
bool isPaused = false;
bool pauseKeyPressed = false;
// Summoning state
bool isSummoning = false;
bool tabKeyPressed = false;
RigidBody previewObject = {
glm::vec3(0.0f, 5.0f, -5.0f), glm::vec3(0.0f), glm::vec3(0.0f),
glm::vec3(1.0f), ShapeType::Cuboid, glm::vec3(0.0f, 1.0f, 0.0f), 1.0f
};
// Main update loop
while (!glfwWindowShouldClose(window)) {
//update objects
double currTime = glfwGetTime();
deltaTime = currTime - prevTime;
prevTime = currTime;
// New IMGUI frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
if (glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_PRESS) {
if (!pauseKeyPressed) {
isPaused = !isPaused;
pauseKeyPressed = true;
}
} else {
pauseKeyPressed = false;
}
// Toggle summoning
if (glfwGetKey(window, GLFW_KEY_TAB) == GLFW_PRESS) {
if (!tabKeyPressed) {
isSummoning = !isSummoning;
tabKeyPressed = true;
if (isSummoning) glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
else {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
camera.firstMouse = true;
}
}
} else {
tabKeyPressed = false;
}
// Draw the UI
if (isSummoning) {
ImGui::Begin("Summon Object", &isSummoning, ImGuiWindowFlags_AlwaysAutoResize);
ImGui::SliderFloat3("Position", glm::value_ptr(previewObject.position), -10.0f, 10.0f);
glm::vec3 eulerDegrees = glm::degrees(glm::eulerAngles(previewObject.orientation));
if (ImGui::SliderFloat3("Orientation", glm::value_ptr(eulerDegrees), -180.0f, 180.0f)) {
previewObject.orientation = glm::quat(glm::radians(eulerDegrees));
}
ImGui::SliderFloat3("Scale", glm::value_ptr(previewObject.scale), 0.1f, 5.0f);
ImGui::Separator();
ImGui::SliderFloat3("Linear Velocity", glm::value_ptr(previewObject.velocity), -5.0f, 5.0f);
ImGui::SliderFloat3("Angular Velocity", glm::value_ptr(previewObject.angularVelocity), -5.0f, 5.0f);
ImGui::Separator();
ImGui::ColorEdit3("Colour", glm::value_ptr(previewObject.colour));
ImGui::SliderFloat("Mass", &previewObject.mass, 0.0f, 50.0f);
if (ImGui::Button("Summon Into World!", ImVec2(-1.0f, 40.0f))) {
engine.addRigidObject(previewObject);
isSummoning = false;
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
camera.firstMouse = true;
}
ImGui::End();
}
if (!isPaused) {
engine.update(deltaTime);
}
// Handle camera movement
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
camera.moveForward(deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
camera.moveBackward(deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
camera.moveLeft(deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
camera.moveRight(deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) {
camera.moveUp(deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) {
camera.moveDown(deltaTime);
}
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS && !io.WantCaptureMouse) {
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
camera.firstMouse = true;
}
// Render the scene (objects will stay still, only the camera moves)
int width, height;
glfwGetFramebufferSize(window, &width, &height);
engine.render(camera, width, height, isPaused, isSummoning, &previewObject);
// Render IMGUI
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
// Swap buffers and poll events
glfwSwapBuffers(window);
glfwPollEvents();
}
// Cleanup
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwTerminate();
return 0;
}