diff --git a/resources/resources.qrc b/resources/resources.qrc
index a5456949..1e53b8d4 100644
--- a/resources/resources.qrc
+++ b/resources/resources.qrc
@@ -54,5 +54,7 @@
../src/noggit/rendering/glsl/sphere_frag.glsl
../src/noggit/rendering/glsl/square_vert.glsl
../src/noggit/rendering/glsl/square_frag.glsl
+ ../src/noggit/rendering/glsl/cylinder_vert.glsl
+ ../src/noggit/rendering/glsl/cylinder_frag.glsl
diff --git a/src/noggit/rendering/Primitives.cpp b/src/noggit/rendering/Primitives.cpp
index c08f84d0..5d882bc8 100755
--- a/src/noggit/rendering/Primitives.cpp
+++ b/src/noggit/rendering/Primitives.cpp
@@ -7,10 +7,13 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
+#include
using namespace Noggit::Rendering::Primitives;
@@ -198,15 +201,12 @@ void WireBox::setup_buffers()
}
- void Sphere::draw(glm::mat4x4 const& mvp
- , glm::vec3 const& pos
- , glm::vec4 const& color
- , float radius
- )
+ void Sphere::draw(glm::mat4x4 const& mvp, glm::vec3 const& pos, glm::vec4 const& color
+ , float radius, int longitude, int latitude, float alpha, bool wireframe, bool drawBoth)
{
if (!_buffers_are_setup)
{
- setup_buffers();
+ setup_buffers(longitude, latitude);
}
OpenGL::Scoped::use_program sphere_shader {*_program.get()};
@@ -214,18 +214,38 @@ void WireBox::setup_buffers()
sphere_shader.uniform("model_view_projection", mvp);
sphere_shader.uniform("origin", glm::vec3(pos.x,pos.y,pos.z));
sphere_shader.uniform("radius", radius);
- sphere_shader.uniform("color", color);
+ sphere_shader.uniform("color", glm::vec4(color.r, color.g, color.b, alpha));
OpenGL::Scoped::vao_binder const _(_vao[0]);
- gl.drawElements(GL_TRIANGLES, _indices_vbo, _indice_count, GL_UNSIGNED_SHORT, nullptr);
+ if (drawBoth)
+ {
+ gl.drawElements(GL_TRIANGLES, _indices_vbo, _indice_count, GL_UNSIGNED_SHORT, nullptr);
+ sphere_shader.uniform("color", glm::vec4(1.f, 1.f, 1.f, 1.f));
+ gl.drawElements(GL_LINE_STRIP, _indices_vbo, _indice_count, GL_UNSIGNED_SHORT, nullptr);
+ return;
+ }
+
+ if (!wireframe)
+ {
+ gl.drawElements(GL_TRIANGLES, _indices_vbo, _indice_count, GL_UNSIGNED_SHORT, nullptr);
+ }
+ else
+ {
+ gl.drawElements(GL_LINE_STRIP, _indices_vbo, _indice_count, GL_UNSIGNED_SHORT, nullptr);
+ }
}
-void Sphere::setup_buffers()
+void Sphere::setup_buffers(int longitude, int latitude)
{
_vao.upload();
_buffers.upload();
+ const int na = longitude;
+ const int nb = latitude;
+ const int na3 = na * 3;
+ const int nn = nb * na3;
+
std::vector vertices;
std::vector indices;
@@ -235,37 +255,47 @@ void Sphere::setup_buffers()
, OpenGL::shader::src_from_qrc("sphere_fs")
}}));
+ float x, y, z, a, b, da, db, r = 3.5f;
+ int ia, ib, ix, iy;
+ da = glm::two_pi() / float(na);
+ db = glm::pi() / float(nb - 1);
- int segment = 27;
-
- // add overlapping vertices at the end for an easier vertices generations
- for (int rotation_step = 0; rotation_step <= segment; ++rotation_step)
+ for (ix = 0, b = -glm::half_pi(), ib = 0; ib < nb; ib++, b += db)
{
- math::degrees rotation(360.f*rotation_step / static_cast(segment));
- auto rotationQuat = glm::angleAxis(rotation._, glm::vec3(0, 0, 1));
- for (int i = 0; i < segment; ++i)
- {
- float x = glm::cos(math::radians(math::degrees(i * 360 / segment))._);
- float z = glm::sin(math::radians(math::degrees(i * 360 / segment))._);
-
- glm::vec4 v(x, 0.f, z,0.0f);
-
- vertices.emplace_back(glm::toMat4(rotationQuat) * v);
-
- if (rotation_step < segment)
+ for (a = 0.f, ia = 0; ia < na; ia++, a += da, ix += 3)
{
- indices.emplace_back(i + rotation_step*segment);
- indices.emplace_back(((i + 1) % segment) + rotation_step * segment);
- indices.emplace_back(i + (rotation_step+1) * segment);
+ x = cos(b) * cos(a);
+ z = cos(b) * sin(a);
+ y = sin(b);
- indices.emplace_back(i + (rotation_step+1) * segment);
- indices.emplace_back(((i + 1) % segment) + rotation_step * segment);
- indices.emplace_back(((i + 1) % segment) + (rotation_step+1) * segment);
+ vertices.emplace_back(x, y, z);
}
- }
}
- _indice_count = indices.size();
+ for (ix = 0, iy = 0, ib = 1; ib < nb; ib++)
+ {
+ for (ia = 1; ia < na; ia++, iy++)
+ {
+ indices.push_back(iy); ix++;
+ indices.push_back(iy + 1); ix++;
+ indices.push_back(iy + na); ix++;
+
+ indices.push_back(iy + na); ix++;
+ indices.push_back(iy + 1); ix++;
+ indices.push_back(iy + na + 1); ix++;
+ }
+
+ indices.push_back(iy); ix++;
+ indices.push_back(iy + 1 - na); ix++;
+ indices.push_back(iy + na); ix++;
+
+ indices.push_back(iy + na); ix++;
+ indices.push_back(iy - na + 1); ix++;
+ indices.push_back(iy + 1); ix++;
+ iy++;
+ }
+
+ _indice_count = (int)indices.size();
gl.bufferData
(_vertices_vbo, vertices, GL_STATIC_DRAW);
@@ -298,7 +328,6 @@ void Sphere::setup_buffers()
_buffers_are_setup = false;
}
-
void Square::draw(glm::mat4x4 const& mvp
, glm::vec3 const& pos
, float radius
@@ -379,3 +408,97 @@ void Square::setup_buffers()
}
+ void Cylinder::draw(glm::mat4x4 const& mvp, glm::vec3 const& pos, const glm::vec4 color, float radius, int precision, World* world, int height)
+ {
+ if (!_buffers_are_setup)
+ {
+ setup_buffers(precision, world, height);
+ }
+
+ OpenGL::Scoped::use_program cylinder_shader {*_program.get()};
+
+ cylinder_shader.uniform("model_view_projection", mvp);
+ cylinder_shader.uniform("origin", glm::vec3(pos.x,pos.y,pos.z));
+ cylinder_shader.uniform("radius", radius);
+ cylinder_shader.uniform("color", color);
+ cylinder_shader.uniform("height", height);
+
+ OpenGL::Scoped::vao_binder const _(_vao[0]);
+
+ gl.drawElements(GL_TRIANGLES, _indices_vbo, _indice_count, GL_UNSIGNED_SHORT, nullptr);
+ }
+
+ void Cylinder::unload()
+ {
+ _vao.unload();
+ _buffers.unload();
+ _program.reset();
+
+ _buffers_are_setup = false;
+ }
+
+ void Cylinder::setup_buffers(int precision, World* world, int height)
+ {
+ if (height <= 10.f)
+ height = 10.f;
+
+ _vao.upload();
+ _buffers.upload();
+
+ std::vector vertices;
+ std::vector indices;
+
+ _program.reset(new OpenGL::program({
+ { GL_VERTEX_SHADER, OpenGL::shader::src_from_qrc("cylinder_vs")},
+ { GL_FRAGMENT_SHADER, OpenGL::shader::src_from_qrc("cylinder_fs")}
+ }));
+
+ int num = (precision + 1) * 2;
+ int numi = precision * 6;
+
+ vertices.resize(num);
+ indices.resize(numi);
+
+ for (int i = 0; i <= 1; i++)
+ {
+ for (int j = 0; j <= precision; j++)
+ {
+ float y = (i == 0) ? 0.f : float(height);
+ float x = -(float)cos(j * glm::two_pi() / precision);
+ float z = (float)sin(j * glm::two_pi() / precision);
+
+ vertices[i * (precision + 1) + j] = glm::vec3(x, y, z);
+ }
+ }
+
+ for (int i = 0; i < 1; i++)
+ {
+ for (int j = 0; j < precision; j++)
+ {
+ indices[6 * (i * precision + j) + 0] = i * (precision + 1) + j;
+ indices[6 * (i * precision + j) + 1] = i * (precision + 1) + j + 1;
+ indices[6 * (i * precision + j) + 2] = (i + 1) * (precision + 1) + j;
+ indices[6 * (i * precision + j) + 3] = i * (precision + 1) + j + 1;
+ indices[6 * (i * precision + j) + 4] = (i + 1) * (precision + 1) + j + 1;
+ indices[6 * (i * precision + j) + 5] = (i + 1) * (precision + 1) + j;
+ }
+ }
+
+ _indice_count = (int)indices.size();
+
+ 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());
+
+ {
+ OpenGL::Scoped::vao_binder const _ (_vao[0]);
+ OpenGL::Scoped::buffer_binder const vertices_binder (_vertices_vbo);
+ shader.attrib("position", 3, GL_FLOAT, GL_FALSE, 0, 0);
+ indices_binder.bind();
+ }
+
+ _buffers_are_setup = true;
+ }
\ No newline at end of file
diff --git a/src/noggit/rendering/Primitives.hpp b/src/noggit/rendering/Primitives.hpp
index e63ddde2..9ce9bd82 100755
--- a/src/noggit/rendering/Primitives.hpp
+++ b/src/noggit/rendering/Primitives.hpp
@@ -16,6 +16,7 @@ namespace math
struct vector_4d;
}
+class World;
namespace Noggit::Rendering::Primitives
{
class WireBox
@@ -86,17 +87,22 @@ namespace Noggit::Rendering::Primitives
class Sphere
{
public:
- void draw(glm::mat4x4 const& mvp
- , glm::vec3 const& pos
- , glm::vec4 const& color
- , float radius
+ void draw(glm::mat4x4 const& mvp
+ , glm::vec3 const& pos
+ , glm::vec4 const& color
+ , float radius
+ , int longitude = 32
+ , int latitude = 18
+ , float alpha = 1.f
+ , bool wireframe = false
+ , bool both = false
);
void unload();
private:
bool _buffers_are_setup = false;
- void setup_buffers();
+ void setup_buffers(int longitude, int latitude);
int _indice_count = 0;
@@ -130,4 +136,22 @@ namespace Noggit::Rendering::Primitives
std::unique_ptr _program;
};
+ class Cylinder
+ {
+ public:
+ void draw(glm::mat4x4 const& mvp, glm::vec3 const& pos, const glm::vec4 color, float radius, int precision, World* world, int height = 10);
+ void unload();
+
+ private:
+ bool _buffers_are_setup = false;
+ void setup_buffers(int precision, World* world, int height);
+ int _indice_count = 0;
+
+ OpenGL::Scoped::deferred_upload_vertex_arrays<1> _vao;
+ OpenGL::Scoped::deferred_upload_buffers<2> _buffers;
+ GLuint const& _vertices_vbo = _buffers[0];
+ GLuint const& _indices_vbo = _buffers[1];
+ std::unique_ptr _program;
+ };
+
}