Случайная линия рисуется в проекте C++ opengl
Привет, я довольно новичок в C++ и OpenGL и кодировал версию C++ OpenGL 2d Raycasting Challenge с канала Coding Train YouTube(ep.145). Все это, кажется, работает хорошо, за исключением одной вещи. В проекте всякий раз, когда луч 0 ° (Луч, который указывает прямо направо) не отбрасывает себя, то есть не касается границы(стены), из ниоткуда появляется случайный луч, который продолжается до бесконечности.
Вот код, чтобы вы могли это увидеть.
main.cpp
#include "Raycasting.hpp" #include <iostream> #include <GL/glew.h> #include <GLFW/glfw3.h> #include <cmath> void framebuffer_size_callback(GLFWwindow* window, int w, int h); int width, height; std::vector<Boundary> walls; Particle particle = Particle(width, height); double mx, my; int main() { srand(time(NULL)); GLFWwindow* window; if (!glfwInit()) return 1; width = 600; height = 600; window = glfwCreateWindow(width, height, "Window", NULL, NULL); if (!window) { glfwTerminate(); return 1; } for(int i = 0; i < 5; i++){ walls.push_back(Boundary(rand()%width, rand()%width, rand()%height, rand()%height)); } glfwMakeContextCurrent(window); if(glewInit()!=GLEW_OK) std::cout<<"Error"<<std::endl; glEnable(GL_DEPTH_TEST); glMatrixMode(GL_PROJECTION); glfwGetFramebufferSize(window, &width, &height); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); Particle particle = Particle(width, height); glOrtho(0, width*(width/height), height, 0, -2, 2); while(!glfwWindowShouldClose(window)) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glClearColor(0.11, 0.14, 0.17, 1); glfwGetCursorPos(window, &mx, &my); for(Boundary &wall : walls) wall.show(); particle.update((float)mx, (float)my); particle.show(); particle.look(walls); glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); } void framebuffer_size_callback(GLFWwindow* window, int w, int h) { //float ratio = width/height; width = w; height = h; float ratio = width/height; if(width<height) ratio = height/width; else ratio = width/height; //std::cout<<"Width: "<<width<<" "<<"Height: "<<height<<std::endl; glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(width>height) glOrtho(0, width*ratio, height, 0, -2, 2); else glOrtho(0, width, height*ratio, 0, -2, 2); }
Raycasting.ГЭС
#ifndef RAYCASTING #define RAYCASTING #include <GL/glew.h> #include <GLFW/glfw3.h> #include <cmath> #include <vector> /**DRAWING FUNCTIONS, no need to check these**/ void DrawEllipse(float cx, float cy, float rx, float ry, int num_segments) { float theta = 2 * 3.1415926 / float(num_segments); float c = cosf(theta);//precalculate the sine and cosine float s = sinf(theta); float t; float x = 1;//we start at angle = 0 float y = 0; glBegin(GL_LINE_LOOP); for(int ii = 0; ii < num_segments; ii++) { //apply radius and offset glVertex2f(x * rx + cx, y * ry + cy);//output vertex //apply the rotation matrix t = x; x = c * x - s * y; y = s * t + c * y; } glEnd(); } void stroke(int value){ float v = (float)value/255; glColor3f(v,v,v); } void line(float x1, float y1, float x2, float y2){ glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x2,y2); glEnd(); } void ellipse(float x, float y, float width, float height){ DrawEllipse(x, y, width/2, height/2, 10800); } /**END OF DRAWING FUNCTIONS**/ class V2D{ public: V2D(){} V2D(float _x, float _y){ x = _x; y = _y; } V2D(long int n){ isNull = true; } bool isNull = false; float x; float y; float magnitude(){ return sqrt(x*x + y*y); } void normalize(){ float mag = magnitude(); x /= mag; y /= mag; } }; float dist(V2D start, V2D end){ return sqrt((start.x-end.x)*(start.x-end.x) + (start.y-end.y)*(start.y-end.y)); } class Boundary{ public: Boundary(float x1, float y1, float x2, float y2){ a = V2D(x1, y1); b = V2D(x2, y2); } V2D a,b; void show(){ stroke(255); line(a.x, a.y, b.x, b.y); } }; class Ray{ public: Ray(V2D _pos, float angle){ pos = _pos; dir = V2D(cos(angle), sin(angle)); } V2D pos,dir; void lookAt(float x, float y){ dir.x = x - pos.x; dir.y = y - pos.y; dir.normalize(); } void show(){ stroke(255); line(pos.x, pos.y, pos.x + dir.x * 10, pos.y + dir.y * 10); } V2D cast(Boundary wall){ const float x1 = wall.a.x; const float y1 = wall.a.y; const float x2 = wall.b.x; const float y2 = wall.b.y; const float x3 = pos.x; const float y3 = pos.y; const float x4 = pos.x + dir.x; const float y4 = pos.y + dir.y; const float den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); if(den==0){ return V2D(NULL); } const float t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / den; const float u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / den; if(t > 0 && t < 1 && u > 0){ float X = x1 + t * (x2 - x1); float Y = y1 + t * (y2 - y1); return V2D(X, Y); } else return V2D(NULL); } }; class Particle{ public: Particle(int width, int height){ pos = V2D(width/2, height/2); rays = {}; for(int i = 0; i < 360; i+=1){ rays.push_back(Ray(pos, i*M_PI/180)); } } V2D pos; std::vector<Ray> rays = {}; void update(float x, float y){ for(Ray &ray : rays){ ray.pos = V2D(x,y); } } void show(){ for(int i = 0; i <rays.size(); i++){ rays[i].show(); } } void look(std::vector<Boundary> walls){ for(int i = 0; i < rays.size(); i++){ V2D closest; float record = 100000; for(Boundary &wall : walls){ V2D pt = rays[i].cast(wall); if(!pt.isNull){ const float d = dist(rays[i].pos, pt); if(d < record){ record = d; closest = pt; } } } if(!closest.isNull){ line(rays[i].pos.x, rays[i].pos.y, closest.x, closest.y); } } } }; #endif
файл Makefile
main.o: main.cpp g++ main.cpp -lglfw -I/usr/include/libdrm -L/usr/lib64 -lGLEW -lGLU -lGL -o app
Что я уже пробовал:
Я не знаю, что конкретно делать, но любая помощь/объяснение будут полностью оценены