ENABLE_SPLITTED_VERTEX_BUFFER - fixed export of toolpaths to obj files
This commit is contained in:
parent
dc781535b2
commit
67e144f329
3 changed files with 114 additions and 18 deletions
|
@ -83,11 +83,11 @@ static float round_to_nearest(float value, unsigned int decimals)
|
|||
void GCodeViewer::VBuffer::reset()
|
||||
{
|
||||
// release gpu memory
|
||||
if (!ids.empty()) {
|
||||
glsafe(::glDeleteBuffers(static_cast<GLsizei>(ids.size()), static_cast<const GLuint*>(ids.data())));
|
||||
ids.clear();
|
||||
if (!vbos.empty()) {
|
||||
glsafe(::glDeleteBuffers(static_cast<GLsizei>(vbos.size()), static_cast<const GLuint*>(vbos.data())));
|
||||
vbos.clear();
|
||||
}
|
||||
|
||||
sizes.clear();
|
||||
count = 0;
|
||||
}
|
||||
#else
|
||||
|
@ -358,7 +358,8 @@ const std::vector<GCodeViewer::Color> GCodeViewer::Range_Colors {{
|
|||
|
||||
GCodeViewer::GCodeViewer()
|
||||
{
|
||||
// initializes non opengl data of TBuffers
|
||||
// initializes non OpenGL data of TBuffers
|
||||
// OpenGL data are initialized into render().init_gl_data()
|
||||
for (size_t i = 0; i < m_buffers.size(); ++i) {
|
||||
TBuffer& buffer = m_buffers[i];
|
||||
switch (buffer_type(i))
|
||||
|
@ -633,6 +634,13 @@ void GCodeViewer::render() const
|
|||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||
}
|
||||
|
||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
bool GCodeViewer::can_export_toolpaths() const
|
||||
{
|
||||
return has_data() && m_buffers[buffer_id(EMoveType::Extrude)].render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle;
|
||||
}
|
||||
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
|
||||
void GCodeViewer::update_sequential_view_current(unsigned int first, unsigned int last)
|
||||
{
|
||||
auto is_visible = [this](unsigned int id) {
|
||||
|
@ -747,8 +755,6 @@ void GCodeViewer::set_layers_z_range(const std::array<unsigned int, 2>& layers_z
|
|||
|
||||
void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
|
||||
{
|
||||
#if !ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
|
||||
if (filename == nullptr)
|
||||
return;
|
||||
|
||||
|
@ -758,15 +764,24 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
|
|||
wxBusyCursor busy;
|
||||
|
||||
// the data needed is contained into the Extrude TBuffer
|
||||
const TBuffer& buffer = m_buffers[buffer_id(EMoveType::Extrude)];
|
||||
if (!buffer.has_data())
|
||||
const TBuffer& t_buffer = m_buffers[buffer_id(EMoveType::Extrude)];
|
||||
if (!t_buffer.has_data())
|
||||
return;
|
||||
|
||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Triangle)
|
||||
return;
|
||||
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
|
||||
// collect color information to generate materials
|
||||
std::vector<Color> colors;
|
||||
for (const RenderPath& path : buffer.render_paths) {
|
||||
for (const RenderPath& path : t_buffer.render_paths) {
|
||||
colors.push_back(path.color);
|
||||
}
|
||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
std::sort(colors.begin(), colors.end());
|
||||
colors.erase(std::unique(colors.begin(), colors.end()), colors.end());
|
||||
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
|
||||
// save materials file
|
||||
boost::filesystem::path mat_filename(filename);
|
||||
|
@ -801,6 +816,78 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
|
|||
fprintf(fp, "# Generated by %s based on Slic3r\n", SLIC3R_BUILD_ID);
|
||||
fprintf(fp, "\nmtllib ./%s\n", mat_filename.filename().string().c_str());
|
||||
|
||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
const size_t floats_per_vertex = t_buffer.vertices.vertex_size_floats();
|
||||
|
||||
std::vector<Vec3f> out_vertices;
|
||||
std::vector<Vec3f> out_normals;
|
||||
std::vector<size_t> vertices_offsets;
|
||||
vertices_offsets.push_back(0);
|
||||
|
||||
// get vertices/normals data from vertex buffers on gpu
|
||||
for (size_t i = 0; i < t_buffer.vertices.vbos.size(); ++i) {
|
||||
const size_t floats_count = t_buffer.vertices.sizes[i] / sizeof(float);
|
||||
VertexBuffer vertices(floats_count);
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, t_buffer.vertices.vbos[i]));
|
||||
glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, 0, static_cast<GLsizeiptr>(t_buffer.vertices.sizes[i]), static_cast<void*>(vertices.data())));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
const size_t vertices_count = floats_count / floats_per_vertex;
|
||||
for (size_t j = 0; j < vertices_count; ++j) {
|
||||
const size_t base = j * floats_per_vertex;
|
||||
out_vertices.push_back({ vertices[base + 0], vertices[base + 1], vertices[base + 2] });
|
||||
out_normals.push_back({ vertices[base + 3], vertices[base + 4], vertices[base + 5] });
|
||||
}
|
||||
vertices_offsets.push_back(vertices_offsets.back() + vertices_count);
|
||||
}
|
||||
|
||||
// save vertices to file
|
||||
fprintf(fp, "\n# vertices\n");
|
||||
for (const Vec3f& v : out_vertices) {
|
||||
fprintf(fp, "v %g %g %g\n", v[0], v[1], v[2]);
|
||||
}
|
||||
|
||||
// save normals to file
|
||||
fprintf(fp, "\n# normals\n");
|
||||
for (const Vec3f& n : out_normals) {
|
||||
fprintf(fp, "vn %g %g %g\n", n[0], n[1], n[2]);
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (const Color& color : colors) {
|
||||
// save material triangles to file
|
||||
fprintf(fp, "\nusemtl material_%zu\n", i + 1);
|
||||
fprintf(fp, "# triangles material %zu\n", i + 1);
|
||||
|
||||
for (const RenderPath& render_path : t_buffer.render_paths) {
|
||||
if (render_path.color != color)
|
||||
continue;
|
||||
|
||||
const IBuffer& ibuffer = t_buffer.indices[render_path.index_buffer_id];
|
||||
const size_t vertices_offset = vertices_offsets[render_path.index_buffer_id];
|
||||
|
||||
// get indices data from index buffer on gpu
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer.ibo));
|
||||
for (size_t j = 0; j < render_path.sizes.size(); ++j) {
|
||||
const size_t triangles_count = render_path.sizes[j] / 3;
|
||||
IndexBuffer indices(render_path.sizes[j]);
|
||||
glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLintptr>(render_path.offsets[j]),
|
||||
static_cast<GLsizeiptr>(render_path.sizes[j] * sizeof(unsigned int)), static_cast<void*>(indices.data())));
|
||||
|
||||
for (size_t k = 0; k < triangles_count; ++k) {
|
||||
const size_t base = k * 3;
|
||||
const size_t v1 = 1 + static_cast<size_t>(indices[base + 0]) + vertices_offset;
|
||||
const size_t v2 = 1 + static_cast<size_t>(indices[base + 1]) + vertices_offset;
|
||||
const size_t v3 = 1 + static_cast<size_t>(indices[base + 2]) + vertices_offset;
|
||||
if (v1 != v2)
|
||||
// do not export dummy triangles
|
||||
fprintf(fp, "f %zu//%zu %zu//%zu %zu//%zu\n", v1, v1, v2, v2, v3, v3);
|
||||
}
|
||||
}
|
||||
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
++i;
|
||||
}
|
||||
#else
|
||||
// get vertices data from vertex buffer on gpu
|
||||
size_t floats_per_vertex = buffer.vertices.vertex_size_floats();
|
||||
VertexBuffer vertices = VertexBuffer(buffer.vertices.count * floats_per_vertex);
|
||||
|
@ -1041,10 +1128,9 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
|
|||
|
||||
++ i;
|
||||
}
|
||||
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
|
||||
fclose(fp);
|
||||
|
||||
#endif // !ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
}
|
||||
|
||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
|
@ -1525,7 +1611,8 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
|||
|
||||
GLuint id = 0;
|
||||
glsafe(::glGenBuffers(1, &id));
|
||||
t_buffer.vertices.ids.push_back(static_cast<unsigned int>(id));
|
||||
t_buffer.vertices.vbos.push_back(static_cast<unsigned int>(id));
|
||||
t_buffer.vertices.sizes.push_back(size_bytes);
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, id));
|
||||
glsafe(::glBufferData(GL_ARRAY_BUFFER, size_bytes, v_buffer.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
|
@ -1581,14 +1668,14 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
|||
// ensure there is at least one index buffer
|
||||
if (i_multibuffer.empty()) {
|
||||
i_multibuffer.push_back(IndexBuffer());
|
||||
vbo_index_list.push_back(t_buffer.vertices.ids[curr_vertex_buffer.first]);
|
||||
vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]);
|
||||
}
|
||||
|
||||
// if adding the indices for the current segment exceeds the threshold size of the current index buffer
|
||||
// create another index buffer
|
||||
if (i_multibuffer.back().size() * sizeof(unsigned int) >= IBUFFER_THRESHOLD_BYTES - t_buffer.indices_per_segment_size_bytes()) {
|
||||
i_multibuffer.push_back(IndexBuffer());
|
||||
vbo_index_list.push_back(t_buffer.vertices.ids[curr_vertex_buffer.first]);
|
||||
vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]);
|
||||
}
|
||||
|
||||
// if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer
|
||||
|
@ -1598,7 +1685,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
|||
|
||||
++curr_vertex_buffer.first;
|
||||
curr_vertex_buffer.second = 0;
|
||||
vbo_index_list.push_back(t_buffer.vertices.ids[curr_vertex_buffer.first]);
|
||||
vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]);
|
||||
|
||||
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) {
|
||||
Path& last_path = t_buffer.paths.back();
|
||||
|
|
|
@ -59,7 +59,9 @@ class GCodeViewer
|
|||
EFormat format{ EFormat::Position };
|
||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
// vbos id
|
||||
std::vector<unsigned int> ids;
|
||||
std::vector<unsigned int> vbos;
|
||||
// sizes of the buffers, in bytes, used in export to obj
|
||||
std::vector<size_t> sizes;
|
||||
#else
|
||||
// vbo id
|
||||
unsigned int id{ 0 };
|
||||
|
@ -301,7 +303,7 @@ class GCodeViewer
|
|||
|
||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
bool has_data() const {
|
||||
return !vertices.ids.empty() && vertices.ids.front() != 0 && !indices.empty() && indices.front().ibo != 0;
|
||||
return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0;
|
||||
}
|
||||
#else
|
||||
bool has_data() const { return vertices.id != 0 && !indices.empty() && indices.front().id != 0; }
|
||||
|
@ -588,6 +590,9 @@ public:
|
|||
void render() const;
|
||||
|
||||
bool has_data() const { return !m_roles.empty(); }
|
||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
bool can_export_toolpaths() const;
|
||||
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
|
||||
const BoundingBoxf3& get_paths_bounding_box() const { return m_paths_bounding_box; }
|
||||
const BoundingBoxf3& get_max_bounding_box() const { return m_max_bounding_box; }
|
||||
|
|
|
@ -3866,7 +3866,11 @@ void GLCanvas3D::update_tooltip_for_settings_item_in_main_toolbar()
|
|||
|
||||
bool GLCanvas3D::has_toolpaths_to_export() const
|
||||
{
|
||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
return m_gcode_viewer.can_export_toolpaths();
|
||||
#else
|
||||
return m_gcode_viewer.has_data();
|
||||
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
|
||||
}
|
||||
|
||||
void GLCanvas3D::export_toolpaths_to_obj(const char* filename) const
|
||||
|
|
Loading…
Add table
Reference in a new issue