akwk/zadanie-2_new/main.cpp

229 lines
6.7 KiB
C++
Raw Normal View History

2024-06-06 23:28:15 +02:00
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <cmath>
#include <vector>
#include <iostream>
2024-06-09 23:18:46 +02:00
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "shader.h"
2024-06-09 23:54:35 +02:00
#include <cstdlib>
const float g = 9.81f;
const float airResistance = 0.1f;
2024-06-06 23:28:15 +02:00
const int windowWidth = 1200;
const int windowHeight = 800;
2024-06-09 23:54:35 +02:00
float startTime;
const float delay = 2.0f; // 2-sekundowe opóźnienie
2024-06-06 23:28:15 +02:00
struct Ball {
float x, y, z;
float vx, vy, vz;
float r, g, b;
};
2024-06-09 23:54:35 +02:00
std::vector<Ball> balls(10); // Wektor przechowujący 10 kul
2024-06-09 23:18:46 +02:00
GLuint shaderProgram;
GLuint VAO, VBO;
2024-06-06 23:28:15 +02:00
void initializeBalls() {
2024-06-09 23:54:35 +02:00
srand(static_cast<unsigned>(time(0))); // Inicjalizujemy generator liczb losowych
2024-06-06 23:28:15 +02:00
for (int i = 0; i < 10; ++i) {
2024-06-09 23:54:35 +02:00
float angle = 15.0f + static_cast<float>(rand() % 60); // Losowy kąt między 15 a 75 stopni
float speed = 5.0f + static_cast<float>(rand() % 20); // Losowa prędkość między 5 a 25
balls[i] = {
2024-06-06 23:28:15 +02:00
.x = 0.0f,
2024-06-09 23:54:35 +02:00
.y = 2.0f * i, // Ustawienie kul na tej samej wysokości początkowej
2024-06-06 23:28:15 +02:00
.z = 0.0f,
.vx = static_cast<float>(speed * cos(angle * M_PI / 180.0f)),
.vy = static_cast<float>(speed * sin(angle * M_PI / 180.0f)),
.vz = 0.0f,
.r = static_cast<float>(rand()) / RAND_MAX,
.g = static_cast<float>(rand()) / RAND_MAX,
.b = static_cast<float>(rand()) / RAND_MAX
};
}
2024-06-09 23:54:35 +02:00
startTime = glfwGetTime(); // Ustawienie początkowego czasu symulacji
2024-06-06 23:28:15 +02:00
}
2024-06-09 23:54:35 +02:00
2024-06-09 23:31:10 +02:00
void compileShaders(){
2024-06-09 23:18:46 +02:00
Shader shader("circle_vs.glsl", "circle_fs.glsl");
shaderProgram = shader.programID();
}
2024-06-06 23:28:15 +02:00
// Funkcja do integracji Rungego-Kutty
void rungeKuttaStep(Ball &ball, float dt) {
2024-06-09 23:54:35 +02:00
float k1vx = -airResistance * ball.vx;
float k1vy = -g - airResistance * ball.vy;
float k2vx = -airResistance * (ball.vx + 0.5f * dt * k1vx);
float k2vy = -g - airResistance * (ball.vy + 0.5f * dt * k1vy);
float k3vx = -airResistance * (ball.vx + 0.5f * dt * k2vx);
float k3vy = -g - airResistance * (ball.vy + 0.5f * dt * k2vy);
float k4vx = -airResistance * (ball.vx + dt * k3vx);
float k4vy = -g - airResistance * (ball.vy + dt * k3vy);
2024-06-06 23:28:15 +02:00
ball.vx += (dt / 6.0f) * (k1vx + 2.0f * k2vx + 2.0f * k3vx + k4vx);
ball.vy += (dt / 6.0f) * (k1vy + 2.0f * k2vy + 2.0f * k3vy + k4vy);
ball.x += ball.vx * dt;
ball.y += ball.vy * dt;
}
2024-06-09 23:18:46 +02:00
void setupSphereBuffers() {
float radius = 0.5f;
int slices = 20;
int stacks = 20;
std::vector<float> vertices;
2024-06-06 23:28:15 +02:00
for (int i = 0; i <= stacks; ++i) {
float V = i / (float) stacks;
float phi = V * M_PI;
for (int j = 0; j <= slices; ++j) {
float U = j / (float) slices;
float theta = U * (M_PI * 2);
float x = cosf(theta) * sinf(phi);
float y = cosf(phi);
float z = sinf(theta) * sinf(phi);
2024-06-09 23:18:46 +02:00
vertices.push_back(x * radius);
vertices.push_back(y * radius);
vertices.push_back(z * radius);
}
}
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW);
2024-06-09 23:31:10 +02:00
2024-06-09 23:18:46 +02:00
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void drawSphere() {
glBindVertexArray(VAO);
2024-06-09 23:31:10 +02:00
glDrawArrays(GL_TRIANGLE_STRIP, 0, (20 + 1) * (20 + 1));
2024-06-09 23:18:46 +02:00
glBindVertexArray(0);
2024-06-06 23:28:15 +02:00
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2024-06-09 23:18:46 +02:00
glUseProgram(shaderProgram);
2024-06-09 23:54:35 +02:00
// Ustawienie widoku kamery
2024-06-09 23:31:10 +02:00
glm::mat4 view = glm::lookAt(glm::vec3(0, 20, 50), glm::vec3(0, 10, 0), glm::vec3(0, 1, 0));
2024-06-09 23:18:46 +02:00
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)windowWidth / (float)windowHeight, 0.1f, 100.0f);
2024-06-09 23:54:35 +02:00
// Renderowanie każdej z 10 kul
for (int i = 0; i < 10; ++i) {
Ball &ball = balls[i]; // Uzyskanie dostępu do danej kuli
2024-06-09 23:18:46 +02:00
glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(ball.x, ball.y, ball.z));
2024-06-09 23:31:10 +02:00
2024-06-09 23:54:35 +02:00
// Ustawienie macierzy modelu, widoku i projekcji w shaderze
2024-06-09 23:31:10 +02:00
GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
GLint viewLoc = glGetUniformLocation(shaderProgram, "view");
GLint projLoc = glGetUniformLocation(shaderProgram, "projection");
2024-06-09 23:18:46 +02:00
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
2024-06-09 23:31:10 +02:00
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
2024-06-09 23:18:46 +02:00
2024-06-09 23:54:35 +02:00
// Ustawienie koloru kuli w shaderze
2024-06-09 23:31:10 +02:00
GLint colorLoc = glGetUniformLocation(shaderProgram, "color");
2024-06-09 23:18:46 +02:00
glUniform3f(colorLoc, ball.r, ball.g, ball.b);
2024-06-09 23:54:35 +02:00
drawSphere(); // Rysowanie kuli
2024-06-06 23:28:15 +02:00
}
2024-06-09 23:54:35 +02:00
glfwSwapBuffers(glfwGetCurrentContext()); // Przełączanie buforów
2024-06-06 23:28:15 +02:00
}
2024-06-09 23:54:35 +02:00
2024-06-06 23:28:15 +02:00
void update() {
2024-06-09 23:54:35 +02:00
float currentTime = glfwGetTime();
2024-06-06 23:28:15 +02:00
float dt = 0.01f;
2024-06-09 23:54:35 +02:00
if (currentTime - startTime >= delay) {
for (auto &ball : balls) {
rungeKuttaStep(ball, dt);
}
2024-06-06 23:28:15 +02:00
}
}
void setupOpenGL() {
2024-06-09 23:18:46 +02:00
compileShaders();
setupSphereBuffers();
2024-06-06 23:28:15 +02:00
glEnable(GL_DEPTH_TEST);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
}
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (action == GLFW_PRESS) {
switch (key) {
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
}
}
}
int main() {
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
return -1;
}
2024-06-09 23:18:46 +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-06 23:28:15 +02:00
GLFWwindow* window = glfwCreateWindow(windowWidth, windowHeight, "Animacja 10 kul - Rzut ukośny", nullptr, nullptr);
if (!window) {
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, keyCallback); // Rejestracja callbacku klawiatury
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
initializeBalls();
setupOpenGL();
while (!glfwWindowShouldClose(window)) {
display();
update();
glfwPollEvents();
}
2024-06-09 23:18:46 +02:00
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
2024-06-06 23:28:15 +02:00
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}