Tech ENABLE_GLINDEXEDVERTEXARRAY_REMOVAL - Replace GLIndexedVertexArray with GLModel: GLVolume geometry + removed class GLIndexedVertexArray from codebase

(cherry picked from commit prusa3d/PrusaSlicer@1eac357739)
This commit is contained in:
enricoturri1966 2023-10-23 17:02:29 +08:00 committed by Noisyfox
parent d85bbcba50
commit d09dc36ff1
16 changed files with 765 additions and 1130 deletions

View file

@ -8,15 +8,50 @@
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/Polygon.hpp"
#include "libslic3r/BuildVolume.hpp"
#include "libslic3r/Geometry/ConvexHull.hpp"
#include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string/predicate.hpp>
#if ENABLE_SMOOTH_NORMALS
#include <igl/per_face_normals.h>
#include <igl/per_corner_normals.h>
#include <igl/per_vertex_normals.h>
#endif // ENABLE_SMOOTH_NORMALS
#include <GL/glew.h>
namespace Slic3r {
namespace GUI {
#if ENABLE_SMOOTH_NORMALS
static void smooth_normals_corner(const TriangleMesh& mesh, std::vector<stl_normal>& normals)
{
using MapMatrixXfUnaligned = Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
using MapMatrixXiUnaligned = Eigen::Map<const Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
std::vector<Vec3f> face_normals = its_face_normals(mesh.its);
Eigen::MatrixXd vertices = MapMatrixXfUnaligned(mesh.its.vertices.front().data(),
Eigen::Index(mesh.its.vertices.size()), 3).cast<double>();
Eigen::MatrixXi indices = MapMatrixXiUnaligned(mesh.its.indices.front().data(),
Eigen::Index(mesh.its.indices.size()), 3);
Eigen::MatrixXd in_normals = MapMatrixXfUnaligned(face_normals.front().data(),
Eigen::Index(face_normals.size()), 3).cast<double>();
Eigen::MatrixXd out_normals;
igl::per_corner_normals(vertices, indices, in_normals, 1.0, out_normals);
normals = std::vector<stl_normal>(mesh.its.vertices.size());
for (size_t i = 0; i < mesh.its.indices.size(); ++i) {
for (size_t j = 0; j < 3; ++j) {
normals[mesh.its.indices[i][j]] = out_normals.row(i * 3 + j).cast<float>();
}
}
}
#endif // ENABLE_SMOOTH_NORMALS
void GLModel::Geometry::reserve_vertices(size_t vertices_count)
{
vertices.reserve(vertices_count * vertex_stride_floats(format));
@ -206,6 +241,35 @@ Vec2f GLModel::Geometry::extract_tex_coord_2(size_t id) const
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_ushort_index(size_t id, unsigned short index)
{
assert(id < indices_count());
if (id < indices_count())
::memcpy(indices.data() + id * sizeof(unsigned short), &index, sizeof(unsigned short));
}
void GLModel::Geometry::set_uint_index(size_t id, unsigned int index)
{
assert(id < indices_count());
if (id < indices_count())
::memcpy(indices.data() + id * sizeof(unsigned int), &index, sizeof(unsigned int));
}
unsigned int GLModel::Geometry::extract_uint_index(size_t id) const
{
if (format.index_type != EIndexType::UINT) {
@ -218,7 +282,7 @@ unsigned int GLModel::Geometry::extract_uint_index(size_t id) const
return -1;
}
unsigned int ret = -1;
unsigned int ret = (unsigned int)-1;
::memcpy(&ret, indices.data() + id * index_stride_bytes(format), sizeof(unsigned int));
return ret;
}
@ -235,11 +299,21 @@ unsigned short GLModel::Geometry::extract_ushort_index(size_t id) const
return -1;
}
unsigned short ret = -1;
unsigned short ret = (unsigned short)-1;
::memcpy(&ret, indices.data() + id * index_stride_bytes(format), sizeof(unsigned short));
return ret;
}
void GLModel::Geometry::remove_vertex(size_t id)
{
assert(id < vertices_count());
if (id < vertices_count()) {
size_t stride = vertex_stride_floats(format);
std::vector<float>::iterator it = vertices.begin() + id * stride;
vertices.erase(it, it + stride);
}
}
size_t GLModel::Geometry::vertex_stride_floats(const Format& format)
{
switch (format.vertex_layout)
@ -417,21 +491,24 @@ void GLModel::init_from(const indexed_triangle_set& its)
}
Geometry& data = m_render_data.geometry;
data.format = { Geometry::EPrimitiveType::Triangles, Geometry::EVertexLayout::P3N3, Geometry::EIndexType::UINT };
data.format = { Geometry::EPrimitiveType::Triangles, Geometry::EVertexLayout::P3N3, GLModel::Geometry::index_type(3 * its.indices.size()) };
data.reserve_vertices(3 * its.indices.size());
data.reserve_indices(3 * its.indices.size());
// vertices + indices
unsigned int vertices_counter = 0;
for (uint32_t i = 0; i < its.indices.size(); ++i) {
stl_triangle_vertex_indices face = its.indices[i];
stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
stl_vertex n = face_normal_normalized(vertex);
const stl_triangle_vertex_indices face = its.indices[i];
const stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
const stl_vertex n = face_normal_normalized(vertex);
for (size_t j = 0; j < 3; ++j) {
data.add_vertex(vertex[j], n);
}
vertices_counter += 3;
data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
if (data.format.index_type == GLModel::Geometry::EIndexType::USHORT)
data.add_ushort_triangle((unsigned short)vertices_counter - 3, (unsigned short)vertices_counter - 2, (unsigned short)vertices_counter - 1);
else
data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
}
// update bounding box
@ -553,6 +630,17 @@ static GLenum get_index_type(const GLModel::Geometry::Format& format)
void GLModel::render()
{
render(std::make_pair<size_t, size_t>(0, indices_count()));
}
void GLModel::render(const std::pair<size_t, size_t>& range)
{
if (m_render_disabled)
return;
if (range.second == range.first)
return;
GLShaderProgram* shader = wxGetApp().get_current_shader();
if (shader == nullptr)
@ -570,8 +658,8 @@ void GLModel::render()
const GLenum index_type = get_index_type(data.format);
const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format);
const bool position = Geometry::has_position(data.format);
const bool normal = Geometry::has_normal(data.format);
const bool position = Geometry::has_position(data.format);
const bool normal = Geometry::has_normal(data.format);
const bool tex_coord = Geometry::has_tex_coord(data.format);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id));
@ -592,7 +680,7 @@ void GLModel::render()
shader->set_uniform("uniform_color", data.color);
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id));
glsafe(::glDrawElements(mode, indices_count(), index_type, nullptr));
glsafe(::glDrawElements(mode, range.second - range.first + 1, index_type, (const void*)(range.first * Geometry::index_stride_bytes(data.format))));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
if (tex_coord)
@ -721,6 +809,61 @@ static void append_triangle(GLModel::Geometry& data, unsigned short v1, unsigned
data.add_ushort_index(v2);
data.add_ushort_index(v3);
}
template<typename Fn>
inline bool all_vertices_inside(const GLModel::Geometry& geometry, Fn fn)
{
const size_t position_stride_floats = geometry.position_stride_floats(geometry.format);
const size_t position_offset_floats = geometry.position_offset_floats(geometry.format);
assert(position_stride_floats == 3);
if (geometry.vertices.empty() || position_stride_floats != 3)
return false;
for (auto it = geometry.vertices.begin(); it != geometry.vertices.end(); ) {
it += position_offset_floats;
if (!fn({ *it, *(it + 1), *(it + 2) }))
return false;
it += (geometry.vertex_stride_floats(geometry.format) - position_offset_floats - position_stride_floats);
}
return true;
}
bool contains(const BuildVolume& volume, const GLModel& model, bool ignore_bottom)
{
static constexpr const double epsilon = BuildVolume::BedEpsilon;
switch (volume.type()) {
case BuildVolume_Type::Rectangle:
{
BoundingBox3Base<Vec3d> build_volume = volume.bounding_volume().inflated(epsilon);
if (volume.printable_height() == 0.0)
build_volume.max.z() = std::numeric_limits<double>::max();
if (ignore_bottom)
build_volume.min.z() = -std::numeric_limits<double>::max();
const BoundingBoxf3& model_box = model.get_bounding_box();
return build_volume.contains(model_box.min) && build_volume.contains(model_box.max);
}
case BuildVolume_Type::Circle:
{
const Geometry::Circled& circle = volume.circle();
const Vec2f c = unscaled<float>(circle.center);
const float r = unscaled<double>(circle.radius) + float(epsilon);
const float r2 = sqr(r);
return volume.printable_height() == 0.0 ?
all_vertices_inside(model.get_geometry(), [c, r2](const Vec3f& p) { return (to_2d(p) - c).squaredNorm() <= r2; }) :
all_vertices_inside(model.get_geometry(), [c, r2, z = volume.printable_height() + epsilon](const Vec3f& p) { return (to_2d(p) - c).squaredNorm() <= r2 && p.z() <= z; });
}
case BuildVolume_Type::Convex:
//FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently.
case BuildVolume_Type::Custom:
return volume.printable_height() == 0.0 ?
all_vertices_inside(model.get_geometry(), [&volume](const Vec3f& p) { return Geometry::inside_convex_polygon(volume.top_bottom_convex_hull_decomposition_bed(), to_2d(p).cast<double>()); }) :
all_vertices_inside(model.get_geometry(), [&volume, z = volume.printable_height() + epsilon](const Vec3f& p) { return Geometry::inside_convex_polygon(volume.top_bottom_convex_hull_decomposition_bed(), to_2d(p).cast<double>()) && p.z() <= z; });
default:
return true;
}
}
GLModel::Geometry stilized_arrow(unsigned short resolution, float tip_radius, float tip_height, float stem_radius, float stem_height)
{
resolution = std::max<unsigned short>(4, resolution);