Line to Spline with CatmullRom interpolation

This commit is contained in:
EIntemporel
2022-12-08 23:55:14 +01:00
parent 5e95b7e92f
commit ec1f946270
2 changed files with 94 additions and 4 deletions

View File

@@ -503,15 +503,32 @@ void Square::setup_buffers()
_buffers_are_setup = true;
}*/
void Line::initSpline()
{
draw(glm::mat4x4{},
std::vector<glm::vec3>{ {}, {} },
glm::vec4{},
false);
}
void Line::draw(glm::mat4x4 const& mvp
, std::vector<glm::vec3> const points
, glm::vec4 const& color
, bool spline
)
{
if (points.size() < 2)
return;
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<glm::vec3> const points)
{
const float tension = 0.5f;
std::vector<glm::vec3> tempPoints;
tempPoints.push_back(points[0]);
for (auto const& p : points)
tempPoints.push_back(p);
tempPoints.push_back(points[points.size() - 1]);
std::vector<glm::vec3> vertices;
std::vector<std::uint16_t> 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<glm::vec3> vertices, std::vector<std::uint16_t> indices)
{
_indice_count = (int)indices.size();
_program.reset(new OpenGL::program(
{
@@ -544,8 +628,8 @@ void Square::setup_buffers()
}
));
gl.bufferData<GL_ARRAY_BUFFER, glm::vec3> (_vertices_vbo, vertices, GL_STATIC_DRAW);
gl.bufferData<GL_ELEMENT_ARRAY_BUFFER, std::uint16_t> (_indices_vbo, indices, GL_STATIC_DRAW);
gl.bufferData<GL_ARRAY_BUFFER, glm::vec3>(_vertices_vbo, vertices, GL_STATIC_DRAW);
gl.bufferData<GL_ELEMENT_ARRAY_BUFFER, std::uint16_t>(_indices_vbo, indices, GL_STATIC_DRAW);
OpenGL::Scoped::index_buffer_manual_binder indices_binder(_indices_vbo);
OpenGL::Scoped::use_program shader(*_program.get());

View File

@@ -157,14 +157,20 @@ namespace Noggit::Rendering::Primitives
class Line
{
public:
void draw(glm::mat4x4 const& mvp, std::vector<glm::vec3> const points, glm::vec4 const& color);
void initSpline();
void draw(glm::mat4x4 const& mvp, std::vector<glm::vec3> const points, glm::vec4 const& color, bool spline);
void unload();
private:
bool _buffers_are_setup = false;
void setup_buffers(std::vector<glm::vec3> const points);
void setup_buffers_interpolated(std::vector<glm::vec3> 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<glm::vec3> vertices, std::vector<std::uint16_t> indices);
OpenGL::Scoped::deferred_upload_vertex_arrays<1> _vao;
OpenGL::Scoped::deferred_upload_buffers<2> _buffers;
GLuint const& _vertices_vbo = _buffers[0];