NEW: upgrade GLModel and so on
Jira: STUDIO-6166 most of code from PrusaSlicer thanks for PrusaSlicer and enricoturri1966 commit f8ce187262df8ef588f649c414a095c971f36e67 Author: enricoturri1966 <enricoturri@seznam.cz> Date: Wed Mar 9 11:51:02 2022 +0100 Tech ENABLE_LEGACY_OPENGL_REMOVAL - Refactoring of GLModel to automatically detect the data type to use into the index buffer in dependence of vertices count Change-Id: I8b05c5c01c1d06cc24d1981479f44c016a46b2dd
This commit is contained in:
parent
626e2a9f79
commit
98faf48787
|
@ -16,6 +16,424 @@
|
|||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
void GLModel::Geometry::add_vertex(const Vec2f &position)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P2);
|
||||
vertices.emplace_back(position.x());
|
||||
vertices.emplace_back(position.y());
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_vertex(const Vec2f &position, const Vec2f &tex_coord)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P2T2);
|
||||
vertices.emplace_back(position.x());
|
||||
vertices.emplace_back(position.y());
|
||||
vertices.emplace_back(tex_coord.x());
|
||||
vertices.emplace_back(tex_coord.y());
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_vertex(const Vec3f &position)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P3);
|
||||
vertices.emplace_back(position.x());
|
||||
vertices.emplace_back(position.y());
|
||||
vertices.emplace_back(position.z());
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_vertex(const Vec3f &position, const Vec2f &tex_coord)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P3T2);
|
||||
vertices.emplace_back(position.x());
|
||||
vertices.emplace_back(position.y());
|
||||
vertices.emplace_back(position.z());
|
||||
vertices.emplace_back(tex_coord.x());
|
||||
vertices.emplace_back(tex_coord.y());
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_vertex(const Vec3f &position, const Vec3f &normal)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P3N3);
|
||||
vertices.emplace_back(position.x());
|
||||
vertices.emplace_back(position.y());
|
||||
vertices.emplace_back(position.z());
|
||||
vertices.emplace_back(normal.x());
|
||||
vertices.emplace_back(normal.y());
|
||||
vertices.emplace_back(normal.z());
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_vertex(const Vec3f &position, const Vec3f &normal, const Vec2f &tex_coord)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P3N3T2);
|
||||
vertices.emplace_back(position.x());
|
||||
vertices.emplace_back(position.y());
|
||||
vertices.emplace_back(position.z());
|
||||
vertices.emplace_back(normal.x());
|
||||
vertices.emplace_back(normal.y());
|
||||
vertices.emplace_back(normal.z());
|
||||
vertices.emplace_back(tex_coord.x());
|
||||
vertices.emplace_back(tex_coord.y());
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_vertex(const Vec4f &position)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P4);
|
||||
vertices.emplace_back(position.x());
|
||||
vertices.emplace_back(position.y());
|
||||
vertices.emplace_back(position.z());
|
||||
vertices.emplace_back(position.w());
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_index(unsigned int id) { indices.emplace_back(id); }
|
||||
|
||||
void GLModel::Geometry::add_line(unsigned int id1, unsigned int id2)
|
||||
{
|
||||
indices.emplace_back(id1);
|
||||
indices.emplace_back(id2);
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_triangle(unsigned int id1, unsigned int id2, unsigned int id3)
|
||||
{
|
||||
indices.emplace_back(id1);
|
||||
indices.emplace_back(id2);
|
||||
indices.emplace_back(id3);
|
||||
}
|
||||
|
||||
Vec2f GLModel::Geometry::extract_position_2(size_t id) const
|
||||
{
|
||||
const size_t p_stride = position_stride_floats(format);
|
||||
if (p_stride != 2) {
|
||||
assert(false);
|
||||
return {FLT_MAX, FLT_MAX};
|
||||
}
|
||||
|
||||
if (vertices_count() <= id) {
|
||||
assert(false);
|
||||
return {FLT_MAX, FLT_MAX};
|
||||
}
|
||||
|
||||
const float *start = &vertices[id * vertex_stride_floats(format) + position_offset_floats(format)];
|
||||
return {*(start + 0), *(start + 1)};
|
||||
}
|
||||
|
||||
Vec3f GLModel::Geometry::extract_position_3(size_t id) const
|
||||
{
|
||||
const size_t p_stride = position_stride_floats(format);
|
||||
if (p_stride != 3) {
|
||||
assert(false);
|
||||
return {FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
}
|
||||
|
||||
if (vertices_count() <= id) {
|
||||
assert(false);
|
||||
return {FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
}
|
||||
|
||||
const float *start = &vertices[id * vertex_stride_floats(format) + position_offset_floats(format)];
|
||||
return {*(start + 0), *(start + 1), *(start + 2)};
|
||||
}
|
||||
|
||||
Vec3f GLModel::Geometry::extract_normal_3(size_t id) const
|
||||
{
|
||||
const size_t n_stride = normal_stride_floats(format);
|
||||
if (n_stride != 3) {
|
||||
assert(false);
|
||||
return {FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
}
|
||||
|
||||
if (vertices_count() <= id) {
|
||||
assert(false);
|
||||
return {FLT_MAX, FLT_MAX, FLT_MAX};
|
||||
}
|
||||
|
||||
const float *start = &vertices[id * vertex_stride_floats(format) + normal_offset_floats(format)];
|
||||
return {*(start + 0), *(start + 1), *(start + 2)};
|
||||
}
|
||||
|
||||
Vec2f GLModel::Geometry::extract_tex_coord_2(size_t id) const
|
||||
{
|
||||
const size_t t_stride = tex_coord_stride_floats(format);
|
||||
if (t_stride != 2) {
|
||||
assert(false);
|
||||
return {FLT_MAX, FLT_MAX};
|
||||
}
|
||||
|
||||
if (vertices_count() <= id) {
|
||||
assert(false);
|
||||
return {FLT_MAX, FLT_MAX};
|
||||
}
|
||||
|
||||
const float *start = &vertices[id * vertex_stride_floats(format) + tex_coord_offset_floats(format)];
|
||||
return {*(start + 0), *(start + 1)};
|
||||
}
|
||||
|
||||
void GLModel::Geometry::set_vertex(size_t id, const Vec3f &position, const Vec3f &normal)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P3N3);
|
||||
assert(id < vertices_count());
|
||||
if (id < vertices_count()) {
|
||||
float *start = &vertices[id * vertex_stride_floats(format)];
|
||||
*(start + 0) = position.x();
|
||||
*(start + 1) = position.y();
|
||||
*(start + 2) = position.z();
|
||||
*(start + 3) = normal.x();
|
||||
*(start + 4) = normal.y();
|
||||
*(start + 5) = normal.z();
|
||||
}
|
||||
}
|
||||
|
||||
void GLModel::Geometry::set_index(size_t id, unsigned int index)
|
||||
{
|
||||
assert(id < indices_count());
|
||||
if (id < indices_count()) indices[id] = index;
|
||||
}
|
||||
|
||||
unsigned int GLModel::Geometry::extract_index(size_t id) const
|
||||
{
|
||||
if (indices_count() <= id) {
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return indices[id];
|
||||
}
|
||||
|
||||
void GLModel::Geometry::remove_vertex(size_t id)
|
||||
{
|
||||
assert(id < vertices_count());
|
||||
if (id < vertices_count()) {
|
||||
const size_t stride = vertex_stride_floats(format);
|
||||
std::vector<float>::const_iterator it = vertices.begin() + id * stride;
|
||||
vertices.erase(it, it + stride);
|
||||
}
|
||||
}
|
||||
|
||||
indexed_triangle_set GLModel::Geometry::get_as_indexed_triangle_set() const
|
||||
{
|
||||
indexed_triangle_set its;
|
||||
its.vertices.reserve(vertices_count());
|
||||
for (size_t i = 0; i < vertices_count(); ++i) { its.vertices.emplace_back(extract_position_3(i)); }
|
||||
its.indices.reserve(indices_count() / 3);
|
||||
for (size_t i = 0; i < indices_count() / 3; ++i) {
|
||||
const size_t tri_id = i * 3;
|
||||
its.indices.emplace_back(extract_index(tri_id), extract_index(tri_id + 1), extract_index(tri_id + 2));
|
||||
}
|
||||
return its;
|
||||
}
|
||||
|
||||
size_t GLModel::Geometry::vertex_stride_floats(const Format &format)
|
||||
{
|
||||
switch (format.vertex_layout) {
|
||||
case EVertexLayout::P2: {
|
||||
return 2;
|
||||
}
|
||||
case EVertexLayout::P2T2: {
|
||||
return 4;
|
||||
}
|
||||
case EVertexLayout::P3: {
|
||||
return 3;
|
||||
}
|
||||
case EVertexLayout::P3T2: {
|
||||
return 5;
|
||||
}
|
||||
case EVertexLayout::P3N3: {
|
||||
return 6;
|
||||
}
|
||||
case EVertexLayout::P3N3T2: {
|
||||
return 8;
|
||||
}
|
||||
case EVertexLayout::P4: {
|
||||
return 4;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
size_t GLModel::Geometry::position_stride_floats(const Format &format)
|
||||
{
|
||||
switch (format.vertex_layout) {
|
||||
case EVertexLayout::P2:
|
||||
case EVertexLayout::P2T2: {
|
||||
return 2;
|
||||
}
|
||||
case EVertexLayout::P3:
|
||||
case EVertexLayout::P3T2:
|
||||
case EVertexLayout::P3N3:
|
||||
case EVertexLayout::P3N3T2: {
|
||||
return 3;
|
||||
}
|
||||
case EVertexLayout::P4: {
|
||||
return 4;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
size_t GLModel::Geometry::position_offset_floats(const Format &format)
|
||||
{
|
||||
switch (format.vertex_layout) {
|
||||
case EVertexLayout::P2:
|
||||
case EVertexLayout::P2T2:
|
||||
case EVertexLayout::P3:
|
||||
case EVertexLayout::P3T2:
|
||||
case EVertexLayout::P3N3:
|
||||
case EVertexLayout::P3N3T2:
|
||||
case EVertexLayout::P4: {
|
||||
return 0;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
size_t GLModel::Geometry::normal_stride_floats(const Format &format)
|
||||
{
|
||||
switch (format.vertex_layout) {
|
||||
case EVertexLayout::P3N3:
|
||||
case EVertexLayout::P3N3T2: {
|
||||
return 3;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
size_t GLModel::Geometry::normal_offset_floats(const Format &format)
|
||||
{
|
||||
switch (format.vertex_layout) {
|
||||
case EVertexLayout::P3N3:
|
||||
case EVertexLayout::P3N3T2: {
|
||||
return 3;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
size_t GLModel::Geometry::tex_coord_stride_floats(const Format &format)
|
||||
{
|
||||
switch (format.vertex_layout) {
|
||||
case EVertexLayout::P2T2:
|
||||
case EVertexLayout::P3T2:
|
||||
case EVertexLayout::P3N3T2: {
|
||||
return 2;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
size_t GLModel::Geometry::tex_coord_offset_floats(const Format &format)
|
||||
{
|
||||
switch (format.vertex_layout) {
|
||||
case EVertexLayout::P2T2: {
|
||||
return 2;
|
||||
}
|
||||
case EVertexLayout::P3T2: {
|
||||
return 3;
|
||||
}
|
||||
case EVertexLayout::P3N3T2: {
|
||||
return 6;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
size_t GLModel::Geometry::index_stride_bytes(const Geometry &data)
|
||||
{
|
||||
switch (data.index_type) {
|
||||
case EIndexType::UINT: {
|
||||
return sizeof(unsigned int);
|
||||
}
|
||||
case EIndexType::USHORT: {
|
||||
return sizeof(unsigned short);
|
||||
}
|
||||
case EIndexType::UBYTE: {
|
||||
return sizeof(unsigned char);
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool GLModel::Geometry::has_position(const Format &format)
|
||||
{
|
||||
switch (format.vertex_layout) {
|
||||
case EVertexLayout::P2:
|
||||
case EVertexLayout::P2T2:
|
||||
case EVertexLayout::P3:
|
||||
case EVertexLayout::P3T2:
|
||||
case EVertexLayout::P3N3:
|
||||
case EVertexLayout::P3N3T2:
|
||||
case EVertexLayout::P4: {
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool GLModel::Geometry::has_normal(const Format &format)
|
||||
{
|
||||
switch (format.vertex_layout) {
|
||||
case EVertexLayout::P2:
|
||||
case EVertexLayout::P2T2:
|
||||
case EVertexLayout::P3:
|
||||
case EVertexLayout::P3T2:
|
||||
case EVertexLayout::P4: {
|
||||
return false;
|
||||
}
|
||||
case EVertexLayout::P3N3:
|
||||
case EVertexLayout::P3N3T2: {
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool GLModel::Geometry::has_tex_coord(const Format &format)
|
||||
{
|
||||
switch (format.vertex_layout) {
|
||||
case EVertexLayout::P2T2:
|
||||
case EVertexLayout::P3T2:
|
||||
case EVertexLayout::P3N3T2: {
|
||||
return true;
|
||||
}
|
||||
case EVertexLayout::P2:
|
||||
case EVertexLayout::P3:
|
||||
case EVertexLayout::P3N3:
|
||||
case EVertexLayout::P4: {
|
||||
return false;
|
||||
}
|
||||
default: {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
size_t GLModel::InitializationData::vertices_count() const
|
||||
{
|
||||
|
@ -35,6 +453,46 @@ size_t GLModel::InitializationData::indices_count() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
GLModel::~GLModel()
|
||||
{
|
||||
reset();
|
||||
if (mesh) { delete mesh; }
|
||||
}
|
||||
|
||||
void GLModel::init_from(Geometry &&data, bool generate_mesh)
|
||||
{
|
||||
if (is_initialized()) {
|
||||
// call reset() if you want to reuse this model
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.vertices.empty() || data.indices.empty()) {
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
m_render_data.clear();
|
||||
m_render_data.push_back(RenderData());
|
||||
m_render_data.back().indices_count = data.indices.size();
|
||||
m_render_data.back().type = data.format.type;
|
||||
m_render_data.back().color = data.color.get_data();
|
||||
if (generate_mesh) {
|
||||
if (!mesh) { mesh = new TriangleMesh(); }
|
||||
mesh->its = std::move(data.get_as_indexed_triangle_set());
|
||||
}
|
||||
m_render_data.back().geometry = std::move(data);
|
||||
// update bounding box
|
||||
for (size_t i = 0; i < data.vertices_count(); ++i) {
|
||||
const size_t position_stride = Geometry::position_stride_floats(data.format);
|
||||
if (position_stride == 3)
|
||||
m_bounding_box.merge(m_render_data.back().geometry.extract_position_3(i).cast<double>());
|
||||
else if (position_stride == 2) {
|
||||
const Vec2f position = m_render_data.back().geometry.extract_position_2(i);
|
||||
m_bounding_box.merge(Vec3f(position.x(), position.y(), 0.0f).cast<double>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLModel::init_from(const InitializationData& data)
|
||||
{
|
||||
if (!m_render_data.empty()) // call reset() if you want to reuse this model
|
||||
|
@ -193,8 +651,17 @@ void GLModel::render() const
|
|||
GLShaderProgram* shader = wxGetApp().get_current_shader();
|
||||
|
||||
for (const RenderData& data : m_render_data) {
|
||||
if (data.vbo_id == 0 || data.ibo_id == 0)
|
||||
continue;
|
||||
// sends data to gpu if not done yet
|
||||
if (data.vbo_id == 0 || data.ibo_id == 0) {
|
||||
auto origin_data = const_cast<RenderData *>(&data);
|
||||
if (data.geometry.vertices_count() > 0 && data.geometry.indices_count() > 0
|
||||
&& !send_to_gpu(*origin_data, data.geometry.vertices, data.geometry.indices))
|
||||
continue;
|
||||
}
|
||||
bool has_normal = true;
|
||||
if (data.geometry.vertices_count() > 0) {
|
||||
has_normal = Geometry::has_normal(data.geometry.format);
|
||||
}
|
||||
|
||||
GLenum mode;
|
||||
switch (data.type)
|
||||
|
@ -207,11 +674,16 @@ void GLModel::render() const
|
|||
}
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id));
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)0));
|
||||
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
|
||||
if (has_normal) {
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void *) 0));
|
||||
glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), (const void *) (3 * sizeof(float))));
|
||||
|
||||
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
|
||||
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||
glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
|
||||
} else {
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), (const void *) 0));
|
||||
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||
}
|
||||
|
||||
if (shader != nullptr)
|
||||
shader->set_uniform("uniform_color", data.color);
|
||||
|
@ -306,10 +778,17 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
|
|||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
}
|
||||
|
||||
void GLModel::send_to_gpu(RenderData& data, const std::vector<float>& vertices, const std::vector<unsigned int>& indices)
|
||||
bool GLModel::send_to_gpu(RenderData& data, const std::vector<float>& vertices, const std::vector<unsigned int>& indices) const
|
||||
{
|
||||
assert(data.vbo_id == 0);
|
||||
assert(data.ibo_id == 0);
|
||||
if (data.vbo_id > 0 || data.ibo_id > 0) {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (vertices.empty() || indices.empty()) {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// vertex data -> send to gpu
|
||||
glsafe(::glGenBuffers(1, &data.vbo_id));
|
||||
|
@ -322,6 +801,7 @@ void GLModel::send_to_gpu(RenderData& data, const std::vector<float>& vertices,
|
|||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ibo_id));
|
||||
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
return true;
|
||||
}
|
||||
|
||||
GLModel::InitializationData stilized_arrow(int resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
|
||||
|
@ -744,5 +1224,181 @@ GLModel::InitializationData diamond(int resolution)
|
|||
return data;
|
||||
}
|
||||
|
||||
GLModel::Geometry smooth_sphere(unsigned int resolution, float radius)
|
||||
{
|
||||
resolution = std::max<unsigned int>(4, resolution);
|
||||
|
||||
const unsigned int sectorCount = resolution;
|
||||
const unsigned int stackCount = resolution;
|
||||
|
||||
const float sectorStep = float(2.0 * M_PI / sectorCount);
|
||||
const float stackStep = float(M_PI / stackCount);
|
||||
|
||||
GLModel::Geometry data;
|
||||
data.format = {GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3};
|
||||
data.reserve_vertices((stackCount - 1) * sectorCount + 2);
|
||||
data.reserve_indices((2 * (stackCount - 1) * sectorCount) * 3);
|
||||
|
||||
// vertices
|
||||
for (unsigned int i = 0; i <= stackCount; ++i) {
|
||||
// from pi/2 to -pi/2
|
||||
const double stackAngle = 0.5 * M_PI - stackStep * i;
|
||||
const double xy = double(radius) * ::cos(stackAngle);
|
||||
const double z = double(radius) * ::sin(stackAngle);
|
||||
if (i == 0 || i == stackCount) {
|
||||
const Vec3f v(float(xy), 0.0f, float(z));
|
||||
data.add_vertex(v, (Vec3f) v.normalized());
|
||||
} else {
|
||||
for (unsigned int j = 0; j < sectorCount; ++j) {
|
||||
// from 0 to 2pi
|
||||
const double sectorAngle = sectorStep * j;
|
||||
const Vec3f v(float(xy * std::cos(sectorAngle)), float(xy * std::sin(sectorAngle)), float(z));
|
||||
data.add_vertex(v, (Vec3f) v.normalized());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// triangles
|
||||
for (unsigned int i = 0; i < stackCount; ++i) {
|
||||
// Beginning of current stack.
|
||||
unsigned int k1 = (i == 0) ? 0 : (1 + (i - 1) * sectorCount);
|
||||
const unsigned int k1_first = k1;
|
||||
// Beginning of next stack.
|
||||
unsigned int k2 = (i == 0) ? 1 : (k1 + sectorCount);
|
||||
const unsigned int k2_first = k2;
|
||||
for (unsigned int j = 0; j < sectorCount; ++j) {
|
||||
// 2 triangles per sector excluding first and last stacks
|
||||
unsigned int k1_next = k1;
|
||||
unsigned int k2_next = k2;
|
||||
if (i != 0) {
|
||||
k1_next = (j + 1 == sectorCount) ? k1_first : (k1 + 1);
|
||||
data.add_triangle(k1, k2, k1_next);
|
||||
}
|
||||
if (i + 1 != stackCount) {
|
||||
k2_next = (j + 1 == sectorCount) ? k2_first : (k2 + 1);
|
||||
data.add_triangle(k1_next, k2, k2_next);
|
||||
}
|
||||
k1 = k1_next;
|
||||
k2 = k2_next;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
GLModel::Geometry smooth_cylinder(unsigned int resolution, float radius, float height)
|
||||
{
|
||||
resolution = std::max<unsigned int>(4, resolution);
|
||||
|
||||
const unsigned int sectorCount = resolution;
|
||||
const float sectorStep = 2.0f * float(M_PI) / float(sectorCount);
|
||||
|
||||
GLModel::Geometry data;
|
||||
data.format = {GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3};
|
||||
data.reserve_vertices(sectorCount * 4 + 2);
|
||||
data.reserve_indices(sectorCount * 4 * 3);
|
||||
|
||||
auto generate_vertices_on_circle = [sectorCount, sectorStep](float radius) {
|
||||
std::vector<Vec3f> ret;
|
||||
ret.reserve(sectorCount);
|
||||
for (unsigned int i = 0; i < sectorCount; ++i) {
|
||||
// from 0 to 2pi
|
||||
const float sectorAngle = sectorStep * i;
|
||||
ret.emplace_back(radius * std::cos(sectorAngle), radius * std::sin(sectorAngle), 0.0f);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
const std::vector<Vec3f> base_vertices = generate_vertices_on_circle(radius);
|
||||
const Vec3f h = height * Vec3f::UnitZ();
|
||||
|
||||
// stem vertices
|
||||
for (unsigned int i = 0; i < sectorCount; ++i) {
|
||||
const Vec3f &v = base_vertices[i];
|
||||
const Vec3f n = v.normalized();
|
||||
data.add_vertex(v, n);
|
||||
data.add_vertex(v + h, n);
|
||||
}
|
||||
|
||||
// stem triangles
|
||||
for (unsigned int i = 0; i < sectorCount; ++i) {
|
||||
unsigned int v1 = i * 2;
|
||||
unsigned int v2 = (i < sectorCount - 1) ? v1 + 2 : 0;
|
||||
unsigned int v3 = v2 + 1;
|
||||
unsigned int v4 = v1 + 1;
|
||||
data.add_triangle(v1, v2, v3);
|
||||
data.add_triangle(v1, v3, v4);
|
||||
}
|
||||
|
||||
// bottom cap vertices
|
||||
Vec3f cap_center = Vec3f::Zero();
|
||||
unsigned int cap_center_id = data.vertices_count();
|
||||
Vec3f normal = -Vec3f::UnitZ();
|
||||
|
||||
data.add_vertex(cap_center, normal);
|
||||
for (unsigned int i = 0; i < sectorCount; ++i) { data.add_vertex(base_vertices[i], normal); }
|
||||
|
||||
// bottom cap triangles
|
||||
for (unsigned int i = 0; i < sectorCount; ++i) { data.add_triangle(cap_center_id, (i < sectorCount - 1) ? cap_center_id + i + 2 : cap_center_id + 1, cap_center_id + i + 1); }
|
||||
|
||||
// top cap vertices
|
||||
cap_center += h;
|
||||
cap_center_id = data.vertices_count();
|
||||
normal = -normal;
|
||||
|
||||
data.add_vertex(cap_center, normal);
|
||||
for (unsigned int i = 0; i < sectorCount; ++i) { data.add_vertex(base_vertices[i] + h, normal); }
|
||||
|
||||
// top cap triangles
|
||||
for (unsigned int i = 0; i < sectorCount; ++i) { data.add_triangle(cap_center_id, cap_center_id + i + 1, (i < sectorCount - 1) ? cap_center_id + i + 2 : cap_center_id + 1); }
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
GLModel::Geometry smooth_torus(unsigned int primary_resolution, unsigned int secondary_resolution, float radius, float thickness)
|
||||
{
|
||||
const unsigned int torus_sector_count = std::max<unsigned int>(4, primary_resolution);
|
||||
const float torus_sector_step = 2.0f * float(M_PI) / float(torus_sector_count);
|
||||
const unsigned int section_sector_count = std::max<unsigned int>(4, secondary_resolution);
|
||||
const float section_sector_step = 2.0f * float(M_PI) / float(section_sector_count);
|
||||
|
||||
GLModel::Geometry data;
|
||||
data.format = {GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3};
|
||||
data.reserve_vertices(torus_sector_count * section_sector_count);
|
||||
data.reserve_indices(torus_sector_count * section_sector_count * 2 * 3);
|
||||
|
||||
// vertices
|
||||
for (unsigned int i = 0; i < torus_sector_count; ++i) {
|
||||
const float section_angle = torus_sector_step * i;
|
||||
const float csa = std::cos(section_angle);
|
||||
const float ssa = std::sin(section_angle);
|
||||
const Vec3f section_center(radius * csa, radius * ssa, 0.0f);
|
||||
for (unsigned int j = 0; j < section_sector_count; ++j) {
|
||||
const float circle_angle = section_sector_step * j;
|
||||
const float thickness_xy = thickness * std::cos(circle_angle);
|
||||
const float thickness_z = thickness * std::sin(circle_angle);
|
||||
const Vec3f v(thickness_xy * csa, thickness_xy * ssa, thickness_z);
|
||||
data.add_vertex(section_center + v, (Vec3f) v.normalized());
|
||||
}
|
||||
}
|
||||
|
||||
// triangles
|
||||
for (unsigned int i = 0; i < torus_sector_count; ++i) {
|
||||
const unsigned int ii = i * section_sector_count;
|
||||
const unsigned int ii_next = ((i + 1) % torus_sector_count) * section_sector_count;
|
||||
for (unsigned int j = 0; j < section_sector_count; ++j) {
|
||||
const unsigned int j_next = (j + 1) % section_sector_count;
|
||||
const unsigned int i0 = ii + j;
|
||||
const unsigned int i1 = ii_next + j;
|
||||
const unsigned int i2 = ii_next + j_next;
|
||||
const unsigned int i3 = ii + j_next;
|
||||
data.add_triangle(i0, i1, i2);
|
||||
data.add_triangle(i0, i2, i3);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -28,13 +28,110 @@ namespace GUI {
|
|||
LineLoop
|
||||
};
|
||||
|
||||
struct Geometry
|
||||
{
|
||||
// enum class EPrimitiveType : unsigned char { Points, Triangles, TriangleStrip, TriangleFan, Lines, LineStrip, LineLoop };
|
||||
enum class EVertexLayout : unsigned char {
|
||||
P2, // position 2 floats
|
||||
P2T2, // position 2 floats + texture coords 2 floats
|
||||
P3, // position 3 floats
|
||||
P3T2, // position 3 floats + texture coords 2 floats
|
||||
P3N3, // position 3 floats + normal 3 floats
|
||||
P3N3T2, // position 3 floats + normal 3 floats + texture coords 2 floats
|
||||
P4, // position 4 floats
|
||||
};
|
||||
|
||||
enum class EIndexType : unsigned char {
|
||||
UINT, // unsigned int
|
||||
USHORT, // unsigned short
|
||||
UBYTE // unsigned byte
|
||||
};
|
||||
|
||||
struct Format
|
||||
{
|
||||
PrimitiveType type{PrimitiveType::Triangles};
|
||||
EVertexLayout vertex_layout{EVertexLayout::P3N3};
|
||||
};
|
||||
|
||||
Format format;
|
||||
std::vector<float> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
EIndexType index_type{EIndexType::UINT};
|
||||
ColorRGBA color{ColorRGBA::BLACK()};
|
||||
|
||||
void reserve_vertices(size_t vertices_count) { vertices.reserve(vertices_count * vertex_stride_floats(format)); }
|
||||
void reserve_indices(size_t indices_count) { indices.reserve(indices_count); }
|
||||
|
||||
void add_vertex(const Vec2f &position); // EVertexLayout::P2
|
||||
void add_vertex(const Vec2f &position, const Vec2f &tex_coord); // EVertexLayout::P2T2
|
||||
void add_vertex(const Vec3f &position); // EVertexLayout::P3
|
||||
void add_vertex(const Vec3f &position, const Vec2f &tex_coord); // EVertexLayout::P3T2
|
||||
void add_vertex(const Vec3f &position, const Vec3f &normal); // EVertexLayout::P3N3
|
||||
void add_vertex(const Vec3f &position, const Vec3f &normal, const Vec2f &tex_coord); // EVertexLayout::P3N3T2
|
||||
void add_vertex(const Vec4f &position); // EVertexLayout::P4
|
||||
|
||||
void set_vertex(size_t id, const Vec3f &position, const Vec3f &normal); // EVertexLayout::P3N3
|
||||
|
||||
void set_index(size_t id, unsigned int index);
|
||||
|
||||
void add_index(unsigned int id);
|
||||
void add_line(unsigned int id1, unsigned int id2);
|
||||
void add_triangle(unsigned int id1, unsigned int id2, unsigned int id3);
|
||||
|
||||
Vec2f extract_position_2(size_t id) const;
|
||||
Vec3f extract_position_3(size_t id) const;
|
||||
Vec3f extract_normal_3(size_t id) const;
|
||||
Vec2f extract_tex_coord_2(size_t id) const;
|
||||
|
||||
unsigned int extract_index(size_t id) const;
|
||||
|
||||
void remove_vertex(size_t id);
|
||||
|
||||
bool is_empty() const { return vertices_count() == 0 || indices_count() == 0; }
|
||||
|
||||
size_t vertices_count() const { return vertices.size() / vertex_stride_floats(format); }
|
||||
size_t indices_count() const { return indices.size(); }
|
||||
|
||||
size_t vertices_size_floats() const { return vertices.size(); }
|
||||
size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); }
|
||||
size_t indices_size_bytes() const { return indices.size() * index_stride_bytes(*this); }
|
||||
|
||||
indexed_triangle_set get_as_indexed_triangle_set() const;
|
||||
|
||||
static size_t vertex_stride_floats(const Format &format);
|
||||
static size_t vertex_stride_bytes(const Format &format) { return vertex_stride_floats(format) * sizeof(float); }
|
||||
|
||||
static size_t position_stride_floats(const Format &format);
|
||||
static size_t position_stride_bytes(const Format &format) { return position_stride_floats(format) * sizeof(float); }
|
||||
static size_t position_offset_floats(const Format &format);
|
||||
static size_t position_offset_bytes(const Format &format) { return position_offset_floats(format) * sizeof(float); }
|
||||
|
||||
static size_t normal_stride_floats(const Format &format);
|
||||
static size_t normal_stride_bytes(const Format &format) { return normal_stride_floats(format) * sizeof(float); }
|
||||
static size_t normal_offset_floats(const Format &format);
|
||||
static size_t normal_offset_bytes(const Format &format) { return normal_offset_floats(format) * sizeof(float); }
|
||||
|
||||
static size_t tex_coord_stride_floats(const Format &format);
|
||||
static size_t tex_coord_stride_bytes(const Format &format) { return tex_coord_stride_floats(format) * sizeof(float); }
|
||||
static size_t tex_coord_offset_floats(const Format &format);
|
||||
static size_t tex_coord_offset_bytes(const Format &format) { return tex_coord_offset_floats(format) * sizeof(float); }
|
||||
|
||||
static size_t index_stride_bytes(const Geometry &data);
|
||||
|
||||
static bool has_position(const Format &format);
|
||||
static bool has_normal(const Format &format);
|
||||
static bool has_tex_coord(const Format &format);
|
||||
};
|
||||
|
||||
struct RenderData
|
||||
{
|
||||
PrimitiveType type;
|
||||
unsigned int vbo_id{ 0 };
|
||||
unsigned int ibo_id{ 0 };
|
||||
size_t indices_count{ 0 };
|
||||
std::array<float, 4> color{ 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
Geometry geometry;
|
||||
|
||||
PrimitiveType type;
|
||||
unsigned int vbo_id{0};
|
||||
unsigned int ibo_id{0};
|
||||
size_t indices_count{0};
|
||||
std::array<float, 4> color{1.0f, 1.0f, 1.0f, 1.0f};
|
||||
};
|
||||
|
||||
struct InitializationData
|
||||
|
@ -66,8 +163,11 @@ namespace GUI {
|
|||
|
||||
public:
|
||||
GLModel() = default;
|
||||
virtual ~GLModel() { reset(); }
|
||||
virtual ~GLModel();
|
||||
|
||||
TriangleMesh *mesh{nullptr};
|
||||
|
||||
void init_from(Geometry &&data, bool generate_mesh = false);
|
||||
void init_from(const InitializationData& data);
|
||||
void init_from(const indexed_triangle_set& its, const BoundingBoxf3& bbox);
|
||||
void init_from(const indexed_triangle_set& its);
|
||||
|
@ -87,7 +187,7 @@ namespace GUI {
|
|||
const std::string& get_filename() const { return m_filename; }
|
||||
|
||||
private:
|
||||
void send_to_gpu(RenderData& data, const std::vector<float>& vertices, const std::vector<unsigned int>& indices);
|
||||
bool send_to_gpu(RenderData &data, const std::vector<float> &vertices, const std::vector<unsigned int> &indices) const;
|
||||
};
|
||||
|
||||
// create an arrow with cylindrical stem and conical tip, with the given dimensions and resolution
|
||||
|
@ -113,7 +213,19 @@ namespace GUI {
|
|||
// the diamond is contained into a box with size [1, 1, 1]
|
||||
GLModel::InitializationData diamond(int resolution);
|
||||
|
||||
} // namespace GUI
|
||||
// create a sphere with smooth normals
|
||||
// the origin of the sphere is in its center
|
||||
GLModel::Geometry smooth_sphere(unsigned int resolution, float radius);
|
||||
// create a cylinder with smooth normals
|
||||
// the axis of the cylinder is the Z axis
|
||||
// the origin of the cylinder is the center of its bottom cap face
|
||||
GLModel::Geometry smooth_cylinder(unsigned int resolution, float radius, float height);
|
||||
// create a torus with smooth normals
|
||||
// the axis of the torus is the Z axis
|
||||
// the origin of the torus is in its center
|
||||
GLModel::Geometry smooth_torus(unsigned int primary_resolution, unsigned int secondary_resolution, float radius, float thickness);
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_GLModel_hpp_
|
||||
|
|
|
@ -5983,6 +5983,12 @@ Sidebar& GUI_App::sidebar()
|
|||
return plater_->sidebar();
|
||||
}
|
||||
|
||||
GizmoObjectManipulation *GUI_App::obj_manipul()
|
||||
{
|
||||
// If this method is called before plater_ has been initialized, return nullptr (to avoid a crash)
|
||||
return (plater_ != nullptr) ? &plater_->get_view3D_canvas3D()->get_gizmos_manager().get_object_manipulation() : nullptr;
|
||||
}
|
||||
|
||||
ObjectSettings* GUI_App::obj_settings()
|
||||
{
|
||||
return sidebar().obj_settings();
|
||||
|
|
|
@ -130,6 +130,7 @@ enum CameraMenuIDs {
|
|||
|
||||
class Tab;
|
||||
class ConfigWizard;
|
||||
class GizmoObjectManipulation;
|
||||
|
||||
static wxString dots("...", wxConvUTF8);
|
||||
|
||||
|
@ -527,6 +528,7 @@ public:
|
|||
#endif /* __APPLE */
|
||||
|
||||
Sidebar& sidebar();
|
||||
GizmoObjectManipulation *obj_manipul();
|
||||
ObjectSettings* obj_settings();
|
||||
ObjectList* obj_list();
|
||||
ObjectLayers* obj_layers();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "GLGizmoRotate.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/CutUtils.hpp"
|
||||
#include "slic3r/GUI/MeshUtils.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
enum class CutConnectorType : int;
|
||||
class ModelVolume;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/GLModel.hpp"
|
||||
#include "slic3r/GUI/MeshUtils.hpp"
|
||||
|
||||
#include <cereal/archives/binary.hpp>
|
||||
|
||||
|
@ -114,6 +115,21 @@ protected:
|
|||
std::string m_icon_filename;
|
||||
unsigned int m_sprite_id;
|
||||
int m_hover_id;
|
||||
enum GripperType {
|
||||
UNDEFINE,
|
||||
POINT,
|
||||
EDGE,
|
||||
CIRCLE,
|
||||
CIRCLE_1,
|
||||
CIRCLE_2,
|
||||
PLANE,
|
||||
PLANE_1,
|
||||
PLANE_2,
|
||||
SPHERE_1,
|
||||
SPHERE_2,
|
||||
};
|
||||
std::map<GripperType, std::shared_ptr<PickRaycaster>> m_gripper_id_raycast_map;
|
||||
|
||||
bool m_dragging;
|
||||
std::array<float, 4> m_base_color;
|
||||
std::array<float, 4> m_drag_color;
|
||||
|
|
Loading…
Reference in New Issue