#ifndef _H_LINE_H #define _H_LINE_H #include #include #include #include #include class Line { private: unsigned VAO, VBO; glm::vec4 color; public: Line(glm::vec3 start, glm::vec3 end) { float vertices[] = { start.x, start.y, start.z, end.x, end.y, end.z }; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_DYNAMIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); color = glm::vec4(1.0f, 0.0f, 0.0f, 1.0f); } void updateVertices(const glm::vec3& origin, const glm::vec3& target) { float vertices[] = { origin.x, origin.y, origin.z, target.x, target.y, target.z }; glBindBuffer(GL_ARRAY_BUFFER, VBO); float* ptr = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); if (ptr) { for (int i = 0; i < sizeof(vertices) / sizeof(vertices[0]); i++) { ptr[i] = vertices[i]; } glUnmapBuffer(GL_ARRAY_BUFFER); } glBindBuffer(GL_ARRAY_BUFFER, 0); } void setColor(glm::vec4 color) { this->color = color; } const glm::vec4& getColor() const { return color; } void draw() { glBindVertexArray(VAO); glLineWidth(10.0f); glDrawArrays(GL_LINES, 0, 2); glBindVertexArray(0); } ~Line() { glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); } }; class LineDrawer { public: static LineDrawer& getInstance() { static LineDrawer instance; return instance; } LineDrawer(LineDrawer const&) = delete; void operator=(LineDrawer const&) = delete; void addLine(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color) { auto line = std::make_shared(start, end); line->setColor(color); lines.push_back(line); } void draw(const glm::mat4& mvp) { glUseProgram(programID); for (auto& line : lines) { glUniform4fv(glGetUniformLocation(programID, "Color"), 1, glm::value_ptr(line->getColor())); glUniformMatrix4fv(glGetUniformLocation(programID, "mvp"), 1, GL_FALSE, glm::value_ptr(mvp)); line->draw(); } lines.clear(); } ~LineDrawer() { glDeleteProgram(programID); } private: unsigned programID; LineDrawer() { const char* vertexShader = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "uniform mat4 mvp;\n" "void main()\n" "{\n" "gl_Position = mvp * vec4(aPos, 1.0);\n" "}\0"; const char* fragmentShader = "#version 330 core\n" "out vec4 FragColor;\n" "uniform vec4 Color;\n" "void main()\n" "{\n" "FragColor = Color;\n" "}\0"; unsigned vertexID, fragmentID; vertexID = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexID, 1, &vertexShader, NULL); glCompileShader(vertexID); fragmentID = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentID, 1, &fragmentShader, NULL); glCompileShader(fragmentID); programID = glCreateProgram(); glAttachShader(programID, vertexID); glAttachShader(programID, fragmentID); glLinkProgram(programID); glDeleteShader(vertexID); glDeleteShader(fragmentID); } std::vector> lines; }; #endif