akwk/zadanie-1/main.cpp

188 lines
4.3 KiB
C++
Raw Normal View History

2024-05-03 00:12:36 +02:00
#include <GL/glew.h>
#include <GLFW/glfw3.h>
2024-06-09 22:33:24 +02:00
#include <cmath>
#include <iostream>
#include <vector>
2024-06-09 22:56:47 +02:00
#include "shader.h"
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
// Konstante
const float g = 9.81f; // przyspieszenie ziemskie
2024-06-09 22:56:47 +02:00
const float r = 0.6f; // długość nici
2024-06-09 22:33:24 +02:00
const float dt = 0.01f; // krok czasowy
// Zmienne globalne
float theta = 0.5f; // początkowy kąt
float omega = 0.0f; // początkowa prędkość kątowa
2024-05-03 00:12:36 +02:00
2024-06-09 22:56:47 +02:00
GLuint VBO, VAO, EBO, shaderProgram;
void compileShaders(){
Shader shader("pendulum_vs.glsl", "pendulum_fs.glsl");
shaderProgram = shader.programID();
}
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
void initOpenGL()
{
2024-06-09 22:56:47 +02:00
compileShaders();
2024-06-09 22:33:24 +02:00
// Setup Vertex Array Object and Vertex Buffer Object
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
glBindVertexArray(VAO);
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4, nullptr, GL_DYNAMIC_DRAW);
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
// Pozycja
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
2024-05-03 00:12:36 +02:00
}
2024-06-14 00:49:10 +02:00
float f(float theta){
return -(g / r) * sin(theta);
}
2024-06-09 22:33:24 +02:00
// Metoda Eulera
void updateEuler()
{
2024-06-14 00:49:10 +02:00
float alpha = f(theta); // przyspieszenie kątowe
2024-06-09 22:33:24 +02:00
omega += alpha * dt; // aktualizacja prędkości kątowej
theta += omega * dt; // aktualizacja kąta
2024-05-03 00:12:36 +02:00
}
2024-06-09 22:33:24 +02:00
// Metoda Verleta
void updateVerlet()
{
static float prev_theta = theta;
2024-06-14 00:49:10 +02:00
float alpha = f(theta); // przyspieszenie kątowe
2024-06-09 22:33:24 +02:00
float new_theta = 2 * theta - prev_theta + alpha * dt * dt; // aktualizacja kąta
prev_theta = theta;
theta = new_theta;
}
// Metoda Rungego-Kutty rzędu 4
void updateRungeKutta()
{
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
float k1_theta = omega;
2024-06-14 00:49:10 +02:00
float k1_omega = f(theta);
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
float k2_theta = omega + 0.5f * dt * k1_omega;
2024-06-14 00:49:10 +02:00
float k2_omega = f(theta + 0.5f * dt * k1_theta);
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
float k3_theta = omega + 0.5f * dt * k2_omega;
2024-06-14 00:49:10 +02:00
float k3_omega = f(theta + 0.5f * dt * k2_theta);
2024-06-09 22:33:24 +02:00
float k4_theta = omega + dt * k3_omega;
2024-06-14 00:49:10 +02:00
float k4_omega = f(theta + dt * k3_theta);
2024-06-09 22:33:24 +02:00
theta += (dt / 6.0f) * (k1_theta + 2.0f * k2_theta + 2.0f * k3_theta + k4_theta);
omega += (dt / 6.0f) * (k1_omega + 2.0f * k2_omega + 2.0f * k3_omega + k4_omega);
2024-05-03 00:12:36 +02:00
}
2024-06-09 22:33:24 +02:00
void drawPendulum()
{
float x = r * sin(theta);
float y = -r * cos(theta);
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
float vertices[] = {
0.0f, 0.0f, // Punkt zaczepienia
x, y // Punkt masy
};
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
glBindBuffer(GL_ARRAY_BUFFER, 0);
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
glClear(GL_COLOR_BUFFER_BIT);
2024-06-09 22:56:47 +02:00
glUseProgram(shaderProgram);
2024-06-09 22:33:24 +02:00
glBindVertexArray(VAO);
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
glDrawArrays(GL_LINES, 0, 2);
glDrawArrays(GL_POINTS, 1, 1);
glBindVertexArray(0);
2024-05-03 00:12:36 +02:00
}
int main()
{
2024-06-09 22:33:24 +02:00
if (!glfwInit())
2024-05-03 00:12:36 +02:00
{
2024-06-09 22:33:24 +02:00
std::cerr << "Nie można zainicjalizować GLFW" << std::endl;
2024-05-03 00:12:36 +02:00
return -1;
}
2024-06-09 22:56:47 +02:00
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
2024-06-09 22:33:24 +02:00
GLFWwindow* window = glfwCreateWindow(800, 600, "Wahadło Matematyczne", NULL, NULL);
if (!window)
{
std::cerr << "Nie można utworzyć okna GLFW" << std::endl;
2024-05-03 00:12:36 +02:00
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
2024-06-09 22:33:24 +02:00
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cerr << "Nie można zainicjalizować GLEW" << std::endl;
2024-05-03 00:12:36 +02:00
return -1;
}
2024-06-09 22:33:24 +02:00
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2, 2, -2, 2, -1, 1);
glMatrixMode(GL_MODELVIEW);
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
glPointSize(10.0f);
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
initOpenGL();
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
int method = 1; // Domyślnie metoda Eulera
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
std::cout << "Wybierz metodę: (1) Euler, (2) Verlet, (3) Runge-Kutta: ";
std::cin >> method;
2024-05-03 00:12:36 +02:00
2024-06-09 22:33:24 +02:00
while (!glfwWindowShouldClose(window))
{
switch (method)
{
case 1:
updateEuler();
break;
case 2:
updateVerlet();
break;
case 3:
updateRungeKutta();
break;
default:
updateEuler();
break;
}
drawPendulum();
2024-05-03 00:12:36 +02:00
glfwSwapBuffers(window);
glfwPollEvents();
}
2024-06-09 22:33:24 +02:00
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwDestroyWindow(window);
2024-05-03 00:12:36 +02:00
glfwTerminate();
return 0;
}