Port the OBJ parser to C++

This commit is contained in:
Alessandro Ranellucci 2017-03-01 20:13:10 +01:00
parent 80718b79a9
commit de19e5dabc
6 changed files with 2105 additions and 25 deletions

View File

@ -1,33 +1,12 @@
package Slic3r::Format::OBJ;
use Moo;
use File::Basename qw(basename);
sub read_file {
my $self = shift;
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 $basename = basename($file);
my $object = $model->add_object(input_file => $file, name => $basename);
my $volume = $object->add_volume(mesh => $mesh, name => $basename);
$model->read_obj($file);
return $model;
}

View File

@ -117,6 +117,7 @@ src/slic3r/GUI/3DScene.cpp
src/slic3r/GUI/3DScene.hpp
src/slic3r/GUI/GUI.cpp
src/slic3r/GUI/GUI.hpp
src/tiny_obj_loader.h
src/xsinit.h
t/01_trianglemesh.t
t/03_point.t

View File

@ -3,11 +3,17 @@
#include <fstream>
#include <iostream>
#define TINYOBJLOADER_IMPLEMENTATION
#include "tiny_obj_loader.h"
namespace Slic3r { namespace IO {
bool
STL::read(std::string input_file, TriangleMesh* mesh)
{
// TODO: encode file name
// TODO: check that file exists
try {
mesh->ReadSTLFile(input_file);
mesh->check_topology();
@ -20,9 +26,6 @@ STL::read(std::string input_file, TriangleMesh* mesh)
bool
STL::read(std::string input_file, Model* model)
{
// TODO: encode file name
// TODO: check that file exists
TriangleMesh mesh;
if (!STL::read(input_file, &mesh)) return false;
@ -50,6 +53,77 @@ STL::write(TriangleMesh& mesh, std::string output_file, bool binary)
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
OBJ::write(TriangleMesh& mesh, std::string output_file)
{

View File

@ -19,6 +19,8 @@ class STL
class OBJ
{
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);
};

2020
xs/src/tiny_obj_loader.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
%{
#include <xsinit.h>
#include "libslic3r/IO.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/PrintConfig.hpp"
%}
@ -13,6 +14,9 @@
Clone<Model> clone()
%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();
Ref<ModelObject> _add_object_clone(ModelObject* other, bool copy_volumes = true)
%code%{ RETVAL = THIS->add_object(*other, copy_volumes); %};