[cgkit-commits] cgkit2/wrappers/rply py_rply_read.cpp,NONE,1.1
Brought to you by:
mbaas
From: Matthias B. <mb...@us...> - 2005-05-02 16:49:43
|
Update of /cvsroot/cgkit/cgkit2/wrappers/rply In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11011/wrappers/rply Added Files: py_rply_read.cpp Log Message: Initial version of the PLY import (not finished yet. User variables aren't imported yet) --- NEW FILE: py_rply_read.cpp --- /*====================================================================== cgkit - Python Computer Graphics Kit Copyright (C) 2004 Matthias Baas (ba...@ir...) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA cgkit homepage: http://cgkit.sourceforge.net ======================================================================*/ #include <boost/python.hpp> #include <iostream> #include <exception> #include <string> #include <vector> #include "polyhedrongeom.h" #include "arrayslot.h" #include "vec3.h" #include "rply/rply.h" using namespace boost::python; ////////////////////////////////////////////////////////////////////// /// Info about a int slot class PlyVarIntInfo { public: /// The slot that should receive the values support3d::ArraySlot<int>* slot; /// The current index long idx; /// The data block int* data; PlyVarIntInfo(support3d::ArraySlot<int>* s) : slot(s), idx(0) { data = s->dataPtr(); } }; /// Info about a vec3 slot class PlyVarVec3Info { public: /// The slot that should receive the values support3d::ArraySlot<support3d::vec3d>* slot; /// The current index long idx; /// The data block support3d::vec3d* data; PlyVarVec3Info(support3d::ArraySlot<support3d::vec3d>* s) : slot(s), idx(0) { data = s->dataPtr(); } }; /// Info about a list variable class PlyVarListInfo { public: /// Callback function that is called when the list is complete int (*callback)(PlyVarListInfo& vi); /// The geom object support3d::PolyhedronGeom& geom; /// The current list std::vector<double> elements; /// The current index long idx; PlyVarListInfo(support3d::PolyhedronGeom& ageom, int (*acallback)(PlyVarListInfo&)) : geom(ageom), callback(acallback), elements(), idx(0) {} }; // Callbacks /// Set the x component of a vec3 slot. int var_vec3_x(p_ply_argument arg) { PlyVarVec3Info* vi; ply_get_argument_user_data(arg, (void**)(&vi), 0); vi->data[vi->idx].x = ply_get_argument_value(arg); vi->idx++; return 1; } /// Set the y component of a vec3 slot. int var_vec3_y(p_ply_argument arg) { PlyVarVec3Info* vi; ply_get_argument_user_data(arg, (void**)(&vi), 0); vi->data[vi->idx].y = ply_get_argument_value(arg); vi->idx++; return 1; } /// Set the z component of a vec3 slot. int var_vec3_z(p_ply_argument arg) { PlyVarVec3Info* vi; ply_get_argument_user_data(arg, (void**)(&vi), 0); vi->data[vi->idx].z = ply_get_argument_value(arg); vi->idx++; return 1; } int var_list(p_ply_argument arg) { PlyVarListInfo* vi; ply_get_argument_user_data(arg, (void**)(&vi), 0); long len, val_index; ply_get_argument_property(arg, 0, &len, &val_index); // Is the current value the list length? Then initialize the var info if (val_index<0) { vi->elements.clear(); } else { vi->elements.push_back(ply_get_argument_value(arg)); // Is the list complete? if (val_index+1>=len) { int res = vi->callback(*vi); vi->idx++; return res; } } return 1; } int var_vert_ids(PlyVarListInfo& vi) { std::vector<int> loop; // Convert the list to ints... for(unsigned int i=0; i<vi.elements.size(); i++) { // +0.1 to make sure the conversion to int will be the true int... loop.push_back(int(vi.elements[i]+0.1)); } vi.geom.setLoop(vi.idx, 0, loop); return 1; } ////////////////////////////////////////////////////////////////////// /** This class describes a user defined variable. */ class VariableInfo { public: /// Variable name (=slot name) std::string varname; /// Variable type support3d::VarType vartype; /// Element name std::string element; /// Number of properties (1 or 3) int numprops; /// Property 1 name std::string prop1name; /// Property 2 name std::string prop2name; /// Property 3 name std::string prop3name; /// The number of variable values long ninstances; /// The property type e_ply_type proptype; e_ply_type len_type; e_ply_type val_type; bool valid; VariableInfo() : varname(), vartype(support3d::INT), element(), numprops(0), prop1name(), prop2name(), prop3name(), ninstances(0), proptype(PLY_INT), len_type(PLY_INT), val_type(PLY_INT), valid(false) {} /// Return the storage class for the corresponding slot support3d::VarStorage storageClass() { if (element=="vertex") return support3d::VARYING; if (element=="face") return support3d::UNIFORM; return support3d::USER; } }; ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// /** PLYReader */ class PLYReader { private: /// PLY file handle. p_ply handle; /// Stores the number of vertices... long numverts; /// Stores the number of faces... long numfaces; public: PLYReader() : handle(0), numverts(0), numfaces(0) {} ~PLYReader() { close(); } /** Open a PLY file. */ void open(std::string name) { close(); // Open the file handle = ply_open(name.c_str(), 0); if (handle==0) { // ...exception... } } /** Close the file (if it is open). */ void close() { if (handle!=0) { ply_close(handle); handle = 0; numverts = 0; numfaces = 0; } } /** Read the file header. The return value is a tuple (elements, comment, objinfo). comment and objinfo is a string that is a concatenation of all individual comment/objinfo lines in the file. elements is a list of the elements specified in the header. Each element is described by a 3-tuple (name, ninstances, properties). name is the element's name (such as "vertex" and "face"), ninstances specifies how many items are stored in the file and properties is a list of element properties. Each property is again stored as a tuple (name, type, len_type, val_type) where name is the name of the property, type its type and len_type/val_type is the type of the length and the value of list properties. Each type is given as a string. This method also initializes the class attributes numverts and numfaces. */ object readHeader() { // Read the header... if (!ply_read_header(handle)) { return object(); } // Iterate over the elements... p_ply_element el = ply_get_next_element(handle, 0); list elements; while(el!=0) { const char* elname; long ninstances; ply_get_element_info(el, &elname, &ninstances); if (strcmp(elname, "vertex")==0) numverts = ninstances; else if (strcmp(elname, "face")==0) numfaces = ninstances; // Iterate over the properties of the element... p_ply_property prop = ply_get_next_property(el, 0); list props; while(prop!=0) { const char* propname; e_ply_type proptype, len_type, val_type; ply_get_property_info(prop, &propname, &proptype, &len_type, &val_type); props.append(make_tuple(std::string(propname), plyTypeToString(proptype), plyTypeToString(len_type), plyTypeToString(val_type))); prop = ply_get_next_property(el, prop); } elements.append(make_tuple(std::string(elname), ninstances, props)); el = ply_get_next_element(handle, el); } // Iterate over the comments const char* s = ply_get_next_comment(handle, 0); list comments; while(s!=0) { comments.append(boost::python::str(s)); s = ply_get_next_comment(handle, s); } // Iterate over the objinfos s = ply_get_next_obj_info(handle, 0); list objinfos; while(s!=0) { objinfos.append(boost::python::str(s)); s = ply_get_next_obj_info(handle, s); } return make_tuple(elements, boost::python::str("\n").join(comments), boost::python::str("\n").join(objinfos)); } /** Read the data. This may only be called after readHeader() was called. slotcreator is a callable that returns a new slot. vardecl is a list of variable declarations. */ void read(support3d::PolyhedronGeom& geom, object slotcreator, object vardecl) { std::vector<PlyVarIntInfo*> intvars; // Create polyhedron geom (via Python callback)... /* object pygeom = geomcreator(); extract<PolyhedronGeom&> xpg(pygeom); if (!xpg.check()) { std::cerr<<"Warning: No geom available. Aborting PLY import."<<std::endl; return; } PolyhedronGeom& polygeom = xpg();*/ geom.verts.resize(numverts); geom.setNumPolys(numfaces); for (int i=0; i<vardecl.attr("__len__")(); i++) { // Declaration tuple (slotname, vartype, elementname, (propnames)) object decl = vardecl[i]; VariableInfo vi = createVarInfo(decl); // std::cout<<"VAR: "<<vi.varname<<std::endl; // std::cout<<" valid: "<<vi.valid<<std::endl; // std::cout<<" ninst: "<<vi.ninstances<<std::endl; if (!vi.valid) continue; if (vi.numprops==1 && vi.proptype!=PLY_LIST) { slotcreator(vi.varname, vi.storageClass(), vi.vartype, 1, vi.ninstances); } // numprops==1 / type!=list -> Prop direkt übernehmen (int/float) // numprops==1 / type==list -> Prop als Liste (Slot später erstellen) // numprops==3 -> Prop als Vec3 } PlyVarVec3Info vertinfox(&geom.verts); PlyVarVec3Info vertinfoy(&geom.verts); PlyVarVec3Info vertinfoz(&geom.verts); ply_set_read_cb(handle, "vertex", "x", var_vec3_x, &vertinfox, 0); ply_set_read_cb(handle, "vertex", "y", var_vec3_y, &vertinfoy, 0); ply_set_read_cb(handle, "vertex", "z", var_vec3_z, &vertinfoz, 0); PlyVarListInfo facesinfo(geom, var_vert_ids); ply_set_read_cb(handle, "face", "vertex_indices", var_list, &facesinfo, 0); ply_read(handle); } ////////////////////////////////////////////////////////////////////// private: /** Create a VariableInfo object from a Python declaration tuple. */ VariableInfo createVarInfo(object decl) { VariableInfo res; // Item 0: Slot name res.varname = extract<std::string>(decl[0]); // Item 1: Variable type res.vartype = extract<support3d::VarType>(decl[1]); // Item 2: Element name res.element = extract<std::string>(decl[2]); // Item 3: propnames (either 1 or 3 strings) res.numprops = extract<int>(decl[3].attr("__len__")()); switch(res.numprops) { case 1: { res.prop1name = extract<std::string>(decl[3][0]); res.valid = searchProperty(res.element.c_str(), res.prop1name.c_str(), &res.ninstances, &res.proptype, &res.len_type, &res.val_type); break; } case 3: { res.prop1name = extract<std::string>(decl[3][0]); res.prop2name = extract<std::string>(decl[3][1]); res.prop2name = extract<std::string>(decl[3][2]); // Get the number of values (from one of the 3 properties) // If none of the properties is available, mark the result as invalid res.valid = searchProperty(res.element.c_str(), res.prop1name.c_str(), &res.ninstances, &res.proptype, &res.len_type, &res.val_type); if (res.valid) break; res.valid = searchProperty(res.element.c_str(), res.prop2name.c_str(), &res.ninstances, 0,0,0); if (res.valid) break; res.valid = searchProperty(res.element.c_str(), res.prop3name.c_str(), &res.ninstances, 0,0,0); break; } default: /* res remains invalid */ break; } return res; } /** Search a property and return info about it. len_type and val_type are only meaningful if proptype is PLY_LIST. \param element The element name \param property The property name inside the element \param[out] ninstances Receives the number of values (may be NULL) \param[out] proptype Receives the type of the property (may be NULL) \param[out] len_type Receives the type of the list length (may be NULL) \param[out] val_type Receives the type of a list item (may be NULL) */ bool searchProperty(const char* element, const char* property, long* ninstances, e_ply_type* proptype, e_ply_type* len_type, e_ply_type* val_type) { // Iterate over the elements... p_ply_element el = ply_get_next_element(handle, 0); while(el!=0) { const char* elname; ply_get_element_info(el, &elname, ninstances); if (strcmp(elname, element)==0) break; el = ply_get_next_element(handle, el); } if (el==0) return false; // Iterate over the properties of the element... p_ply_property prop = ply_get_next_property(el, 0); while(prop!=0) { const char* propname; ply_get_property_info(prop, &propname, proptype, len_type, val_type); if (strcmp(propname, property)==0) return true; prop = ply_get_next_property(el, prop); } return false; } /** Convert a PLY type specification into a string. */ std::string plyTypeToString(e_ply_type t) { switch(t) { case PLY_INT8: return "int8"; case PLY_UINT8: return "uint8"; case PLY_INT16: return "int16"; case PLY_UINT16: return "uint16"; case PLY_INT32: return "int32"; case PLY_UIN32: return "uint32"; case PLY_FLOAT32: return "float32"; case PLY_FLOAT64: return "float64"; case PLY_CHAR: return "char"; case PLY_UCHAR: return "uchar"; case PLY_SHORT: return "short"; case PLY_USHORT: return "ushort"; case PLY_INT: return "int"; case PLY_UINT: return "uint"; case PLY_FLOAT: return "float"; case PLY_DOUBLE: return "double"; case PLY_LIST: return "list"; default: return "?"; } } }; ////////////////////////////////////////////////////////////////////// void rply() { class_<PLYReader>("PLYReader", init<>()) .def("open", &PLYReader::open) .def("close", &PLYReader::close) .def("readHeader", &PLYReader::readHeader) .def("read", &PLYReader::read) ; } |