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:
enricoturri1966 2024-02-27 15:38:23 +08:00 committed by Lane.Wei
parent 626e2a9f79
commit 98faf48787
6 changed files with 810 additions and 18 deletions

View File

@ -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

View File

@ -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_

View File

@ -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();

View File

@ -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();

View File

@ -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;

View File

@ -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;