mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 09:17:52 -06:00
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()
|
void GCodeViewer::VBuffer::reset()
|
||||||
{
|
{
|
||||||
// release gpu memory
|
// release gpu memory
|
||||||
if (!ids.empty()) {
|
if (!vbos.empty()) {
|
||||||
glsafe(::glDeleteBuffers(static_cast<GLsizei>(ids.size()), static_cast<const GLuint*>(ids.data())));
|
glsafe(::glDeleteBuffers(static_cast<GLsizei>(vbos.size()), static_cast<const GLuint*>(vbos.data())));
|
||||||
ids.clear();
|
vbos.clear();
|
||||||
}
|
}
|
||||||
|
sizes.clear();
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -358,7 +358,8 @@ const std::vector<GCodeViewer::Color> GCodeViewer::Range_Colors {{
|
||||||
|
|
||||||
GCodeViewer::GCodeViewer()
|
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) {
|
for (size_t i = 0; i < m_buffers.size(); ++i) {
|
||||||
TBuffer& buffer = m_buffers[i];
|
TBuffer& buffer = m_buffers[i];
|
||||||
switch (buffer_type(i))
|
switch (buffer_type(i))
|
||||||
|
@ -633,6 +634,13 @@ void GCodeViewer::render() const
|
||||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
#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)
|
void GCodeViewer::update_sequential_view_current(unsigned int first, unsigned int last)
|
||||||
{
|
{
|
||||||
auto is_visible = [this](unsigned int id) {
|
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
|
void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
|
||||||
{
|
{
|
||||||
#if !ENABLE_SPLITTED_VERTEX_BUFFER
|
|
||||||
|
|
||||||
if (filename == nullptr)
|
if (filename == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -758,15 +764,24 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
|
||||||
wxBusyCursor busy;
|
wxBusyCursor busy;
|
||||||
|
|
||||||
// the data needed is contained into the Extrude TBuffer
|
// the data needed is contained into the Extrude TBuffer
|
||||||
const TBuffer& buffer = m_buffers[buffer_id(EMoveType::Extrude)];
|
const TBuffer& t_buffer = m_buffers[buffer_id(EMoveType::Extrude)];
|
||||||
if (!buffer.has_data())
|
if (!t_buffer.has_data())
|
||||||
return;
|
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
|
// collect color information to generate materials
|
||||||
std::vector<Color> colors;
|
std::vector<Color> colors;
|
||||||
for (const RenderPath& path : buffer.render_paths) {
|
for (const RenderPath& path : t_buffer.render_paths) {
|
||||||
colors.push_back(path.color);
|
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
|
// save materials file
|
||||||
boost::filesystem::path mat_filename(filename);
|
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, "# Generated by %s based on Slic3r\n", SLIC3R_BUILD_ID);
|
||||||
fprintf(fp, "\nmtllib ./%s\n", mat_filename.filename().string().c_str());
|
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
|
// get vertices data from vertex buffer on gpu
|
||||||
size_t floats_per_vertex = buffer.vertices.vertex_size_floats();
|
size_t floats_per_vertex = buffer.vertices.vertex_size_floats();
|
||||||
VertexBuffer vertices = VertexBuffer(buffer.vertices.count * floats_per_vertex);
|
VertexBuffer vertices = VertexBuffer(buffer.vertices.count * floats_per_vertex);
|
||||||
|
@ -1041,10 +1128,9 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const
|
||||||
|
|
||||||
++ i;
|
++ i;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
#endif // !ENABLE_SPLITTED_VERTEX_BUFFER
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 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;
|
GLuint id = 0;
|
||||||
glsafe(::glGenBuffers(1, &id));
|
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(::glBindBuffer(GL_ARRAY_BUFFER, id));
|
||||||
glsafe(::glBufferData(GL_ARRAY_BUFFER, size_bytes, v_buffer.data(), GL_STATIC_DRAW));
|
glsafe(::glBufferData(GL_ARRAY_BUFFER, size_bytes, v_buffer.data(), GL_STATIC_DRAW));
|
||||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
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
|
// ensure there is at least one index buffer
|
||||||
if (i_multibuffer.empty()) {
|
if (i_multibuffer.empty()) {
|
||||||
i_multibuffer.push_back(IndexBuffer());
|
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
|
// if adding the indices for the current segment exceeds the threshold size of the current index buffer
|
||||||
// create another index buffer
|
// create another index buffer
|
||||||
if (i_multibuffer.back().size() * sizeof(unsigned int) >= IBUFFER_THRESHOLD_BYTES - t_buffer.indices_per_segment_size_bytes()) {
|
if (i_multibuffer.back().size() * sizeof(unsigned int) >= IBUFFER_THRESHOLD_BYTES - t_buffer.indices_per_segment_size_bytes()) {
|
||||||
i_multibuffer.push_back(IndexBuffer());
|
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
|
// 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.first;
|
||||||
curr_vertex_buffer.second = 0;
|
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) {
|
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) {
|
||||||
Path& last_path = t_buffer.paths.back();
|
Path& last_path = t_buffer.paths.back();
|
||||||
|
|
|
@ -59,7 +59,9 @@ class GCodeViewer
|
||||||
EFormat format{ EFormat::Position };
|
EFormat format{ EFormat::Position };
|
||||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||||
// vbos id
|
// 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
|
#else
|
||||||
// vbo id
|
// vbo id
|
||||||
unsigned int id{ 0 };
|
unsigned int id{ 0 };
|
||||||
|
@ -301,7 +303,7 @@ class GCodeViewer
|
||||||
|
|
||||||
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
#if ENABLE_SPLITTED_VERTEX_BUFFER
|
||||||
bool has_data() const {
|
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
|
#else
|
||||||
bool has_data() const { return vertices.id != 0 && !indices.empty() && indices.front().id != 0; }
|
bool has_data() const { return vertices.id != 0 && !indices.empty() && indices.front().id != 0; }
|
||||||
|
@ -588,6 +590,9 @@ public:
|
||||||
void render() const;
|
void render() const;
|
||||||
|
|
||||||
bool has_data() const { return !m_roles.empty(); }
|
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_paths_bounding_box() const { return m_paths_bounding_box; }
|
||||||
const BoundingBoxf3& get_max_bounding_box() const { return m_max_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
|
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();
|
return m_gcode_viewer.has_data();
|
||||||
|
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLCanvas3D::export_toolpaths_to_obj(const char* filename) const
|
void GLCanvas3D::export_toolpaths_to_obj(const char* filename) const
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue