From 0528cfb93e932e8ceda1ac13aea4ffc37af3c977 Mon Sep 17 00:00:00 2001
From: Quinta <0pietroquintavalle0@gmail.com>
Date: Fri, 12 Jul 2024 03:22:10 +0200
Subject: [PATCH] Gave up on that fucking bug for today
---
.gitignore | 1 +
.idea/.gitignore | 8 ++
.idea/gravity.iml | 2 +
.idea/misc.xml | 7 ++
.idea/modules.xml | 8 ++
CMakeLists.txt | 37 +++++++
CelestialBody.cpp | 37 +++++++
CelestialBody.h | 28 +++++
Renderer.cpp | 215 +++++++++++++++++++++++++++++++++++++++
Renderer.h | 33 ++++++
Simulator.cpp | 54 ++++++++++
Simulator.h | 25 +++++
main.cpp | 36 +++++++
vcpkg-configuration.json | 14 +++
vcpkg.json | 10 ++
15 files changed, 515 insertions(+)
create mode 100644 .gitignore
create mode 100644 .idea/.gitignore
create mode 100644 .idea/gravity.iml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/modules.xml
create mode 100644 CMakeLists.txt
create mode 100644 CelestialBody.cpp
create mode 100644 CelestialBody.h
create mode 100644 Renderer.cpp
create mode 100644 Renderer.h
create mode 100644 Simulator.cpp
create mode 100644 Simulator.h
create mode 100644 main.cpp
create mode 100644 vcpkg-configuration.json
create mode 100644 vcpkg.json
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ff9047e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/cmake-build-debug/
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/gravity.iml b/.idea/gravity.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/gravity.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..0b76fe5
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..6ef4ed2
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..486a02a
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,37 @@
+cmake_minimum_required(VERSION 3.28)
+project(gravity)
+
+set(CMAKE_CXX_STANDARD 17)
+
+# Find packages
+find_package(OpenGL REQUIRED)
+find_package(GLEW REQUIRED)
+find_package(glfw3 CONFIG REQUIRED)
+find_package(glm CONFIG REQUIRED)
+
+# Add executable
+add_executable(gravity
+ main.cpp
+ CelestialBody.cpp
+ Simulator.cpp
+ Renderer.cpp
+)
+
+# Include directories
+target_include_directories(gravity PRIVATE
+ ${OPENGL_INCLUDE_DIRS}
+ ${GLEW_INCLUDE_DIRS}
+)
+
+# Link libraries
+target_link_libraries(gravity PRIVATE
+ ${OPENGL_LIBRARIES}
+ GLEW::GLEW
+ glfw
+ glm::glm
+)
+
+# On some systems, you might need to explicitly link against OpenGL
+if(UNIX AND NOT APPLE)
+ target_link_libraries(gravity PRIVATE GL)
+endif()
\ No newline at end of file
diff --git a/CelestialBody.cpp b/CelestialBody.cpp
new file mode 100644
index 0000000..780bb19
--- /dev/null
+++ b/CelestialBody.cpp
@@ -0,0 +1,37 @@
+//
+// Created by 0piet on 7/12/2024.
+//
+#include "CelestialBody.h"
+#include
+#include
+
+// Helper function to convert glm::vec3 to string
+std::string vec3_to_string(const glm::vec3& v) {
+ std::stringstream ss;
+ ss << "(" << v.x << ", " << v.y << ", " << v.z << ")";
+ return ss.str();
+}
+
+CelestialBody::CelestialBody(float mass, const glm::vec3& position, const glm::vec3& velocity)
+ : mass(mass), position(position), velocity(velocity), acceleration(0.0f) {}
+
+void CelestialBody::update(float dt) {
+ if (glm::any(glm::isnan(velocity)) || glm::any(glm::isinf(velocity))) {
+ std::cout << "Warning: Invalid velocity detected: " << vec3_to_string(velocity) << std::endl;
+ velocity = glm::vec3(0.0f);
+ }
+
+ velocity += acceleration * dt;
+ position += velocity * dt;
+
+ if (glm::any(glm::isnan(position)) || glm::any(glm::isinf(position))) {
+ std::cout << "Warning: Invalid position detected: " << vec3_to_string(position) << std::endl;
+ position = glm::vec3(0.0f);
+ }
+
+ acceleration = glm::vec3(0.0f);
+}
+
+void CelestialBody::applyForce(const glm::vec3& force) {
+ acceleration += force / mass;
+}
\ No newline at end of file
diff --git a/CelestialBody.h b/CelestialBody.h
new file mode 100644
index 0000000..b81bc94
--- /dev/null
+++ b/CelestialBody.h
@@ -0,0 +1,28 @@
+//
+// Created by 0piet on 7/12/2024.
+//
+
+#ifndef GRAVITY_CELESTIALBODY_H
+#define GRAVITY_CELESTIALBODY_H
+#pragma once
+#include
+#include
+
+class CelestialBody {
+public:
+ CelestialBody(float mass, const glm::vec3& position, const glm::vec3& velocity);
+
+ void update(float dt);
+ void applyForce(const glm::vec3& force);
+
+ float getMass() const { return mass; }
+ glm::vec3 getPosition() const { return position; }
+ glm::vec3 getVelocity() const { return velocity; }
+
+private:
+ float mass;
+ glm::vec3 position;
+ glm::vec3 velocity;
+ glm::vec3 acceleration;
+};
+#endif //GRAVITY_CELESTIALBODY_H
diff --git a/Renderer.cpp b/Renderer.cpp
new file mode 100644
index 0000000..9b4a6be
--- /dev/null
+++ b/Renderer.cpp
@@ -0,0 +1,215 @@
+//
+// Created by 0piet on 7/12/2024.
+//
+#include "Renderer.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+Renderer::Renderer(int width, int height) {
+ if (!glfwInit()) {
+ throw std::runtime_error("Failed to initialize GLFW");
+ }
+
+ window = glfwCreateWindow(width, height, "3D Gravity Simulator", nullptr, nullptr);
+ if (!window) {
+ glfwTerminate();
+ throw std::runtime_error("Failed to create GLFW window");
+ }
+
+ glfwMakeContextCurrent(window);
+
+ if (glewInit() != GLEW_OK) {
+ throw std::runtime_error("Failed to initialize GLEW");
+ }
+
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_LIGHT0);
+ glEnable(GL_COLOR_MATERIAL);
+
+ createSphereMesh(1.0f, 20, 20);
+}
+
+Renderer::~Renderer() {
+ glDeleteVertexArrays(1, &sphereVAO);
+ glDeleteBuffers(1, &sphereVBO);
+ glDeleteBuffers(1, &sphereEBO);
+ glfwDestroyWindow(window);
+ glfwTerminate();
+}
+
+void Renderer::render(const Simulator& simulator) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glClearColor(0.0f, 0.0f, 0.1f, 1.0f);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(45.0, 1024.0 / 768.0, 1e8, 1e12);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ gluLookAt(3e11, 2e11, 3e11, 0, 0, 0, 0, 1, 0);
+
+ drawGrid();
+
+ const auto& bodies = simulator.getBodies();
+ for (size_t i = 0; i < bodies.size(); ++i) {
+ const auto& body = bodies[i];
+ float minSize = 2e9f;
+ float scaleFactor = std::max(std::cbrt(body.getMass()) * 1e-9f, minSize);
+
+ glm::vec3 pos = body.getPosition();
+ std::cout << "Rendering body " << i << " (";
+ switch(i) {
+ case 0: std::cout << "Sun"; break;
+ case 1: std::cout << "Mercury"; break;
+ case 2: std::cout << "Venus"; break;
+ case 3: std::cout << "Earth"; break;
+ case 4: std::cout << "Mars"; break;
+ default: std::cout << "Unknown"; break;
+ }
+ std::cout << ") at position ("
+ << pos.x << ", " << pos.y << ", " << pos.z
+ << ") with scale " << scaleFactor << std::endl;
+
+ // Set color based on body index
+ switch(i) {
+ case 0: glColor3f(1.0f, 1.0f, 0.0f); break; // Sun: Yellow
+ case 1: glColor3f(0.5f, 0.5f, 0.5f); break; // Mercury: Gray
+ case 2: glColor3f(0.9f, 0.7f, 0.4f); break; // Venus: Light Orange
+ case 3: glColor3f(0.0f, 0.5f, 1.0f); break; // Earth: Blue
+ case 4: glColor3f(1.0f, 0.0f, 0.0f); break; // Mars: Red
+ default: glColor3f(1.0f, 1.0f, 1.0f); break; // White for any additional bodies
+ }
+
+ drawSphere(body.getPosition(), scaleFactor);
+ }
+}
+
+bool Renderer::shouldClose() {
+ return glfwWindowShouldClose(window);
+}
+
+void Renderer::swapBuffers() {
+ glfwSwapBuffers(window);
+ glfwPollEvents();
+}
+
+void Renderer::drawSphere(const glm::vec3& position, float radius) {
+ glPushMatrix();
+ glTranslatef(position.x, position.y, position.z);
+ glScalef(radius, radius, radius);
+
+ glBindVertexArray(sphereVAO);
+ glDrawElements(GL_TRIANGLES, sphereIndexCount, GL_UNSIGNED_INT, 0);
+ glBindVertexArray(0);
+
+ glPopMatrix();
+}
+
+void Renderer::createSphereMesh(float radius, int sectors, int stacks) {
+ std::vector vertices;
+ std::vector indices;
+
+ float x, y, z, xy;
+ float nx, ny, nz, lengthInv = 1.0f / radius;
+ float s, t;
+
+ float sectorStep = 2 * M_PI / sectors;
+ float stackStep = M_PI / stacks;
+ float sectorAngle, stackAngle;
+
+ for (int i = 0; i <= stacks; ++i) {
+ stackAngle = M_PI / 2 - i * stackStep;
+ xy = radius * cosf(stackAngle);
+ z = radius * sinf(stackAngle);
+
+ for (int j = 0; j <= sectors; ++j) {
+ sectorAngle = j * sectorStep;
+
+ x = xy * cosf(sectorAngle);
+ y = xy * sinf(sectorAngle);
+
+ nx = x * lengthInv;
+ ny = y * lengthInv;
+ nz = z * lengthInv;
+
+ vertices.push_back(x);
+ vertices.push_back(y);
+ vertices.push_back(z);
+ }
+ }
+
+ for (int i = 0; i < stacks; ++i) {
+ int k1 = i * (sectors + 1);
+ int k2 = k1 + sectors + 1;
+
+ for (int j = 0; j < sectors; ++j, ++k1, ++k2) {
+ if (i != 0) {
+ indices.push_back(k1);
+ indices.push_back(k2);
+ indices.push_back(k1 + 1);
+ }
+
+ if (i != (stacks - 1)) {
+ indices.push_back(k1 + 1);
+ indices.push_back(k2);
+ indices.push_back(k2 + 1);
+ }
+ }
+ }
+
+ glGenVertexArrays(1, &sphereVAO);
+ glGenBuffers(1, &sphereVBO);
+ glGenBuffers(1, &sphereEBO);
+
+ glBindVertexArray(sphereVAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, sphereVBO);
+ glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sphereEBO);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
+
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
+
+ glBindVertexArray(0);
+
+ sphereVertexCount = vertices.size() / 3;
+ sphereIndexCount = indices.size();
+}
+
+void Renderer::drawDebugTriangle() {
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(-1, 1, -1, 1, -1, 1);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glBegin(GL_TRIANGLES);
+ glColor3f(1.0f, 0.0f, 0.0f);
+ glVertex3f(-0.5f, -0.5f, 0.0f);
+ glColor3f(0.0f, 1.0f, 0.0f);
+ glVertex3f(0.5f, -0.5f, 0.0f);
+ glColor3f(0.0f, 0.0f, 1.0f);
+ glVertex3f(0.0f, 0.5f, 0.0f);
+ glEnd();
+}
+
+void Renderer::drawGrid() {
+ glBegin(GL_LINES);
+ glColor3f(0.2f, 0.2f, 0.2f); // Gray color for the grid
+ for (float i = -5e11f; i <= 5e11f; i += 5e10f) {
+ glVertex3f(i, 0, -5e11f);
+ glVertex3f(i, 0, 5e11f);
+ glVertex3f(-5e11f, 0, i);
+ glVertex3f(5e11f, 0, i);
+ }
+ glEnd();
+}
\ No newline at end of file
diff --git a/Renderer.h b/Renderer.h
new file mode 100644
index 0000000..ce0e7c0
--- /dev/null
+++ b/Renderer.h
@@ -0,0 +1,33 @@
+//
+// Created by 0piet on 7/12/2024.
+//
+
+#ifndef GRAVITY_RENDERER_H
+#define GRAVITY_RENDERER_H
+#pragma once
+#include
+#include
+#include
+#include "Simulator.h"
+
+class Renderer {
+public:
+ Renderer(int width, int height);
+ ~Renderer();
+
+ void render(const Simulator& simulator);
+ bool shouldClose();
+ void swapBuffers();
+
+private:
+ GLFWwindow* window;
+ void drawSphere(const glm::vec3& position, float radius);
+ void createSphereMesh(float radius, int sectors, int stacks);
+ void drawDebugTriangle(); // Add this line
+
+ GLuint sphereVAO, sphereVBO, sphereEBO;
+ int sphereVertexCount, sphereIndexCount;
+
+ void drawGrid();
+};
+#endif //GRAVITY_RENDERER_H
diff --git a/Simulator.cpp b/Simulator.cpp
new file mode 100644
index 0000000..85aa34d
--- /dev/null
+++ b/Simulator.cpp
@@ -0,0 +1,54 @@
+//
+// Created by 0piet on 7/12/2024.
+//
+#include "Simulator.h"
+#include
+#include
+
+Simulator::Simulator() {}
+
+void Simulator::addBody(const CelestialBody& body) {
+ bodies.push_back(body);
+}
+
+void Simulator::update(float dt) {
+ // Calculate and apply gravitational forces
+ for (size_t i = 0; i < bodies.size(); ++i) {
+ glm::vec3 totalForce(0.0f);
+ for (size_t j = 0; j < bodies.size(); ++j) {
+ if (i != j) {
+ glm::vec3 force = calculateGravitationalForce(bodies[i], bodies[j]);
+ totalForce += force;
+ }
+ }
+ bodies[i].applyForce(totalForce);
+ }
+
+ // Update positions and velocities
+ for (auto& body : bodies) {
+ body.update(dt);
+ }
+}
+
+glm::vec3 Simulator::calculateGravitationalForce(const CelestialBody& body1, const CelestialBody& body2) {
+ glm::vec3 direction = body2.getPosition() - body1.getPosition();
+ float distance = glm::length(direction);
+
+ // Avoid division by zero and unrealistic forces at very small distances
+ if (distance < 1e9) {
+ std::cout << "Warning: Bodies too close, using minimum distance" << std::endl;
+ distance = 1e9;
+ }
+
+ // Use the actual G value
+ const float G = 6.67430e-11f;
+ float forceMagnitude = G * (body1.getMass() * body2.getMass()) / (distance * distance);
+
+ if (std::isnan(forceMagnitude) || std::isinf(forceMagnitude)) {
+ std::cout << "Warning: Invalid force magnitude calculated. Distance: " << distance
+ << ", Masses: " << body1.getMass() << ", " << body2.getMass() << std::endl;
+ return glm::vec3(0.0f);
+ }
+
+ return glm::normalize(direction) * forceMagnitude;
+}
\ No newline at end of file
diff --git a/Simulator.h b/Simulator.h
new file mode 100644
index 0000000..af9c830
--- /dev/null
+++ b/Simulator.h
@@ -0,0 +1,25 @@
+//
+// Created by 0piet on 7/12/2024.
+//
+
+#ifndef GRAVITY_SIMULATOR_H
+#define GRAVITY_SIMULATOR_H
+#pragma once
+#include
+#include "CelestialBody.h"
+
+class Simulator {
+public:
+ Simulator();
+
+ void addBody(const CelestialBody& body);
+ void update(float dt);
+ const std::vector& getBodies() const { return bodies; }
+
+private:
+ std::vector bodies;
+ const float G = 6.67430e-11f; // Gravitational constant
+
+ glm::vec3 calculateGravitationalForce(const CelestialBody& body1, const CelestialBody& body2);
+};
+#endif //GRAVITY_SIMULATOR_H
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..68d54eb
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,36 @@
+#include "Simulator.h"
+#include "Renderer.h"
+#include
+#include
+
+int main() {
+ Simulator simulator;
+ Renderer renderer(1024, 768); // Increased window size for better visibility
+
+ // Sun
+ simulator.addBody(CelestialBody(1.989e30f, glm::vec3(0, 0, 0), glm::vec3(0, 0, 0)));
+
+// Mercury
+ simulator.addBody(CelestialBody(3.285e23f, glm::vec3(57.9e9f, 0, 0), glm::vec3(0, 47.36e3f, 0)));
+
+// Venus
+ simulator.addBody(CelestialBody(4.867e24f, glm::vec3(108.2e9f, 0, 0), glm::vec3(0, 35.02e3f, 0)));
+
+// Earth
+ simulator.addBody(CelestialBody(5.972e24f, glm::vec3(149.6e9f, 0, 0), glm::vec3(0, 29.78e3f, 0)));
+
+// Mars
+ simulator.addBody(CelestialBody(6.39e23f, glm::vec3(227.9e9f, 0, 0), glm::vec3(0, 24.07e3f, 0)));
+
+ const float dt = 3600.0f; // Time step of 1 hour
+
+ while (!renderer.shouldClose()) {
+ simulator.update(dt);
+ renderer.render(simulator);
+ renderer.swapBuffers();
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(16)); // Aim for roughly 60 FPS
+ }
+
+ return 0;
+}
\ No newline at end of file
diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json
new file mode 100644
index 0000000..2599769
--- /dev/null
+++ b/vcpkg-configuration.json
@@ -0,0 +1,14 @@
+{
+ "default-registry": {
+ "kind": "git",
+ "baseline": "3f530d4827b064f5894e94a8946473d40999826e",
+ "repository": "https://github.com/microsoft/vcpkg"
+ },
+ "registries": [
+ {
+ "kind": "artifact",
+ "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
+ "name": "microsoft"
+ }
+ ]
+}
diff --git a/vcpkg.json b/vcpkg.json
new file mode 100644
index 0000000..d165fcb
--- /dev/null
+++ b/vcpkg.json
@@ -0,0 +1,10 @@
+{
+ "dependencies": [
+ "freeglut",
+ "glew",
+ "glm",
+ "vcpkg-cmake",
+ "opengl",
+ "glfw3"
+ ]
+}
\ No newline at end of file