|
1 |
| -// python2/3 module for tinyobjloader |
2 |
| -// |
3 |
| -// usage: |
4 |
| -// import tinyobjloader as tol |
5 |
| -// model = tol.LoadObj(name) |
6 |
| -// print(model["shapes"]) |
7 |
| -// print(model["materials"] |
8 |
| -// note: |
9 |
| -// `shape.mesh.index_t` is represented as flattened array: (vertex_index, normal_index, texcoord_index) * num_faces |
10 |
| - |
11 |
| -#include <Python.h> |
12 |
| -#include <vector> |
13 |
| -#include "../tiny_obj_loader.h" |
14 |
| - |
15 |
| -typedef std::vector<double> vectd; |
16 |
| -typedef std::vector<int> vecti; |
17 |
| - |
18 |
| -PyObject* pyTupleFromfloat3(float array[3]) { |
19 |
| - int i; |
20 |
| - PyObject* tuple = PyTuple_New(3); |
21 |
| - |
22 |
| - for (i = 0; i <= 2; i++) { |
23 |
| - PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i])); |
24 |
| - } |
25 |
| - |
26 |
| - return tuple; |
| 1 | +#include <pybind11\pybind11.h> |
| 2 | +#include <pybind11\stl.h> |
| 3 | + |
| 4 | +#define TINYOBJLOADER_IMPLEMENTATION |
| 5 | +#include <tiny_obj_loader.h> |
| 6 | + |
| 7 | + |
| 8 | +namespace py = pybind11; |
| 9 | + |
| 10 | + |
| 11 | +py::tuple loadModel(std::string modelfile) { |
| 12 | + tinyobj::attrib_t attrib; |
| 13 | + std::vector<tinyobj::shape_t> shapes; |
| 14 | + std::vector<tinyobj::material_t> materials; |
| 15 | + std::string err; |
| 16 | + |
| 17 | + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, modelfile.c_str())) { |
| 18 | + std::exception(err); |
| 19 | + } |
| 20 | + |
| 21 | + py::dict uniqueVertices; |
| 22 | + py::list vertices; |
| 23 | + py::list indices; |
| 24 | + |
| 25 | + for (const auto& shape : shapes) { |
| 26 | + for (const auto& index : shape.mesh.indices) { |
| 27 | + py::tuple vertex = py::make_tuple( |
| 28 | + // vertex position |
| 29 | + attrib.vertices[3 * index.vertex_index + 0], |
| 30 | + attrib.vertices[3 * index.vertex_index + 1], |
| 31 | + attrib.vertices[3 * index.vertex_index + 2], |
| 32 | + // color |
| 33 | + 1.0, 1.0, 1.0, |
| 34 | + // texcoord |
| 35 | + attrib.texcoords[2 * index.texcoord_index + 0], |
| 36 | + 1.0f - attrib.texcoords[2 * index.texcoord_index + 1] |
| 37 | + ); |
| 38 | + |
| 39 | + if (!uniqueVertices.contains(vertex)) { |
| 40 | + uniqueVertices[vertex] = static_cast<uint32_t>(vertices.size()); |
| 41 | + vertices.append(vertex); |
| 42 | + } |
| 43 | + |
| 44 | + indices.append(uniqueVertices[vertex]); |
| 45 | + } |
| 46 | + } |
| 47 | + |
| 48 | + return py::make_tuple(vertices, indices); |
27 | 49 | }
|
28 | 50 |
|
29 |
| -extern "C" { |
30 |
| - |
31 |
| -static PyObject* pyLoadObj(PyObject* self, PyObject* args) { |
32 |
| - PyObject *rtndict, *pyshapes, *pymaterials, *pymaterial_indices, *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; |
39 |
| - |
40 |
| - tinyobj::attrib_t attrib; |
41 |
| - std::vector<tinyobj::shape_t> shapes; |
42 |
| - std::vector<tinyobj::material_t> materials; |
43 |
| - |
44 |
| - if (!PyArg_ParseTuple(args, "s", &filename)) return NULL; |
45 |
| - |
46 |
| - std::string err; |
47 |
| - tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename); |
48 |
| - |
49 |
| - pyshapes = PyDict_New(); |
50 |
| - pymaterials = PyDict_New(); |
51 |
| - pymaterial_indices = PyList_New(0); |
52 |
| - rtndict = PyDict_New(); |
53 |
| - |
54 |
| - attribobj = PyDict_New(); |
55 |
| - |
56 |
| - for (int i = 0; i <= 2; i++) { |
57 |
| - current = PyList_New(0); |
58 |
| - |
59 |
| - switch (i) { |
60 |
| - case 0: |
61 |
| - current_name = "vertices"; |
62 |
| - vect = vectd(attrib.vertices.begin(), attrib.vertices.end()); |
63 |
| - break; |
64 |
| - case 1: |
65 |
| - current_name = "normals"; |
66 |
| - vect = vectd(attrib.normals.begin(), attrib.normals.end()); |
67 |
| - break; |
68 |
| - case 2: |
69 |
| - current_name = "texcoords"; |
70 |
| - vect = vectd(attrib.texcoords.begin(), attrib.texcoords.end()); |
71 |
| - break; |
72 |
| - } |
73 |
| - |
74 |
| - for (vectd::iterator it = vect.begin(); it != vect.end(); it++) { |
75 |
| - PyList_Insert(current, it - vect.begin(), PyFloat_FromDouble(*it)); |
76 |
| - } |
77 |
| - |
78 |
| - PyDict_SetItemString(attribobj, current_name, current); |
79 |
| - } |
80 |
| - |
81 |
| - for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin(); |
82 |
| - shape != shapes.end(); shape++) { |
83 |
| - meshobj = PyDict_New(); |
84 |
| - tinyobj::mesh_t cm = (*shape).mesh; |
85 |
| - |
86 |
| - { |
87 |
| - current = PyList_New(0); |
88 |
| - |
89 |
| - for (size_t i = 0; i < cm.indices.size(); i++) { |
90 |
| - // Flatten index array: v_idx, vn_idx, vt_idx, v_idx, vn_idx, vt_idx, |
91 |
| - // ... |
92 |
| - PyList_Insert(current, 3 * i + 0, |
93 |
| - PyLong_FromLong(cm.indices[i].vertex_index)); |
94 |
| - PyList_Insert(current, 3 * i + 1, |
95 |
| - PyLong_FromLong(cm.indices[i].normal_index)); |
96 |
| - PyList_Insert(current, 3 * i + 2, |
97 |
| - PyLong_FromLong(cm.indices[i].texcoord_index)); |
98 |
| - } |
99 |
| - |
100 |
| - PyDict_SetItemString(meshobj, "indices", current); |
101 |
| - } |
102 |
| - |
103 |
| - { |
104 |
| - current = PyList_New(0); |
105 |
| - |
106 |
| - for (size_t i = 0; i < cm.num_face_vertices.size(); i++) { |
107 |
| - // Widen data type to long. |
108 |
| - PyList_Insert(current, i, PyLong_FromLong(cm.num_face_vertices[i])); |
109 |
| - } |
110 |
| - |
111 |
| - PyDict_SetItemString(meshobj, "num_face_vertices", current); |
112 |
| - } |
113 |
| - |
114 |
| - { |
115 |
| - current = PyList_New(0); |
116 |
| - |
117 |
| - for (size_t i = 0; i < cm.material_ids.size(); i++) { |
118 |
| - PyList_Insert(current, i, PyLong_FromLong(cm.material_ids[i])); |
119 |
| - } |
120 |
| - |
121 |
| - PyDict_SetItemString(meshobj, "material_ids", current); |
122 |
| - } |
123 |
| - |
124 |
| - PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj); |
125 |
| - } |
126 |
| - |
127 |
| - for (std::vector<tinyobj::material_t>::iterator mat = materials.begin(); |
128 |
| - mat != materials.end(); mat++) { |
129 |
| - PyObject* matobj = PyDict_New(); |
130 |
| - PyObject* unknown_parameter = PyDict_New(); |
131 |
| - |
132 |
| - for (std::map<std::string, std::string>::iterator p = |
133 |
| - mat->unknown_parameter.begin(); |
134 |
| - p != mat->unknown_parameter.end(); ++p) { |
135 |
| - PyDict_SetItemString(unknown_parameter, p->first.c_str(), |
136 |
| - PyUnicode_FromString(p->second.c_str())); |
137 |
| - } |
138 |
| - |
139 |
| - PyDict_SetItemString(matobj, "shininess", |
140 |
| - PyFloat_FromDouble(mat->shininess)); |
141 |
| - PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble(mat->ior)); |
142 |
| - PyDict_SetItemString(matobj, "dissolve", |
143 |
| - PyFloat_FromDouble(mat->dissolve)); |
144 |
| - PyDict_SetItemString(matobj, "illum", PyLong_FromLong(mat->illum)); |
145 |
| - PyDict_SetItemString(matobj, "ambient_texname", |
146 |
| - PyUnicode_FromString(mat->ambient_texname.c_str())); |
147 |
| - PyDict_SetItemString(matobj, "diffuse_texname", |
148 |
| - PyUnicode_FromString(mat->diffuse_texname.c_str())); |
149 |
| - PyDict_SetItemString(matobj, "specular_texname", |
150 |
| - PyUnicode_FromString(mat->specular_texname.c_str())); |
151 |
| - PyDict_SetItemString( |
152 |
| - matobj, "specular_highlight_texname", |
153 |
| - PyUnicode_FromString(mat->specular_highlight_texname.c_str())); |
154 |
| - PyDict_SetItemString(matobj, "bump_texname", |
155 |
| - PyUnicode_FromString(mat->bump_texname.c_str())); |
156 |
| - PyDict_SetItemString( |
157 |
| - matobj, "displacement_texname", |
158 |
| - PyUnicode_FromString(mat->displacement_texname.c_str())); |
159 |
| - PyDict_SetItemString(matobj, "alpha_texname", |
160 |
| - PyUnicode_FromString(mat->alpha_texname.c_str())); |
161 |
| - PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3(mat->ambient)); |
162 |
| - PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3(mat->diffuse)); |
163 |
| - PyDict_SetItemString(matobj, "specular", |
164 |
| - pyTupleFromfloat3(mat->specular)); |
165 |
| - PyDict_SetItemString(matobj, "transmittance", |
166 |
| - pyTupleFromfloat3(mat->transmittance)); |
167 |
| - PyDict_SetItemString(matobj, "emission", |
168 |
| - pyTupleFromfloat3(mat->emission)); |
169 |
| - PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter); |
170 |
| - |
171 |
| - PyDict_SetItemString(pymaterials, mat->name.c_str(), matobj); |
172 |
| - PyList_Append(pymaterial_indices, PyUnicode_FromString(mat->name.c_str())); |
173 |
| - } |
174 |
| - |
175 |
| - PyDict_SetItemString(rtndict, "shapes", pyshapes); |
176 |
| - PyDict_SetItemString(rtndict, "materials", pymaterials); |
177 |
| - PyDict_SetItemString(rtndict, "material_indices", pymaterial_indices); |
178 |
| - PyDict_SetItemString(rtndict, "attribs", attribobj); |
179 |
| - |
180 |
| - return rtndict; |
181 |
| -} |
182 |
| - |
183 |
| -static PyMethodDef mMethods[] = { |
184 | 51 |
|
185 |
| - {"LoadObj", pyLoadObj, METH_VARARGS}, {NULL, NULL, 0, NULL} |
186 | 52 |
|
187 |
| -}; |
188 | 53 |
|
189 |
| -#if PY_MAJOR_VERSION >= 3 |
| 54 | +PYBIND11_MODULE(tol, m) { |
| 55 | + m.doc() = "tinyobjloader for python(for vulkan tutorial model loading demo)"; |
190 | 56 |
|
191 |
| -static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader", |
192 |
| - NULL, -1, mMethods}; |
193 |
| - |
194 |
| -PyMODINIT_FUNC PyInit_tinyobjloader(void) { |
195 |
| - return PyModule_Create(&moduledef); |
| 57 | + m.def("loadModel", &loadModel, "load an obj model."); |
196 | 58 | }
|
197 | 59 |
|
198 |
| -#else |
199 | 60 |
|
200 |
| -PyMODINIT_FUNC inittinyobjloader(void) { |
201 |
| - Py_InitModule3("tinyobjloader", mMethods, NULL); |
202 |
| -} |
203 |
| - |
204 |
| -#endif // PY_MAJOR_VERSION >= 3 |
205 |
| - |
206 |
| -} |
0 commit comments