commit 0528cfb93e932e8ceda1ac13aea4ffc37af3c977 Author: Quinta <0pietroquintavalle0@gmail.com> Date: Fri Jul 12 03:22:10 2024 +0200 Gave up on that fucking bug for today 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