mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-31 07:02:01 +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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
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 "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); %};
|
||||
|
Loading…
x
Reference in New Issue
Block a user