update slic3r

This commit is contained in:
QIDI TECH
2024-11-28 15:19:12 +08:00
parent a26696f35e
commit 7eb6543991
196 changed files with 18701 additions and 3803 deletions

View File

@@ -459,6 +459,20 @@ GLModel::~GLModel()
if (mesh) { delete mesh; }
}
size_t GLModel::get_vertices_count(int i) const {
if (m_render_data.empty() || i >= m_render_data.size()) {
return 0;
}
return m_render_data[i].vertices_count > 0 ? m_render_data[i].vertices_count : m_render_data[i].geometry.vertices_count();
}
size_t GLModel::get_indices_count(int i) const {
if (m_render_data.empty() || i >= m_render_data.size()) {
return 0;
}
return m_render_data[i].indices_count > 0 ? m_render_data[i].indices_count : m_render_data[i].geometry.indices_count();
}
void GLModel::init_from(Geometry &&data, bool generate_mesh)
{
if (is_initialized()) {
@@ -474,6 +488,7 @@ void GLModel::init_from(Geometry &&data, bool generate_mesh)
m_render_data.clear();
m_render_data.push_back(RenderData());
m_render_data.back().indices_count = data.indices.size();
m_render_data.back().vertices_count = data.vertices.size();
m_render_data.back().type = data.format.type;
m_render_data.back().color = data.color.get_data();
if (generate_mesh) {
@@ -623,22 +638,121 @@ bool GLModel::init_from_file(const std::string& filename)
return true;
}
bool GLModel::init_model_from_poly(const std::vector<Vec2f> &triangles, float z, bool generate_mesh)
{
if (triangles.empty() || triangles.size() % 3 != 0)
return false;
GLModel::Geometry init_data;
init_data.format = {GLModel::PrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3T2};
init_data.reserve_vertices(triangles.size());
init_data.reserve_indices(triangles.size() / 3);
Vec2f min = triangles.front();
Vec2f max = min;
for (const Vec2f &v : triangles) {
min = min.cwiseMin(v).eval();
max = max.cwiseMax(v).eval();
}
const Vec2f size = max - min;
if (size.x() <= 0.0f || size.y() <= 0.0f)
return false;
Vec2f inv_size = size.cwiseInverse();
inv_size.y() *= -1.0f;
// vertices + indices
unsigned int vertices_counter = 0;
for (const Vec2f &v : triangles) {
const Vec3f p = {v.x(), v.y(), z};
init_data.add_vertex(p, (Vec2f) (v - min).cwiseProduct(inv_size).eval());
++vertices_counter;
if (vertices_counter % 3 == 0)
init_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
}
init_from(std::move(init_data), generate_mesh);
return true;
}
bool GLModel::init_model_from_lines(const Lines &lines, float z, bool generate_mesh)
{
GLModel::Geometry init_data;
init_data.format = {GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3};
init_data.reserve_vertices(2 * lines.size());
init_data.reserve_indices(2 * lines.size());
for (const auto &l : lines) {
init_data.add_vertex(Vec3f(unscale<float>(l.a.x()), unscale<float>(l.a.y()), z));
init_data.add_vertex(Vec3f(unscale<float>(l.b.x()), unscale<float>(l.b.y()), z));
const unsigned int vertices_counter = (unsigned int) init_data.vertices_count();
init_data.add_line(vertices_counter - 2, vertices_counter - 1);
}
init_from(std::move(init_data), generate_mesh);
return true;
}
bool GLModel::init_model_from_lines(const Lines3 &lines, bool generate_mesh)
{
GLModel::Geometry init_data;
init_data.format = {GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3};
init_data.reserve_vertices(2 * lines.size());
init_data.reserve_indices(2 * lines.size());
for (const auto &l : lines) {
init_data.add_vertex(Vec3f(unscale<float>(l.a.x()), unscale<float>(l.a.y()), unscale<float>(l.a.z())));
init_data.add_vertex(Vec3f(unscale<float>(l.b.x()), unscale<float>(l.b.y()), unscale<float>(l.b.z())));
const unsigned int vertices_counter = (unsigned int) init_data.vertices_count();
init_data.add_line(vertices_counter - 2, vertices_counter - 1);
}
init_from(std::move(init_data), generate_mesh);
return true;
}
bool GLModel::init_model_from_lines(const Line3floats &lines, bool generate_mesh)
{
GLModel::Geometry init_data;
init_data.format = {GLModel::PrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3};
init_data.reserve_vertices(2 * lines.size());
init_data.reserve_indices(2 * lines.size());
for (const auto &l : lines) {
init_data.add_vertex(l.a);
init_data.add_vertex(l.b);
const unsigned int vertices_counter = (unsigned int) init_data.vertices_count();
init_data.add_line(vertices_counter - 2, vertices_counter - 1);
}
init_from(std::move(init_data), generate_mesh);
return true;
}
void GLModel::set_color(int entity_id, const std::array<float, 4>& color)
{
for (size_t i = 0; i < m_render_data.size(); ++i) {
if (entity_id == -1 || static_cast<int>(i) == entity_id)
if (entity_id == -1 || static_cast<int>(i) == entity_id) {
m_render_data[i].color = color;
m_render_data[i].geometry.color = color;
}
}
}
void GLModel::set_color(const ColorRGBA &color) {
set_color(-1,color.get_data());
}
void GLModel::reset()
{
for (RenderData& data : m_render_data) {
// release gpu memory
if (data.ibo_id > 0)
if (data.ibo_id > 0) {
glsafe(::glDeleteBuffers(1, &data.ibo_id));
if (data.vbo_id > 0)
data.ibo_id = 0;
}
if (data.vbo_id > 0) {
glsafe(::glDeleteBuffers(1, &data.vbo_id));
data.vbo_id = 0;
}
}
m_render_data.clear();
@@ -646,6 +760,50 @@ void GLModel::reset()
m_filename = std::string();
}
static GLenum get_primitive_mode(const GLModel::Geometry::Format &format)
{
switch (format.type) {
case GLModel::PrimitiveType::Points: {
return GL_POINTS;
}
default:
case GLModel::PrimitiveType::Triangles: {
return GL_TRIANGLES;
}
case GLModel::PrimitiveType::TriangleStrip: {
return GL_TRIANGLE_STRIP;
}
case GLModel::PrimitiveType::TriangleFan: {
return GL_TRIANGLE_FAN;
}
case GLModel::PrimitiveType::Lines: {
return GL_LINES;
}
case GLModel::PrimitiveType::LineStrip: {
return GL_LINE_STRIP;
}
case GLModel::PrimitiveType::LineLoop: {
return GL_LINE_LOOP;
}
}
}
static GLenum get_index_type(const GLModel::Geometry &data)
{
switch (data.index_type) {
default:
case GLModel::Geometry::EIndexType::UINT: {
return GL_UNSIGNED_INT;
}
case GLModel::Geometry::EIndexType::USHORT: {
return GL_UNSIGNED_SHORT;
}
case GLModel::Geometry::EIndexType::UBYTE: {
return GL_UNSIGNED_BYTE;
}
}
}
void GLModel::render() const
{
GLShaderProgram* shader = wxGetApp().get_current_shader();
@@ -654,7 +812,7 @@ void GLModel::render() const
// 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
if (data.geometry.vertices_count() > 0 && data.geometry.indices_count() > 0
&& !send_to_gpu(*origin_data, data.geometry.vertices, data.geometry.indices))
continue;
}
@@ -701,6 +859,210 @@ void GLModel::render() const
}
}
void GLModel::render_geometry() {
render_geometry(0,std::make_pair<size_t, size_t>(0, get_indices_count()));
}
void GLModel::render_geometry(int i,const std::pair<size_t, size_t> &range)
{
if (range.second == range.first) return;
GLShaderProgram *shader = wxGetApp().get_current_shader();
if (shader == nullptr) return;
auto &render_data = m_render_data[i];
// sends data to gpu if not done yet
if (render_data.vbo_id == 0 || render_data.ibo_id == 0) {
if (render_data.geometry.vertices_count() > 0 && render_data.geometry.indices_count() > 0 &&
!send_to_gpu(render_data, render_data.geometry.vertices, render_data.geometry.indices))
return;
}
const Geometry &data = render_data.geometry;
const GLenum mode = get_primitive_mode(data.format);
const GLenum index_type = get_index_type(data);
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 tex_coord = Geometry::has_tex_coord(data.format);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, render_data.vbo_id));
int position_id = -1;
int normal_id = -1;
int tex_coord_id = -1;
if (position) {
position_id = shader->get_attrib_location("v_position");
if (position_id != -1) {
glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes,
(const void *) Geometry::position_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(position_id));
}
}
if (normal) {
normal_id = shader->get_attrib_location("v_normal");
if (normal_id != -1) {
glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes,
(const void *) Geometry::normal_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(normal_id));
}
}
if (tex_coord) {
tex_coord_id = shader->get_attrib_location("v_tex_coord");
if (tex_coord_id != -1) {
glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes,
(const void *) Geometry::tex_coord_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(tex_coord_id));
}
}
shader->set_uniform("uniform_color", data.color.get_data());
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, render_data.ibo_id));
glsafe(::glDrawElements(mode, range.second - range.first, index_type, (const void *) (range.first * Geometry::index_stride_bytes(data))));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
if (tex_coord_id != -1) glsafe(::glDisableVertexAttribArray(tex_coord_id));
if (normal_id != -1) glsafe(::glDisableVertexAttribArray(normal_id));
if (position_id != -1) glsafe(::glDisableVertexAttribArray(position_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
void GLModel::create_or_update_mats_vbo(unsigned int &vbo, const std::vector<Slic3r::Geometry::Transformation> &mats)
{ // first bind
if (vbo>0) {
glsafe(::glDeleteBuffers(1, &vbo));
vbo = 0;
}
std::vector<Matrix4f> out_mats;
out_mats.reserve(mats.size());
for (size_t i = 0; i < mats.size(); i++) {
out_mats.emplace_back(mats[i].get_matrix().matrix().cast<float>());
}
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
auto one_mat_all_size = sizeof(float) * 16;
glBufferData(GL_ARRAY_BUFFER, mats.size() * one_mat_all_size, out_mats.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void GLModel::bind_mats_vbo(unsigned int instance_mats_vbo, unsigned int instances_count, int location)
{
if (instance_mats_vbo == 0 || instances_count == 0) {
return;
}
auto one_mat_all_size = sizeof(float) * 16;
auto one_mat_col_size = sizeof(float) * 4;
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, instance_mats_vbo));
for (unsigned int i = 0; i < instances_count; i++) { // set attribute pointers for matrix (4 times vec4)
glsafe(glEnableVertexAttribArray(location));
glsafe(glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) 0));
glsafe(glEnableVertexAttribArray(location + 1));
glsafe(glVertexAttribPointer(location + 1, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) (one_mat_col_size)));
glsafe(glEnableVertexAttribArray(location + 2));
glsafe(glVertexAttribPointer(location + 2, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) (2 * one_mat_col_size)));
glsafe(glEnableVertexAttribArray(location + 3));
glsafe(glVertexAttribPointer(location + 3, 4, GL_FLOAT, GL_FALSE, one_mat_all_size, (void *) (3 * one_mat_col_size)));
// Update the matrix every time after an object is drawn//useful
glsafe(glVertexAttribDivisor(location, 1));
glsafe(glVertexAttribDivisor(location + 1, 1));
glsafe(glVertexAttribDivisor(location + 2, 1));
glsafe(glVertexAttribDivisor(location + 3, 1));
}
}
void GLModel::render_geometry_instance(unsigned int instance_mats_vbo, unsigned int instances_count)
{
render_geometry_instance(instance_mats_vbo, instances_count,std::make_pair<size_t, size_t>(0, get_indices_count()));
}
void GLModel::render_geometry_instance(unsigned int instance_mats_vbo, unsigned int instances_count, const std::pair<size_t, size_t> &range)
{
if (instance_mats_vbo == 0 || instances_count == 0) {
return;
}
if (m_render_data.size() != 1) { return; }
GLShaderProgram *shader = wxGetApp().get_current_shader();
if (shader == nullptr) return;
auto &render_data = m_render_data[0];
// sends data to gpu if not done yet
if (render_data.vbo_id == 0 || render_data.ibo_id == 0) {
if (render_data.geometry.vertices_count() > 0 && render_data.geometry.indices_count() > 0 && !send_to_gpu(render_data.geometry))
return;
}
if (instance_mats_vbo == 0) {
return;
}
const Geometry &data = render_data.geometry;
const GLenum mode = get_primitive_mode(data.format);
const GLenum index_type = get_index_type(data);
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 tex_coord = Geometry::has_tex_coord(data.format);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, render_data.vbo_id));
int position_id = -1;
int normal_id = -1;
int tex_coord_id = -1;
int instace_mats_id = -1;
if (position) {
position_id = shader->get_attrib_location("v_position");
if (position_id != -1) {
glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes,
(const void *) Geometry::position_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(position_id));
}
}
if (normal) {
normal_id = shader->get_attrib_location("v_normal");
if (normal_id != -1) {
glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes,
(const void *) Geometry::normal_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(normal_id));
}
}
if (tex_coord) {
tex_coord_id = shader->get_attrib_location("v_tex_coord");
if (tex_coord_id != -1) {
glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes,
(const void *) Geometry::tex_coord_offset_bytes(data.format)));
glsafe(::glEnableVertexAttribArray(tex_coord_id));
}
}
//glBindAttribLocation(shader->get_id(), 2, "instanceMatrix");
//glBindAttribLocation(2, "instanceMatrix");
//shader->bind(shaderProgram, 0, 'position');
instace_mats_id = shader->get_attrib_location("instanceMatrix");
if (instace_mats_id != -1) {
bind_mats_vbo(instance_mats_vbo, instances_count, instace_mats_id);
}
else {
return;
}
auto res = shader->set_uniform("uniform_color", render_data.color);
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, render_data.ibo_id));
glsafe(::glDrawElementsInstanced(mode, range.second - range.first, index_type, (const void *) (range.first * Geometry::index_stride_bytes(data)), instances_count));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
if (instace_mats_id != -1) glsafe(::glDisableVertexAttribArray(instace_mats_id));
if (tex_coord_id != -1) glsafe(::glDisableVertexAttribArray(tex_coord_id));
if (normal_id != -1) glsafe(::glDisableVertexAttribArray(normal_id));
if (position_id != -1) glsafe(::glDisableVertexAttribArray(position_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const
{
if (instances_vbo == 0)
@@ -778,7 +1140,59 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
bool GLModel::send_to_gpu(RenderData& data, const std::vector<float>& vertices, const std::vector<unsigned int>& indices) const
bool GLModel::send_to_gpu(Geometry &geometry)
{
if (m_render_data.size() != 1) { return false; }
auto& render_data = m_render_data[0];
if (render_data.vbo_id > 0 || render_data.ibo_id > 0) {
assert(false);
return false;
}
Geometry &data = render_data.geometry;
if (data.vertices.empty() || data.indices.empty()) {
assert(false);
return false;
}
// vertices
glsafe(::glGenBuffers(1, &render_data.vbo_id));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, render_data.vbo_id));
glsafe(::glBufferData(GL_ARRAY_BUFFER, data.vertices_size_bytes(), data.vertices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
render_data.vertices_count = get_vertices_count();
data.vertices = std::vector<float>();
// indices
glsafe(::glGenBuffers(1, &render_data.ibo_id));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, render_data.ibo_id));
const size_t indices_count = data.indices.size();
if (render_data.vertices_count <= 256) {
// convert indices to unsigned char to save gpu memory
std::vector<unsigned char> reduced_indices(indices_count);
for (size_t i = 0; i < indices_count; ++i) { reduced_indices[i] = (unsigned char) data.indices[i]; }
data.index_type = Geometry::EIndexType::UBYTE;
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_count * sizeof(unsigned char), reduced_indices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else if (render_data.vertices_count <= 65536) {
// convert indices to unsigned short to save gpu memory
std::vector<unsigned short> reduced_indices(indices_count);
for (size_t i = 0; i < data.indices.size(); ++i) { reduced_indices[i] = (unsigned short) data.indices[i]; }
data.index_type = Geometry::EIndexType::USHORT;
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_count * sizeof(unsigned short), reduced_indices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
data.index_type = Geometry::EIndexType::UINT;
glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.indices_size_bytes(), data.indices.data(), GL_STATIC_DRAW));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
render_data.indices_count = indices_count;
data.indices = std::vector<unsigned int>();
return true;
}
bool GLModel::send_to_gpu(RenderData &data, const std::vector<float> &vertices, const std::vector<unsigned int> &indices) const
{
if (data.vbo_id > 0 || data.ibo_id > 0) {
assert(false);