Skip to content

Commit 5eef2b0

Browse files
committed
Fix python binding.
1 parent d192402 commit 5eef2b0

2 files changed

Lines changed: 153 additions & 119 deletions

File tree

python/TODO.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
* PBR material
2+
* Define index_t struct
3+
* Python 2.7 binding

python/main.cpp

Lines changed: 150 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,160 +1,191 @@
1-
//python3 module for tinyobjloader
1+
// python3 module for tinyobjloader
22
//
3-
//usage:
3+
// usage:
44
// import tinyobjloader as tol
55
// model = tol.LoadObj(name)
66
// print(model["shapes"])
77
// print(model["materials"]
8+
// note:
9+
// `shape.mesh.index_t` is represented as flattened array: (vertex_index, normal_index, texcoord_index) * num_faces
810

911
#include <Python.h>
1012
#include <vector>
1113
#include "../tiny_obj_loader.h"
1214

1315
typedef std::vector<double> vectd;
16+
typedef std::vector<int> vecti;
1417

15-
PyObject*
16-
pyTupleFromfloat3 (float array[3])
17-
{
18-
int i;
19-
PyObject* tuple = PyTuple_New(3);
18+
PyObject* pyTupleFromfloat3(float array[3]) {
19+
int i;
20+
PyObject* tuple = PyTuple_New(3);
2021

21-
for(i=0; i<=2 ; i++){
22-
PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i]));
23-
}
22+
for (i = 0; i <= 2; i++) {
23+
PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i]));
24+
}
2425

25-
return tuple;
26+
return tuple;
2627
}
2728

28-
extern "C"
29-
{
29+
extern "C" {
30+
31+
static PyObject* pyLoadObj(PyObject* self, PyObject* args) {
32+
PyObject *rtndict, *pyshapes, *pymaterials, *attribobj, *current, *meshobj;
33+
34+
char const* current_name;
35+
char const* filename;
36+
vectd vect;
37+
std::vector<tinyobj::index_t> indices;
38+
std::vector<unsigned char> face_verts;
3039

31-
static PyObject*
32-
pyLoadObj(PyObject* self, PyObject* args)
33-
{
34-
PyObject *rtndict, *pyshapes, *pymaterials,
35-
*current, *meshobj;
40+
tinyobj::attrib_t attrib;
41+
std::vector<tinyobj::shape_t> shapes;
42+
std::vector<tinyobj::material_t> materials;
3643

37-
char const* filename;
38-
char *current_name;
39-
vectd vect;
44+
if (!PyArg_ParseTuple(args, "s", &filename)) return NULL;
4045

41-
std::vector<tinyobj::shape_t> shapes;
42-
std::vector<tinyobj::material_t> materials;
46+
std::string err;
47+
tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename);
4348

44-
if(!PyArg_ParseTuple(args, "s", &filename))
45-
return NULL;
49+
pyshapes = PyDict_New();
50+
pymaterials = PyDict_New();
51+
rtndict = PyDict_New();
4652

47-
std::string err;
48-
tinyobj::LoadObj(shapes, materials, err, filename);
53+
attribobj = PyDict_New();
4954

50-
pyshapes = PyDict_New();
51-
pymaterials = PyDict_New();
52-
rtndict = PyDict_New();
55+
for (int i = 0; i <= 2; i++) {
56+
current = PyList_New(0);
57+
58+
switch (i) {
59+
case 0:
60+
current_name = "vertices";
61+
vect = vectd(attrib.vertices.begin(), attrib.vertices.end());
62+
break;
63+
case 1:
64+
current_name = "normals";
65+
vect = vectd(attrib.normals.begin(), attrib.normals.end());
66+
break;
67+
case 2:
68+
current_name = "texcoords";
69+
vect = vectd(attrib.texcoords.begin(), attrib.texcoords.end());
70+
break;
71+
}
72+
73+
for (vectd::iterator it = vect.begin(); it != vect.end(); it++) {
74+
PyList_Insert(current, it - vect.begin(), PyFloat_FromDouble(*it));
75+
}
76+
77+
PyDict_SetItemString(attribobj, current_name, current);
78+
}
79+
80+
for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin();
81+
shape != shapes.end(); shape++) {
82+
meshobj = PyDict_New();
83+
tinyobj::mesh_t cm = (*shape).mesh;
5384

54-
for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin() ;
55-
shape != shapes.end(); shape++)
5685
{
57-
meshobj = PyDict_New();
58-
tinyobj::mesh_t cm = (*shape).mesh;
59-
60-
for (int i = 0; i <= 4; i++ )
61-
{
62-
current = PyList_New(0);
63-
64-
switch(i) {
65-
66-
case 0:
67-
current_name = "positions";
68-
vect = vectd(cm.positions.begin(), cm.positions.end()); break;
69-
case 1:
70-
current_name = "normals";
71-
vect = vectd(cm.normals.begin(), cm.normals.end()); break;
72-
case 2:
73-
current_name = "texcoords";
74-
vect = vectd(cm.texcoords.begin(), cm.texcoords.end()); break;
75-
case 3:
76-
current_name = "indicies";
77-
vect = vectd(cm.indices.begin(), cm.indices.end()); break;
78-
case 4:
79-
current_name = "material_ids";
80-
vect = vectd(cm.material_ids.begin(), cm.material_ids.end()); break;
81-
82-
}
83-
84-
for (vectd::iterator it = vect.begin() ;
85-
it != vect.end(); it++)
86-
{
87-
PyList_Insert(current, it - vect.begin(), PyFloat_FromDouble(*it));
88-
}
89-
90-
PyDict_SetItemString(meshobj, current_name, current);
91-
92-
}
93-
94-
PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj);
86+
current = PyList_New(0);
87+
88+
for (size_t i = 0; i < cm.indices.size(); i++) {
89+
// Flatten index array: v_idx, vn_idx, vt_idx, v_idx, vn_idx, vt_idx,
90+
// ...
91+
PyList_Insert(current, 3 * i + 0,
92+
PyLong_FromLong(cm.indices[i].vertex_index));
93+
PyList_Insert(current, 3 * i + 1,
94+
PyLong_FromLong(cm.indices[i].normal_index));
95+
PyList_Insert(current, 3 * i + 2,
96+
PyLong_FromLong(cm.indices[i].texcoord_index));
97+
}
98+
99+
PyDict_SetItemString(meshobj, "indices", current);
95100
}
96101

97-
for (std::vector<tinyobj::material_t>::iterator mat = materials.begin() ;
98-
mat != materials.end(); mat++)
99102
{
100-
PyObject *matobj = PyDict_New();
101-
PyObject *unknown_parameter = PyDict_New();
102-
103-
for (std::map<std::string, std::string>::iterator p = (*mat).unknown_parameter.begin() ;
104-
p != (*mat).unknown_parameter.end(); ++p)
105-
{
106-
PyDict_SetItemString(unknown_parameter, p->first.c_str(), PyUnicode_FromString(p->second.c_str()));
107-
}
108-
109-
PyDict_SetItemString(matobj, "shininess", PyFloat_FromDouble((*mat).shininess));
110-
PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble((*mat).ior));
111-
PyDict_SetItemString(matobj, "dissolve", PyFloat_FromDouble((*mat).dissolve));
112-
PyDict_SetItemString(matobj, "illum", PyLong_FromLong((*mat).illum));
113-
PyDict_SetItemString(matobj, "ambient_texname", PyUnicode_FromString((*mat).ambient_texname.c_str()));
114-
PyDict_SetItemString(matobj, "diffuse_texname", PyUnicode_FromString((*mat).diffuse_texname.c_str()));
115-
PyDict_SetItemString(matobj, "specular_texname", PyUnicode_FromString((*mat).specular_texname.c_str()));
116-
PyDict_SetItemString(matobj, "specular_highlight_texname", PyUnicode_FromString((*mat).specular_highlight_texname.c_str()));
117-
PyDict_SetItemString(matobj, "bump_texname", PyUnicode_FromString((*mat).bump_texname.c_str()));
118-
PyDict_SetItemString(matobj, "displacement_texname", PyUnicode_FromString((*mat).displacement_texname.c_str()));
119-
PyDict_SetItemString(matobj, "alpha_texname", PyUnicode_FromString((*mat).alpha_texname.c_str()));
120-
PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3((*mat).ambient));
121-
PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3((*mat).diffuse));
122-
PyDict_SetItemString(matobj, "specular", pyTupleFromfloat3((*mat).specular));
123-
PyDict_SetItemString(matobj, "transmittance", pyTupleFromfloat3((*mat).transmittance));
124-
PyDict_SetItemString(matobj, "emission", pyTupleFromfloat3((*mat).emission));
125-
PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter);
126-
127-
PyDict_SetItemString(pymaterials, (*mat).name.c_str(), matobj);
103+
current = PyList_New(0);
104+
105+
for (size_t i = 0; i < cm.num_face_vertices.size(); i++) {
106+
// Widen data type to long.
107+
PyList_Insert(current, i, PyLong_FromLong(cm.num_face_vertices[i]));
108+
}
109+
110+
PyDict_SetItemString(meshobj, "num_face_vertices", current);
128111
}
129112

130-
PyDict_SetItemString(rtndict, "shapes", pyshapes);
131-
PyDict_SetItemString(rtndict, "materials", pymaterials);
113+
{
114+
current = PyList_New(0);
132115

133-
return rtndict;
134-
}
116+
for (size_t i = 0; i < cm.material_ids.size(); i++) {
117+
PyList_Insert(current, i, PyLong_FromLong(cm.material_ids[i]));
118+
}
135119

120+
PyDict_SetItemString(meshobj, "material_ids", current);
121+
}
136122

137-
static PyMethodDef mMethods[] = {
123+
PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj);
124+
}
138125

139-
{"LoadObj", pyLoadObj, METH_VARARGS},
140-
{NULL, NULL, 0, NULL}
126+
for (std::vector<tinyobj::material_t>::iterator mat = materials.begin();
127+
mat != materials.end(); mat++) {
128+
PyObject* matobj = PyDict_New();
129+
PyObject* unknown_parameter = PyDict_New();
141130

142-
};
131+
for (std::map<std::string, std::string>::iterator p =
132+
(*mat).unknown_parameter.begin();
133+
p != (*mat).unknown_parameter.end(); ++p) {
134+
PyDict_SetItemString(unknown_parameter, p->first.c_str(),
135+
PyUnicode_FromString(p->second.c_str()));
136+
}
143137

138+
PyDict_SetItemString(matobj, "shininess",
139+
PyFloat_FromDouble((*mat).shininess));
140+
PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble((*mat).ior));
141+
PyDict_SetItemString(matobj, "dissolve",
142+
PyFloat_FromDouble((*mat).dissolve));
143+
PyDict_SetItemString(matobj, "illum", PyLong_FromLong((*mat).illum));
144+
PyDict_SetItemString(matobj, "ambient_texname",
145+
PyUnicode_FromString((*mat).ambient_texname.c_str()));
146+
PyDict_SetItemString(matobj, "diffuse_texname",
147+
PyUnicode_FromString((*mat).diffuse_texname.c_str()));
148+
PyDict_SetItemString(matobj, "specular_texname",
149+
PyUnicode_FromString((*mat).specular_texname.c_str()));
150+
PyDict_SetItemString(
151+
matobj, "specular_highlight_texname",
152+
PyUnicode_FromString((*mat).specular_highlight_texname.c_str()));
153+
PyDict_SetItemString(matobj, "bump_texname",
154+
PyUnicode_FromString((*mat).bump_texname.c_str()));
155+
PyDict_SetItemString(
156+
matobj, "displacement_texname",
157+
PyUnicode_FromString((*mat).displacement_texname.c_str()));
158+
PyDict_SetItemString(matobj, "alpha_texname",
159+
PyUnicode_FromString((*mat).alpha_texname.c_str()));
160+
PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3((*mat).ambient));
161+
PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3((*mat).diffuse));
162+
PyDict_SetItemString(matobj, "specular",
163+
pyTupleFromfloat3((*mat).specular));
164+
PyDict_SetItemString(matobj, "transmittance",
165+
pyTupleFromfloat3((*mat).transmittance));
166+
PyDict_SetItemString(matobj, "emission",
167+
pyTupleFromfloat3((*mat).emission));
168+
PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter);
169+
170+
PyDict_SetItemString(pymaterials, (*mat).name.c_str(), matobj);
171+
}
172+
173+
PyDict_SetItemString(rtndict, "shapes", pyshapes);
174+
PyDict_SetItemString(rtndict, "materials", pymaterials);
175+
176+
return rtndict;
177+
}
178+
179+
static PyMethodDef mMethods[] = {
180+
181+
{"LoadObj", pyLoadObj, METH_VARARGS}, {NULL, NULL, 0, NULL}
144182

145-
static struct PyModuleDef moduledef = {
146-
PyModuleDef_HEAD_INIT,
147-
"tinyobjloader",
148-
NULL,
149-
-1,
150-
mMethods
151183
};
152184

185+
static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader",
186+
NULL, -1, mMethods};
153187

154-
PyMODINIT_FUNC
155-
PyInit_tinyobjloader(void)
156-
{
157-
return PyModule_Create(&moduledef);
188+
PyMODINIT_FUNC PyInit_tinyobjloader(void) {
189+
return PyModule_Create(&moduledef);
158190
}
159-
160191
}

0 commit comments

Comments
 (0)