diff --git a/src/noggit/rendering/Primitives.cpp b/src/noggit/rendering/Primitives.cpp index 7aef3b28..cda53226 100755 --- a/src/noggit/rendering/Primitives.cpp +++ b/src/noggit/rendering/Primitives.cpp @@ -503,15 +503,32 @@ void Square::setup_buffers() _buffers_are_setup = true; }*/ + void Line::initSpline() + { + draw(glm::mat4x4{}, + std::vector{ {}, {} }, + glm::vec4{}, + false); + } + void Line::draw(glm::mat4x4 const& mvp , std::vector const points , glm::vec4 const& color + , bool spline ) { if (points.size() < 2) return; - setup_buffers(points); + if (!spline || points.size() == 2) + { + setup_buffers(points); + } + else + { + initSpline(); + setup_buffers_interpolated(points); + } OpenGL::Scoped::use_program line_shader{ *_program.get() }; @@ -536,6 +553,73 @@ void Square::setup_buffers() indices.push_back(i); } + setup_shader(vertices, indices); + } + + void Line::setup_buffers_interpolated(std::vector const points) + { + const float tension = 0.5f; + + std::vector tempPoints; + tempPoints.push_back(points[0]); + + for (auto const& p : points) + tempPoints.push_back(p); + + tempPoints.push_back(points[points.size() - 1]); + + std::vector vertices; + std::vector indices; + + for (int i = 1; i < tempPoints.size() - 2; i++) + { + auto s = tension * 2.f; + auto p0 = tempPoints[i - 1]; + auto p1 = tempPoints[i + 0]; + auto p2 = tempPoints[i + 1]; + auto p3 = tempPoints[i + 2]; + + glm::vec3 m1( + (p2.x - p0.x) / s, + (p2.y - p0.y) / s, + (p2.z - p0.z) / s + ); + + glm::vec3 m2( + (p3.x - p1.x) / s, + (p3.y - p1.y) / s, + (p3.z - p1.z) / s + ); + + vertices.push_back(interpolate(0, p1, p2, m1, m2)); + + for (float t = 0.01f; t < 1.f; t += 0.01f) + vertices.push_back(interpolate(t, p1, p2, m1, m2)); + + vertices.push_back(interpolate(1, p1, p2, m1, m2)); + } + + for (int i = 0; i < vertices.size(); ++i) + { + indices.push_back(i); + } + + setup_shader(vertices, indices); + } + + glm::vec3 Line::interpolate(float t, glm::vec3 p0, glm::vec3 p1, glm::vec3 m0, glm::vec3 m1) + { + auto c = 2 * t * t * t - 3 * t * t; + auto c0 = c + 1; + auto c1 = t * t * t - 2 * t * t + t; + auto c2 = -c; + auto c3 = t * t * t - t * t; + + return (c0 * p0 + c1 * m0 + c2 * p1 + c3 * m1); + } + + void Line::setup_shader(std::vector vertices, std::vector indices) + { _indice_count = (int)indices.size(); _program.reset(new OpenGL::program( { @@ -544,8 +628,8 @@ void Square::setup_buffers() } )); - gl.bufferData (_vertices_vbo, vertices, GL_STATIC_DRAW); - gl.bufferData (_indices_vbo, indices, GL_STATIC_DRAW); + gl.bufferData(_vertices_vbo, vertices, GL_STATIC_DRAW); + gl.bufferData(_indices_vbo, indices, GL_STATIC_DRAW); OpenGL::Scoped::index_buffer_manual_binder indices_binder(_indices_vbo); OpenGL::Scoped::use_program shader(*_program.get()); diff --git a/src/noggit/rendering/Primitives.hpp b/src/noggit/rendering/Primitives.hpp index 08825305..b9b96c2a 100755 --- a/src/noggit/rendering/Primitives.hpp +++ b/src/noggit/rendering/Primitives.hpp @@ -157,14 +157,20 @@ namespace Noggit::Rendering::Primitives class Line { public: - void draw(glm::mat4x4 const& mvp, std::vector const points, glm::vec4 const& color); + void initSpline(); + void draw(glm::mat4x4 const& mvp, std::vector const points, glm::vec4 const& color, bool spline); void unload(); private: bool _buffers_are_setup = false; void setup_buffers(std::vector const points); + + void setup_buffers_interpolated(std::vector const points); + glm::vec3 interpolate(float t, glm::vec3 p0, glm::vec3 p1, glm::vec3 m0, glm::vec3 m1); + int _indice_count = 0; + void setup_shader(std::vector vertices, std::vector indices); OpenGL::Scoped::deferred_upload_vertex_arrays<1> _vao; OpenGL::Scoped::deferred_upload_buffers<2> _buffers; GLuint const& _vertices_vbo = _buffers[0];