mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-01 04:21:59 +08:00
Port the OBJ parser to C++
This commit is contained in:
parent
80718b79a9
commit
de19e5dabc
@ -1,33 +1,12 @@
|
|||||||
package Slic3r::Format::OBJ;
|
package Slic3r::Format::OBJ;
|
||||||
use Moo;
|
use Moo;
|
||||||
|
|
||||||
use File::Basename qw(basename);
|
|
||||||
|
|
||||||
sub read_file {
|
sub read_file {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($file) = @_;
|
my ($file) = @_;
|
||||||
|
|
||||||
Slic3r::open(\my $fh, '<', $file) or die "Failed to open $file\n";
|
|
||||||
my $vertices = [];
|
|
||||||
my $facets = [];
|
|
||||||
while (<$fh>) {
|
|
||||||
if (/^v ([^ ]+)\s+([^ ]+)\s+([^ ]+)/) {
|
|
||||||
push @$vertices, [$1, $2, $3];
|
|
||||||
} elsif (/^f (\d+).*? (\d+).*? (\d+).*?/) {
|
|
||||||
push @$facets, [ $1-1, $2-1, $3-1 ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close $fh;
|
|
||||||
|
|
||||||
my $mesh = Slic3r::TriangleMesh->new;
|
|
||||||
$mesh->ReadFromPerl($vertices, $facets);
|
|
||||||
$mesh->check_topology;
|
|
||||||
|
|
||||||
my $model = Slic3r::Model->new;
|
my $model = Slic3r::Model->new;
|
||||||
|
$model->read_obj($file);
|
||||||
my $basename = basename($file);
|
|
||||||
my $object = $model->add_object(input_file => $file, name => $basename);
|
|
||||||
my $volume = $object->add_volume(mesh => $mesh, name => $basename);
|
|
||||||
return $model;
|
return $model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +117,7 @@ src/slic3r/GUI/3DScene.cpp
|
|||||||
src/slic3r/GUI/3DScene.hpp
|
src/slic3r/GUI/3DScene.hpp
|
||||||
src/slic3r/GUI/GUI.cpp
|
src/slic3r/GUI/GUI.cpp
|
||||||
src/slic3r/GUI/GUI.hpp
|
src/slic3r/GUI/GUI.hpp
|
||||||
|
src/tiny_obj_loader.h
|
||||||
src/xsinit.h
|
src/xsinit.h
|
||||||
t/01_trianglemesh.t
|
t/01_trianglemesh.t
|
||||||
t/03_point.t
|
t/03_point.t
|
||||||
|
@ -3,11 +3,17 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#define TINYOBJLOADER_IMPLEMENTATION
|
||||||
|
#include "tiny_obj_loader.h"
|
||||||
|
|
||||||
namespace Slic3r { namespace IO {
|
namespace Slic3r { namespace IO {
|
||||||
|
|
||||||
bool
|
bool
|
||||||
STL::read(std::string input_file, TriangleMesh* mesh)
|
STL::read(std::string input_file, TriangleMesh* mesh)
|
||||||
{
|
{
|
||||||
|
// TODO: encode file name
|
||||||
|
// TODO: check that file exists
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mesh->ReadSTLFile(input_file);
|
mesh->ReadSTLFile(input_file);
|
||||||
mesh->check_topology();
|
mesh->check_topology();
|
||||||
@ -20,9 +26,6 @@ STL::read(std::string input_file, TriangleMesh* mesh)
|
|||||||
bool
|
bool
|
||||||
STL::read(std::string input_file, Model* model)
|
STL::read(std::string input_file, Model* model)
|
||||||
{
|
{
|
||||||
// TODO: encode file name
|
|
||||||
// TODO: check that file exists
|
|
||||||
|
|
||||||
TriangleMesh mesh;
|
TriangleMesh mesh;
|
||||||
if (!STL::read(input_file, &mesh)) return false;
|
if (!STL::read(input_file, &mesh)) return false;
|
||||||
|
|
||||||
@ -50,6 +53,77 @@ STL::write(TriangleMesh& mesh, std::string output_file, bool binary)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
OBJ::read(std::string input_file, TriangleMesh* mesh)
|
||||||
|
{
|
||||||
|
Model model;
|
||||||
|
OBJ::read(input_file, &model);
|
||||||
|
*mesh = model.mesh();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
OBJ::read(std::string input_file, Model* model)
|
||||||
|
{
|
||||||
|
// TODO: encode file name
|
||||||
|
// TODO: check that file exists
|
||||||
|
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, input_file.c_str());
|
||||||
|
|
||||||
|
if (!err.empty()) { // `err` may contain warning message.
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
throw std::runtime_error("Error while reading OBJ file");
|
||||||
|
|
||||||
|
ModelObject* object = model->add_object();
|
||||||
|
object->name = input_file; // TODO: use basename()
|
||||||
|
object->input_file = input_file;
|
||||||
|
|
||||||
|
// Loop over shapes and add a volume for each one.
|
||||||
|
for (std::vector<tinyobj::shape_t>::const_iterator shape = shapes.begin();
|
||||||
|
shape != shapes.end(); ++shape) {
|
||||||
|
|
||||||
|
Pointf3s points;
|
||||||
|
std::vector<Point3> facets;
|
||||||
|
|
||||||
|
// Read vertices.
|
||||||
|
assert((shape->mesh.vertices.size() % 3) == 0);
|
||||||
|
for (size_t v = 0; v < attrib.vertices.size(); ++v) {
|
||||||
|
points.push_back(Pointf3(
|
||||||
|
attrib.vertices[v],
|
||||||
|
attrib.vertices[++v],
|
||||||
|
attrib.vertices[++v]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop over facets of the current shape.
|
||||||
|
for (size_t f = 0; f < shape->mesh.num_face_vertices.size(); ++f) {
|
||||||
|
// tiny_obj_loader should triangulate any facet with more than 3 vertices
|
||||||
|
assert((shape->mesh.num_face_vertices[f] % 3) == 0);
|
||||||
|
|
||||||
|
facets.push_back(Point3(
|
||||||
|
shape->mesh.indices[f*3+0].vertex_index,
|
||||||
|
shape->mesh.indices[f*3+1].vertex_index,
|
||||||
|
shape->mesh.indices[f*3+2].vertex_index
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
TriangleMesh mesh(points, facets);
|
||||||
|
mesh.check_topology();
|
||||||
|
ModelVolume* volume = object->add_volume(mesh);
|
||||||
|
volume->name = input_file; // TODO: use basename()
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
OBJ::write(TriangleMesh& mesh, std::string output_file)
|
OBJ::write(TriangleMesh& mesh, std::string output_file)
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,8 @@ class STL
|
|||||||
class OBJ
|
class OBJ
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static bool read(std::string input_file, TriangleMesh* mesh);
|
||||||
|
static bool read(std::string input_file, Model* model);
|
||||||
static bool write(TriangleMesh& mesh, std::string output_file);
|
static bool write(TriangleMesh& mesh, std::string output_file);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
2020
xs/src/tiny_obj_loader.h
Normal file
2020
xs/src/tiny_obj_loader.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
%{
|
%{
|
||||||
#include <xsinit.h>
|
#include <xsinit.h>
|
||||||
|
#include "libslic3r/IO.hpp"
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
%}
|
%}
|
||||||
@ -13,6 +14,9 @@
|
|||||||
Clone<Model> clone()
|
Clone<Model> clone()
|
||||||
%code%{ RETVAL = THIS; %};
|
%code%{ RETVAL = THIS; %};
|
||||||
|
|
||||||
|
bool read_obj(std::string input_file)
|
||||||
|
%code%{ RETVAL = Slic3r::IO::OBJ::read(input_file, THIS); %};
|
||||||
|
|
||||||
%name{_add_object} Ref<ModelObject> add_object();
|
%name{_add_object} Ref<ModelObject> add_object();
|
||||||
Ref<ModelObject> _add_object_clone(ModelObject* other, bool copy_volumes = true)
|
Ref<ModelObject> _add_object_clone(ModelObject* other, bool copy_volumes = true)
|
||||||
%code%{ RETVAL = THIS->add_object(*other, copy_volumes); %};
|
%code%{ RETVAL = THIS->add_object(*other, copy_volumes); %};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user