diff --git a/python/TODO.md b/python/TODO.md new file mode 100644 index 0000000..d7aff07 --- /dev/null +++ b/python/TODO.md @@ -0,0 +1,3 @@ +* PBR material +* Define index_t struct +* Python 2.7 binding diff --git a/python/main.cpp b/python/main.cpp index f772793..6c794fa 100644 --- a/python/main.cpp +++ b/python/main.cpp @@ -1,160 +1,191 @@ -//python3 module for tinyobjloader +// python3 module for tinyobjloader // -//usage: +// usage: // import tinyobjloader as tol // model = tol.LoadObj(name) // print(model["shapes"]) // print(model["materials"] +// note: +// `shape.mesh.index_t` is represented as flattened array: (vertex_index, normal_index, texcoord_index) * num_faces #include #include #include "../tiny_obj_loader.h" typedef std::vector vectd; +typedef std::vector vecti; -PyObject* -pyTupleFromfloat3 (float array[3]) -{ - int i; - PyObject* tuple = PyTuple_New(3); +PyObject* pyTupleFromfloat3(float array[3]) { + int i; + PyObject* tuple = PyTuple_New(3); - for(i=0; i<=2 ; i++){ - PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i])); - } + for (i = 0; i <= 2; i++) { + PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i])); + } - return tuple; + return tuple; } -extern "C" -{ +extern "C" { -static PyObject* -pyLoadObj(PyObject* self, PyObject* args) -{ - PyObject *rtndict, *pyshapes, *pymaterials, - *current, *meshobj; +static PyObject* pyLoadObj(PyObject* self, PyObject* args) { + PyObject *rtndict, *pyshapes, *pymaterials, *attribobj, *current, *meshobj; - char const* filename; - char *current_name; - vectd vect; + char const* current_name; + char const* filename; + vectd vect; + std::vector indices; + std::vector face_verts; - std::vector shapes; - std::vector materials; + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; - if(!PyArg_ParseTuple(args, "s", &filename)) - return NULL; + if (!PyArg_ParseTuple(args, "s", &filename)) return NULL; - std::string err; - tinyobj::LoadObj(shapes, materials, err, filename); + std::string err; + tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename); - pyshapes = PyDict_New(); - pymaterials = PyDict_New(); - rtndict = PyDict_New(); + pyshapes = PyDict_New(); + pymaterials = PyDict_New(); + rtndict = PyDict_New(); - for (std::vector::iterator shape = shapes.begin() ; - shape != shapes.end(); shape++) - { - meshobj = PyDict_New(); - tinyobj::mesh_t cm = (*shape).mesh; + attribobj = PyDict_New(); - for (int i = 0; i <= 4; i++ ) - { - current = PyList_New(0); + for (int i = 0; i <= 2; i++) { + current = PyList_New(0); - switch(i) { - - case 0: - current_name = "positions"; - vect = vectd(cm.positions.begin(), cm.positions.end()); break; - case 1: - current_name = "normals"; - vect = vectd(cm.normals.begin(), cm.normals.end()); break; - case 2: - current_name = "texcoords"; - vect = vectd(cm.texcoords.begin(), cm.texcoords.end()); break; - case 3: - current_name = "indicies"; - vect = vectd(cm.indices.begin(), cm.indices.end()); break; - case 4: - current_name = "material_ids"; - vect = vectd(cm.material_ids.begin(), cm.material_ids.end()); break; - - } - - for (vectd::iterator it = vect.begin() ; - it != vect.end(); it++) - { - PyList_Insert(current, it - vect.begin(), PyFloat_FromDouble(*it)); - } - - PyDict_SetItemString(meshobj, current_name, current); - - } - - PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj); + switch (i) { + case 0: + current_name = "vertices"; + vect = vectd(attrib.vertices.begin(), attrib.vertices.end()); + break; + case 1: + current_name = "normals"; + vect = vectd(attrib.normals.begin(), attrib.normals.end()); + break; + case 2: + current_name = "texcoords"; + vect = vectd(attrib.texcoords.begin(), attrib.texcoords.end()); + break; } - for (std::vector::iterator mat = materials.begin() ; - mat != materials.end(); mat++) - { - PyObject *matobj = PyDict_New(); - PyObject *unknown_parameter = PyDict_New(); - - for (std::map::iterator p = (*mat).unknown_parameter.begin() ; - p != (*mat).unknown_parameter.end(); ++p) - { - PyDict_SetItemString(unknown_parameter, p->first.c_str(), PyUnicode_FromString(p->second.c_str())); - } - - PyDict_SetItemString(matobj, "shininess", PyFloat_FromDouble((*mat).shininess)); - PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble((*mat).ior)); - PyDict_SetItemString(matobj, "dissolve", PyFloat_FromDouble((*mat).dissolve)); - PyDict_SetItemString(matobj, "illum", PyLong_FromLong((*mat).illum)); - PyDict_SetItemString(matobj, "ambient_texname", PyUnicode_FromString((*mat).ambient_texname.c_str())); - PyDict_SetItemString(matobj, "diffuse_texname", PyUnicode_FromString((*mat).diffuse_texname.c_str())); - PyDict_SetItemString(matobj, "specular_texname", PyUnicode_FromString((*mat).specular_texname.c_str())); - PyDict_SetItemString(matobj, "specular_highlight_texname", PyUnicode_FromString((*mat).specular_highlight_texname.c_str())); - PyDict_SetItemString(matobj, "bump_texname", PyUnicode_FromString((*mat).bump_texname.c_str())); - PyDict_SetItemString(matobj, "displacement_texname", PyUnicode_FromString((*mat).displacement_texname.c_str())); - PyDict_SetItemString(matobj, "alpha_texname", PyUnicode_FromString((*mat).alpha_texname.c_str())); - PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3((*mat).ambient)); - PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3((*mat).diffuse)); - PyDict_SetItemString(matobj, "specular", pyTupleFromfloat3((*mat).specular)); - PyDict_SetItemString(matobj, "transmittance", pyTupleFromfloat3((*mat).transmittance)); - PyDict_SetItemString(matobj, "emission", pyTupleFromfloat3((*mat).emission)); - PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter); - - PyDict_SetItemString(pymaterials, (*mat).name.c_str(), matobj); + for (vectd::iterator it = vect.begin(); it != vect.end(); it++) { + PyList_Insert(current, it - vect.begin(), PyFloat_FromDouble(*it)); } - PyDict_SetItemString(rtndict, "shapes", pyshapes); - PyDict_SetItemString(rtndict, "materials", pymaterials); + PyDict_SetItemString(attribobj, current_name, current); + } - return rtndict; + for (std::vector::iterator shape = shapes.begin(); + shape != shapes.end(); shape++) { + meshobj = PyDict_New(); + tinyobj::mesh_t cm = (*shape).mesh; + + { + current = PyList_New(0); + + for (size_t i = 0; i < cm.indices.size(); i++) { + // Flatten index array: v_idx, vn_idx, vt_idx, v_idx, vn_idx, vt_idx, + // ... + PyList_Insert(current, 3 * i + 0, + PyLong_FromLong(cm.indices[i].vertex_index)); + PyList_Insert(current, 3 * i + 1, + PyLong_FromLong(cm.indices[i].normal_index)); + PyList_Insert(current, 3 * i + 2, + PyLong_FromLong(cm.indices[i].texcoord_index)); + } + + PyDict_SetItemString(meshobj, "indices", current); + } + + { + current = PyList_New(0); + + for (size_t i = 0; i < cm.num_face_vertices.size(); i++) { + // Widen data type to long. + PyList_Insert(current, i, PyLong_FromLong(cm.num_face_vertices[i])); + } + + PyDict_SetItemString(meshobj, "num_face_vertices", current); + } + + { + current = PyList_New(0); + + for (size_t i = 0; i < cm.material_ids.size(); i++) { + PyList_Insert(current, i, PyLong_FromLong(cm.material_ids[i])); + } + + PyDict_SetItemString(meshobj, "material_ids", current); + } + + PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj); + } + + for (std::vector::iterator mat = materials.begin(); + mat != materials.end(); mat++) { + PyObject* matobj = PyDict_New(); + PyObject* unknown_parameter = PyDict_New(); + + for (std::map::iterator p = + (*mat).unknown_parameter.begin(); + p != (*mat).unknown_parameter.end(); ++p) { + PyDict_SetItemString(unknown_parameter, p->first.c_str(), + PyUnicode_FromString(p->second.c_str())); + } + + PyDict_SetItemString(matobj, "shininess", + PyFloat_FromDouble((*mat).shininess)); + PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble((*mat).ior)); + PyDict_SetItemString(matobj, "dissolve", + PyFloat_FromDouble((*mat).dissolve)); + PyDict_SetItemString(matobj, "illum", PyLong_FromLong((*mat).illum)); + PyDict_SetItemString(matobj, "ambient_texname", + PyUnicode_FromString((*mat).ambient_texname.c_str())); + PyDict_SetItemString(matobj, "diffuse_texname", + PyUnicode_FromString((*mat).diffuse_texname.c_str())); + PyDict_SetItemString(matobj, "specular_texname", + PyUnicode_FromString((*mat).specular_texname.c_str())); + PyDict_SetItemString( + matobj, "specular_highlight_texname", + PyUnicode_FromString((*mat).specular_highlight_texname.c_str())); + PyDict_SetItemString(matobj, "bump_texname", + PyUnicode_FromString((*mat).bump_texname.c_str())); + PyDict_SetItemString( + matobj, "displacement_texname", + PyUnicode_FromString((*mat).displacement_texname.c_str())); + PyDict_SetItemString(matobj, "alpha_texname", + PyUnicode_FromString((*mat).alpha_texname.c_str())); + PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3((*mat).ambient)); + PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3((*mat).diffuse)); + PyDict_SetItemString(matobj, "specular", + pyTupleFromfloat3((*mat).specular)); + PyDict_SetItemString(matobj, "transmittance", + pyTupleFromfloat3((*mat).transmittance)); + PyDict_SetItemString(matobj, "emission", + pyTupleFromfloat3((*mat).emission)); + PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter); + + PyDict_SetItemString(pymaterials, (*mat).name.c_str(), matobj); + } + + PyDict_SetItemString(rtndict, "shapes", pyshapes); + PyDict_SetItemString(rtndict, "materials", pymaterials); + + return rtndict; } - static PyMethodDef mMethods[] = { -{"LoadObj", pyLoadObj, METH_VARARGS}, -{NULL, NULL, 0, NULL} + {"LoadObj", pyLoadObj, METH_VARARGS}, {NULL, NULL, 0, NULL} }; +static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader", + NULL, -1, mMethods}; -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "tinyobjloader", - NULL, - -1, - mMethods -}; - - -PyMODINIT_FUNC -PyInit_tinyobjloader(void) -{ - return PyModule_Create(&moduledef); +PyMODINIT_FUNC PyInit_tinyobjloader(void) { + return PyModule_Create(&moduledef); } - }