Skip to content

Commit

Permalink
Merge pull request #8 from Neizvestnyj/obj-convert-support
Browse files Browse the repository at this point in the history
Obj convert support
  • Loading branch information
Neizvestnyj committed Aug 14, 2022
2 parents ee8f475 + c5b4256 commit 6b179fe
Show file tree
Hide file tree
Showing 37 changed files with 746 additions and 99 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

file(GLOB SOURCES "stl2obj/src/*")
file(GLOB SOURCES "stl2obj/src/*" "stl2obj/src/obj_to_stl/*" "stl2obj/src/stl_to_obj/*")

add_executable(stl2obj ${SOURCES})
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# stl-to-obj

## What is it?
It is powerful python tool to convert stl file to obj using c++ in backend and built
with cython for all platforms
It is powerful python tool to convert **.stl** file to **.obj** and **.obj** file to **.stl**
using c++ in backend and built with cython for all platforms

[![PyPI version](https://img.shields.io/pypi/v/stl2obj.svg)](https://pypi.org/project/stl2obj)
[![Documentation Status](https://readthedocs.org/projects/stl-to-obj/badge/?version=latest)](https://stl-to-obj.readthedocs.io/en/latest/?badge=latest)
Expand Down Expand Up @@ -47,11 +47,11 @@ python setup.py install
```py
from stl2obj import Stl2Obj

stl = 'path-to-stl-file'
obj = 'path-to-obj-file'
src = 'path-to-src-file' # may be stl or obj
dst = 'path-to-dst-file' # may be stl or obj
callback = lambda code: print(code)

Stl2Obj().convert(stl, obj, callback)
Stl2Obj().convert(src, dst, callback)
```

## Usage with [python-for-android](https://github.com/kivy/python-for-android)
Expand Down Expand Up @@ -89,4 +89,4 @@ toolchain create Stl-to-obj examples/kivy_example

## Authors

[Neizvestnyj](https://github.com/Neizvestnyj), [psychowasp](https://github.com/psychowasp), [Amir Baserinia](https://github.com/baserinia)
[Neizvestnyj](https://github.com/Neizvestnyj), [psychowasp](https://github.com/psychowasp), [Amir Baserinia](https://github.com/baserinia), [psaghelyi](https://github.com/psaghelyi)
6 changes: 3 additions & 3 deletions examples/base_example/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

current_folder = os.path.join(pathlib.Path(__file__).parents[2].resolve(), 'files')

stl = os.path.join(current_folder, 'cube.stl')
obj = os.path.join(current_folder, 'cube.obj')
src = os.path.join(current_folder, 'cube.stl')
dst = os.path.join(current_folder, 'cube.obj')
a = Stl2Obj()
a.convert(stl, obj)
a.convert(src, dst)
10 changes: 6 additions & 4 deletions examples/kivy_example/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,14 @@ def convert(self):
start_time = time.time()
self.reset_widgets(True)

stl = self.get_file(self.root.ids.field_stl.text)
obj = self.get_file(self.root.ids.field_obj.text)
src = self.get_file(self.root.ids.field_stl.text)
dst = self.get_file(self.root.ids.field_obj.text)

try:
Stl2Obj().convert(src=stl, dst=obj,
debug=True, callback=self.callback,
Stl2Obj().convert(src=src,
dst=dst,
debug=True,
callback=self.callback,
progress_callback=self.progress)
print(f'Conversion done behind {time.time() - start_time}')
except (FileNotFoundError, TypeError) as e:
Expand Down
10 changes: 6 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ def get_version() -> str:
path_to_src = os.path.join(stl2obj_dir, 'src')

# check if all files are included
for file in os.listdir(path_to_src):
name, ext = os.path.splitext(file)
for fd, sub_fds, fns in os.walk(path_to_src):
for fn in fns:
path_to_file = os.path.join(fd, fn)
name, ext = os.path.splitext(path_to_file)

if ext == '.cpp':
cpp_sources.append(file)
if ext == '.cpp':
cpp_sources.append(path_to_file)

additional_files = [os.path.join(path_to_src, src) for src in cpp_sources]

Expand Down
2 changes: 1 addition & 1 deletion stl2obj/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.2"
__version__ = "0.3"
103 changes: 103 additions & 0 deletions stl2obj/src/convert.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include <string>

#include "stl_to_obj/vectornd.h"
#include "stl_to_obj/geometry.h"
#include "stl_to_obj/importstl.h"
#include "stl_to_obj/exportobj.h"

#include "obj_to_stl/convert_file.h"

#include <iostream>
#include <exception>
#include <sstream>
#include <vector>
#include <cstring>

#include "convert.h"
#include "mode.h"
#include "paths.h"

void convert(
string src,
string dst,
bool debug = true,
void(*callback)(int, void*) = NULL,
void* py_callback = NULL,
void* py_progress = NULL) {
/*
`src` - full path to stl file in binary format
`dst` - full path to obj file
`callback` - just function, that call pointer like `py_object`
*/

int code = 0;
int progress_part = 1; // how much progress must pass to trigger (how many iterations of the loop should go through) `py_progress(1)`
string tmp_src = "";
string type = get_extention(src); // stl/obj

if (debug == false) {
streambuf* old = cout.rdbuf();
cout.rdbuf(0);
}

if (type == "stl") {
cout << "Convert stl to obj" << endl;
string mode = get_stl_mode(src);

if (mode == "ASCII") {
cout << "Convert ASCII to BIN" << endl;
progress_part = 2;

tmp_src = split_filename(src, "dir") + "tmp.stl";
int res = stl_mode_converter(src, tmp_src, "ASCII", progress_part, callback, py_callback, py_progress, true);

if (res != 0) {
code = 1;
}
else {
src = tmp_src;
}
}

if (code == 0) {
// create a geometry tesselation object
Geometry tessel;

// fill up the tesselation object with STL data (load STL)
tessel.visit(ImportSTL(src, callback, py_progress, progress_part));

// write down the tesselation object into OBJ file (save OBJ)
tessel.visit(ExportOBJ(dst));

if (tmp_src != "") {
remove(tmp_src.c_str());
cout << tmp_src << " removed" << endl;
}
}
}
else {
cout << "Convert obj to stl" << endl;

Coord3TR tr;
ObjModel model;
StlModel stlModel;

model = ObjModel(callback, py_progress);

try {
read_stl(model, src);
convert_stl2obj(model, stlModel, tr);
write_obj(stlModel, dst);
}
catch (const exception& e)
{
cerr << e.what() << "\n";
code = -1;
}
}

if (callback && py_callback) {
// for python lib `callback` written in c, `py_object` - pointer to python function
callback(code, py_callback);
}
}
File renamed without changes.
69 changes: 0 additions & 69 deletions stl2obj/src/converter.cpp

This file was deleted.

8 changes: 4 additions & 4 deletions stl2obj/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <string>
#include <iostream>

#include "converter.h"
#include "convert.h"

using namespace std;

Expand Down Expand Up @@ -31,14 +31,14 @@ int main(int argc, char** argv)
{
string src, dst;

if (argv[0] && argv[1]) {
if (argc > 2) {
src = argv[1];
dst = argv[2];
}
else {
cout << "You cant pass arguments, using default" << endl;
src = "F:\\VS\\stl-to-obj\\files\\cube.stl";
dst = "F:\\VS\\stl-to-obj\\files\\cube.obj";
src = "F:\\VS\\stl-to-obj\\files\\cube.obj";
dst = "F:\\VS\\stl-to-obj\\files\\cube.stl";
}

cout << src << " will be converted and save as " << dst << endl;
Expand Down
78 changes: 78 additions & 0 deletions stl2obj/src/obj_to_stl/Converter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "Converter.h"

#include <stdexcept>
#include <algorithm>
#include <cfloat>

using namespace std;

void Converter::Convert(const ObjModel& objModel, StlModel& stlModel)
{
// collect coordinates for polygon faces
for (const auto& f : objModel.GetFaces())
{
CreatePolygonsWithNorms(f, objModel.GetVertices(), objModel.GetNorms());
}

// convert polygons to triangles
for (const auto& poly : polygons_)
{
Coord3 translate = trMatix_.ApplyTransformation(objModel.GetCoordMin());
CreateTrianglesWithNormsAndTransform(poly, translate);
}

// sort triangles by z axis (not strictly enforced)
sort(triangles_.begin(), triangles_.end(),
[](const array<Coord3, 3>& a, const array<Coord3, 3>& b) -> bool
{
return min({ a[0].z, a[1].z, a[2].z }) > min({ b[0].z, b[1].z, b[2].z });
});

// move triangles to stl
for (const auto& t : triangles_)
{
// generate normal which should be perpendicular to the triangle plane
Coord3 nv = Coord3::CrossProduct(t[1] - t[0], t[2] - t[0]).Normalize();

stlModel.AddTriangle({ t[0], t[1], t[2], nv });
}
}

void Converter::CreatePolygonsWithNorms(const vector<FaceVertex>& faceVertices, const vector<Coord3>& objVertices, const vector<Coord3>& objNorms)
{
// collect face vertices with norms
vector<Coord3N> face;
for (auto const& v : faceVertices)
{
const Coord3& vt = v.vIndex() ? objVertices[static_cast<size_t>(v.vIndex() - 1)] : Coord3();
const Coord3& vn = v.vnIndex() ? objNorms[static_cast<size_t>(v.vnIndex() - 1)] : Coord3();

face.push_back({ vt, vn });
}
polygons_.push_back(face);
}

void Converter::CreateTrianglesWithNormsAndTransform(const vector<Coord3N>& poly, const Coord3& translate)
{
if (poly.size() < 3)
{
throw runtime_error("Polygon has less than 3 vertices");
};

// traverse polygon and make triangles
for (vector<Coord3N>::const_iterator it = poly.begin(); it+2 != poly.end(); ++it)
{
const Coord3N& p0 = *poly.begin();
const Coord3N& p1 = *(it+1);
const Coord3N& p2 = *(it+2);

array<Coord3, 3> triangle
{
trMatix_.ApplyTransformation(p0.vt - translate),
trMatix_.ApplyTransformation(p1.vt - translate),
trMatix_.ApplyTransformation(p2.vt - translate)
};

triangles_.push_back(triangle);
}
}
28 changes: 28 additions & 0 deletions stl2obj/src/obj_to_stl/Converter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include "ObjModel.h"
#include "StlModel.h"

#include <vector>
#include <array>

using namespace std;

class Converter
{
public:
Converter(Coord3TR trMatix) : trMatix_(trMatix) {}
void Convert(const ObjModel& objModel, StlModel& stlModel);

private:
vector<vector<Coord3N>> polygons_; // list of faces -> list of coordinate pairs (vertex, norm)
vector<array<Coord3,3>> triangles_; // list of faces -> 3 * coordinates

Coord3TR trMatix_;

void CreatePolygonsWithNorms(const vector<FaceVertex>& faceVertices, const vector<Coord3>& objVertices, const vector<Coord3>& objNorms);
void CreateTrianglesWithNormsAndTransform(const vector<Coord3N>& poly, const Coord3& translate);
};



0 comments on commit 6b179fe

Please sign in to comment.