/**************************************************************************** * NanoPLY * * NanoPLY is a C++11 header-only library to read and write PLY file * * * * Copyright(C) 2014-2015 * * Visual Computing Lab * * ISTI - Italian National Research Council * * * * This Source Code Form is subject to the terms of the Mozilla Public * * License, v. 2.0. If a copy of the MPL was not distributed with this * * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * * ****************************************************************************/ #ifndef NANOPLY_WRAPPER_VCG_H #define NANOPLY_WRAPPER_VCG_H #include #include #include #include namespace nanoply { template class NanoPlyWrapper{ private: typedef typename MeshType::PointerToAttribute PointerToAttribute; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::VertexType VertexType; typedef typename MeshType::VertexType::ScalarType VertexCoordScalar; typedef typename MeshType::VertexType::NormalType VertexNormalType; typedef typename MeshType::VertexType::NormalType::ScalarType VertexNormScalar; typedef typename MeshType::VertexType::ColorType VertexColorType; typedef typename MeshType::VertexType::ColorType::ScalarType VertexColorScalar; typedef typename MeshType::VertexType::QualityType VertexQuality; typedef typename MeshType::VertexType::RadiusType VertexRadius; typedef typename MeshType::VertexType::FlagType VertexFlag; typedef typename MeshType::VertexType::TexCoordType VertexTexCoordType; typedef typename MeshType::VertexType::TexCoordType::ScalarType VertexTexScalar; typedef typename MeshType::VertexType::CurvatureType VertexCurType; typedef typename MeshType::VertexType::CurvatureType::ScalarType VertexCurScalar; typedef typename MeshType::VertexType::CurvatureDirType VertexCurDirType; typedef typename MeshType::VertexType::CurScalarType VertexDirCurScalar; typedef typename MeshType::VertexType::CurVecType::ScalarType VertexDirCurVecScalar; typedef typename MeshType::EdgeType EdgeType; typedef typename MeshType::EdgeType::ColorType::ScalarType EdgeColorScalar; typedef typename MeshType::EdgeType::QualityType EdgeQuality; typedef typename MeshType::EdgeType::FlagType EdgeFlag; typedef typename MeshType::FaceType FaceType; typedef typename MeshType::FaceType::NormalType FaceNormalType; typedef typename MeshType::FaceType::NormalType::ScalarType FaceNormScalar; typedef typename MeshType::FaceType::ColorType FaceColorType; typedef typename MeshType::FaceType::ColorType::ScalarType FaceColorScalar; typedef typename MeshType::FaceType::QualityType FaceQuality; typedef typename MeshType::FaceType::FlagType FaceFlag; typedef typename vcg::face::vector_ocf::WedgeTexTypePack FaceTexCoordType; typedef typename MeshType::FaceType::TexCoordType::ScalarType FaceTexScalar; typedef typename MeshType::FaceType::CurvatureDirType FaceCurDirType; typedef typename MeshType::FaceType::CurScalarType FaceDirCurScalar; typedef typename MeshType::FaceType::CurVecType::ScalarType FaceDirCurVecScalar; typedef typename vcg::face::vector_ocf::WedgeColorTypePack WedgeColorType; typedef typename MeshType::FaceType::WedgeColorType::ScalarType WedgeColorScalar; typedef typename vcg::face::vector_ocf::WedgeNormalTypePack WedgeNormalType; typedef typename MeshType::FaceType::WedgeNormalType::ScalarType WedgeNormalScalar; typedef typename MeshType::FaceIterator FaceIterator; template static PlyType getEntity() { return NNP_UNKNOWN_TYPE }; template<> static PlyType getEntity(){ return NNP_UINT8; }; template<> static PlyType getEntity(){ return NNP_INT8; }; template<> static PlyType getEntity(){ return NNP_UINT16; }; template<> static PlyType getEntity(){ return NNP_INT16; }; template<> static PlyType getEntity(){ return NNP_UINT32; }; template<> static PlyType getEntity(){ return NNP_INT32; }; template<> static PlyType getEntity(){ return NNP_FLOAT32; }; template<> static PlyType getEntity(){ return NNP_FLOAT64; }; template static PlyType getEntityList() { return NNP_UNKNOWN_TYPE; }; template<> static PlyType getEntityList(){ return NNP_LIST_UINT8_UINT8; }; template<> static PlyType getEntityList(){ return NNP_LIST_UINT8_INT8; }; template<> static PlyType getEntityList(){ return NNP_LIST_UINT8_UINT16; }; template<> static PlyType getEntityList(){ return NNP_LIST_UINT8_INT16; }; template<> static PlyType getEntityList(){ return NNP_LIST_UINT8_UINT32; }; template<> static PlyType getEntityList(){ return NNP_LIST_UINT8_INT32; }; template<> static PlyType getEntityList(){ return NNP_LIST_UINT8_FLOAT32; }; template<> static PlyType getEntityList(){ return NNP_LIST_UINT8_FLOAT64; }; template inline static void PushDescriport(std::vector& prop, ElementDescriptor& elem, PlyEntity entity, void* ptr) { prop.push_back(PlyProperty(getEntity(), entity)); DescriptorInterface* di = new DataDescriptor(entity, ptr); elem.dataDescriptor.push_back(di); } template inline static void PushDescriportList(std::vector& prop, ElementDescriptor& elem, PlyEntity entity, void* ptr) { prop.push_back(PlyProperty(getEntityList(), entity)); DescriptorInterface* di = new DataDescriptor(entity, ptr); elem.dataDescriptor.push_back(di); } template inline static void PushDescriport(std::vector& prop, ElementDescriptor& elem, std::string& name, void* ptr) { prop.push_back(PlyProperty(getEntity(), name)); DescriptorInterface* di = new DataDescriptor(name, ptr); elem.dataDescriptor.push_back(di); } template inline static void PushDescriportList(std::vector& prop, ElementDescriptor& elem, std::string& name, void* ptr) { prop.push_back(PlyProperty(getEntityList(), name)); DescriptorInterface* di = new DataDescriptor(name, ptr); elem.dataDescriptor.push_back(di); } public: typedef enum { IO_NONE = 0x00000000, IO_VERTCOORD = 0x00000001, IO_VERTFLAGS = 0x00000002, IO_VERTCOLOR = 0x00000004, IO_VERTQUALITY = 0x00000008, IO_VERTNORMAL = 0x00000010, IO_VERTTEXCOORD = 0x00000020, IO_VERTRADIUS = 0x00000040, IO_VERTCURV = 0x00000080, IO_VERTCURVDIR = 0x00000100, IO_VERTATTRIB = 0x00000200, IO_FACEINDEX = 0x00000400, IO_FACEFLAGS = 0x00000800, IO_FACECOLOR = 0x00001000, IO_FACEQUALITY = 0x00002000, IO_FACENORMAL = 0x00004000, IO_FACECURVDIR = 0x00008000, IO_FACEATTRIB = 0x00010000, IO_EDGEINDEX = 0x00020000, IO_EDGEQUALITY = 0x00040000, IO_EDGECOLOR = 0x00080000, IO_EDGEFLAGS = 0x00100000, IO_EDGEATTRIB = 0x00200000, IO_WEDGCOLOR = 0x00400000, IO_WEDGTEXCOORD = 0x00800000, IO_WEDGTEXMULTI = 0x01000000, // when texture index is explicit IO_WEDGNORMAL = 0x02000000, IO_ALL_ATTRIB = 0x03FFFFFF, IO_BITPOLYGONAL = 0x04000000, // loads explicit polygonal mesh IO_CAMERA = 0x08000000, IO_MESHATTRIB = 0x10000000, IO_FLAGS = IO_VERTFLAGS | IO_FACEFLAGS, IO_ALL = 0xFFFFFFFF }BitMask; class CustomAttributeDescriptor { public: typedef std::map MapMeshAttrib; typedef std::map::iterator MapMeshAttribIter; typedef std::map> MapMeshAttribProp; typedef std::map>::iterator MapMeshAttribPropIter; ElementDescriptor::PropertyDescriptor vertexAttrib; ElementDescriptor::PropertyDescriptor faceAttrib; ElementDescriptor::PropertyDescriptor edgeAttrib; std::vector vertexAttribProp; std::vector faceAttribProp; std::vector edgeAttribProp; MapMeshAttrib meshAttrib; MapMeshAttribProp meshAttribProp; std::map meshAttribCnt; CustomAttributeDescriptor::~CustomAttributeDescriptor() { for (int i = 0; i < vertexAttrib.size(); i++) delete vertexAttrib[i]; for (int i = 0; i < edgeAttrib.size(); i++) delete edgeAttrib[i]; for (int i = 0; i < faceAttrib.size(); i++) delete faceAttrib[i]; CustomAttributeDescriptor::MapMeshAttribIter iter = meshAttrib.begin(); for (; iter != meshAttrib.end(); iter++) for (int i = 0; i < (*iter).second.size(); i++) delete (*iter).second[i]; } template void AddVertexAttribDescriptor(const std::string& name, PlyType type, void* ptr) { AddAttribDescriptor(name, type, ptr, vertexAttrib, vertexAttribProp); } template void AddEdgeAttribDescriptor(const std::string& name, PlyType type, void* ptr) { AddAttribDescriptor(name, type, ptr, edgeAttrib, edgeAttribProp); } template void AddFaceAttribDescriptor(const std::string& name, PlyType type, void* ptr) { AddAttribDescriptor(name, type, ptr, faceAttrib, faceAttribProp); } template void AddMeshAttribDescriptor(const std::string& nameAttrib, std::string& nameProp, PlyType type, void* ptr) { meshAttrib[nameAttrib].push_back(new DataDescriptor(nameProp, ptr)); meshAttribProp[nameAttrib].push_back(PlyProperty(type, nameProp)); } void AddMeshAttrib(std::string& name, int cnt) { meshAttribCnt[name] = cnt; } void GetMeshAttrib(std::string filename) { nanoply::Info info(filename); if (info.errInfo == nanoply::NNP_OK) { for (int i = 0; i < info.elemVec.size(); i++) { if (info.elemVec[i].plyElem == NNP_UNKNOWN_ELEM && info.elemVec[i].name != "camera") meshAttribCnt[info.elemVec[i].name] = info.elemVec[i].cnt; } } } bool CreateVertexAttribDescriptor(const PointerToAttribute* ptr) { return CreateAttribDescriptor(ptr, vertexAttrib, vertexAttribProp); } bool CreateEdgeAttribDescriptor(const PointerToAttribute* ptr) { return CreateAttribDescriptor(ptr, edgeAttrib, edgeAttribProp); } bool CreateFaceAttribDescriptor(const PointerToAttribute* ptr) { return CreateAttribDescriptor(ptr, faceAttrib, faceAttribProp); } bool AddVertexAttrib(MeshType& m, std::set& ptrAttrib, PlyElement* elem) { return AddCustomAttrib<0>(m, ptrAttrib, elem, vertexAttrib); } bool AddEdgeAttrib(MeshType& m, std::set& ptrAttrib, PlyElement* elem) { return AddCustomAttrib<1>(m, ptrAttrib, elem, vertexAttrib); } bool AddFaceAttrib(MeshType& m, std::set& ptrAttrib, PlyElement* elem) { return AddCustomAttrib<2>(m, ptrAttrib, elem, vertexAttrib); } private: const std::vector pointSuffix = { "x", "y", "z", "w" }; const std::vector colorSuffix = { "r", "g", "b", "a" }; const std::map pointSuffixMap = { { "x", 0 },{ "y", 1 },{ "z", 2 },{ "w", 3 } }; const std::map colorSuffixMap = { {"r", 0},{ "g", 1 },{ "b", 2 },{ "a", 3 } }; const std::string separator = std::string("@_.#$>"); template void AddAttribDescriptor(const std::string& name, PlyType type, void* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) { attrib.push_back(new DataDescriptor(name, ptr)); attribProp.push_back(PlyProperty(type, name)); } template void AddScalarAttribDescriptor(const PointerToAttribute* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) { AddAttribDescriptor(ptr->_name, getEntity(), ptr->_handle->DataBegin(), attrib, attribProp); } template void AddPointAttribDescriptor(const PointerToAttribute* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) { int size = typename Container::Dimension; std::string name(ptr->_name); Container* tmpPtr = (Container*)ptr->_handle->DataBegin(); for (int i = 0 ; i < size; i++) AddAttribDescriptor((name + "." + pointSuffix[i]), getEntity(), &(*tmpPtr)[i], attrib, attribProp); } template void AddColorAttribDescriptor(const PointerToAttribute* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) { int size = typename Container::Dimension; std::string name(ptr->_name); Container* tmpPtr = (Container*)ptr->_handle->DataBegin(); for (int i = 0; i < size; i++) AddAttribDescriptor((name + "." + colorSuffix[i]), getEntity(), &(*tmpPtr)[i], attrib, attribProp); } template void AddListAttribDescriptor(const PointerToAttribute* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) { AddAttribDescriptor(ptr->_name, getEntityList(), ptr->_handle->DataBegin(), attrib, attribProp); } bool CreateAttribDescriptor(const PointerToAttribute* ptr, ElementDescriptor::PropertyDescriptor& attrib, std::vector& attribProp) { if (ptr->_type == std::type_index(typeid(unsigned char))) AddScalarAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(char))) AddScalarAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(unsigned short))) AddScalarAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(short))) AddScalarAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(unsigned int))) AddScalarAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(int))) AddScalarAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(float))) AddScalarAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(double))) AddScalarAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point2s))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point2i))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point2f))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point2d))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point3s))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point3i))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point3f))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point3d))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point4s))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point4i))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point4f))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Point4d))) AddPointAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Color4b))) AddColorAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Color4f))) AddColorAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Color4d))) AddColorAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(vcg::Color4d))) AddColorAttribDescriptor(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(std::vector))) AddListAttribDescriptor, unsigned char>(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(std::vector))) AddListAttribDescriptor,char>(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(std::vector))) AddListAttribDescriptor, unsigned short>(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(std::vector))) AddListAttribDescriptor, short>(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(std::vector))) AddListAttribDescriptor, unsigned int>(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(std::vector))) AddListAttribDescriptor, int>(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(std::vector))) AddListAttribDescriptor, float>(ptr, attrib, attribProp); else if (ptr->_type == std::type_index(typeid(std::vector))) AddListAttribDescriptor, double>(ptr, attrib, attribProp); else return false; return true; } template void AddScalarAttrib(MeshType& m, const std::string& name, PlyType& type) { if (ActionType == 0) //vertex { auto h = vcg::tri::Allocator::GetPerVertexAttribute(m, name); AddVertexAttribDescriptor(name, type, h._handle->DataBegin()); } else if (ActionType == 1) //Edge { auto h = vcg::tri::Allocator::GetPerEdgeAttribute(m, name); AddEdgeAttribDescriptor(name, type, h._handle->DataBegin()); } else if (ActionType == 2) //Face { auto h = vcg::tri::Allocator::GetPerFaceAttribute(m, name); AddFaceAttribDescriptor(name, type, h._handle->DataBegin()); } } template void AddPointAttrib(MeshType& m, const std::string& name, std::vector& prop) { if (ActionType == 0) //vertex { auto h = vcg::tri::Allocator::GetPerVertexAttribute(m, name); for (int i = 0; i < prop.size(); i++) AddVertexAttribDescriptor(prop[i].name, prop[i].type, &h[0][i]); } else if (ActionType == 1) //Edge { auto h = vcg::tri::Allocator::GetPerEdgeAttribute(m, name); for (int i = 0; i < prop.size(); i++) AddEdgeAttribDescriptor(prop[i].name, prop[i].type, &h[0][i]); } else if (ActionType == 2) //Face { auto h = vcg::tri::Allocator::GetPerFaceAttribute(m, name); for (int i = 0; i < prop.size(); i++) AddFaceAttribDescriptor(prop[i].name, prop[i].type, &h[0][i]); } } template void AddListAttrib(MeshType& m, const std::string& name, PlyType& type) { if (ActionType == 0) //vertex { auto h = vcg::tri::Allocator::GetPerVertexAttribute(m, name); AddVertexAttribDescriptor(name, type, h._handle->DataBegin()); } else if (ActionType == 1) //Edge { auto h = vcg::tri::Allocator::GetPerEdgeAttribute(m, name); AddEdgeAttribDescriptor(name, type, h._handle->DataBegin()); } else if (ActionType == 2) //Face { auto h = vcg::tri::Allocator::GetPerFaceAttribute(m, name); AddFaceAttribDescriptor(name, type, h._handle->DataBegin()); } } template bool AddCustomAttrib(MeshType& m, std::set& ptrAttrib, PlyElement* elem, ElementDescriptor::PropertyDescriptor& attrib) { //Custom attribute with already a data descriptor std::set validCustomAttrib; for (int i = 0; i < attrib.size(); i++) { if (attrib[i]->base == NULL) { std::set::iterator ai; for (ai = ptrAttrib.begin(); ai != ptrAttrib.end(); ++ai) { if (attrib[i]->name == (*ai)._name) { attrib[i]->base = ai->_handle->DataBegin(); validCustomAttrib.insert(attrib[i]->name); break; } } } else validCustomAttrib.insert(attrib[i]->name); } //Get custom properties without a data descriptor std::map, int>> customAttribName; std::vector attribName((*elem).propVec.size()); for (int i = 0; i < (*elem).propVec.size(); i++) { if ((*elem).propVec[i].elem == NNP_UNKNOWN_ENTITY) { if (validCustomAttrib.find((*elem).propVec[i].name) == validCustomAttrib.end()) { std::size_t found = (*elem).propVec[i].name.find_first_of(separator); if (found != std::string::npos) { attribName[i] = (*elem).propVec[i].name.substr(0, found); std::string suffix = (*elem).propVec[i].name.substr(found+1); std::map::const_iterator it1, it2; it1 = pointSuffixMap.find(suffix); it2 = colorSuffixMap.find(suffix); if (it1 != pointSuffixMap.cend()) customAttribName[attribName[i]].second |= (1 << (*it1).second); else if (it2 != colorSuffixMap.cend()) customAttribName[attribName[i]].second |= (1 << ((*it2).second + 4)); } else attribName[i] = (*elem).propVec[i].name; customAttribName[attribName[i]].first.push_back((*elem).propVec[i]); } } } //Create the attribute and the data descriptor std::map, int>>::iterator mapIter; for (mapIter = customAttribName.begin(); mapIter != customAttribName.end(); mapIter++) { unsigned int bitType = 0; std::vector tempProp((*mapIter).second.first.size()); int checkMask = (1 << (*mapIter).second.first.size()) - 1; for (int i = 0; i < (*mapIter).second.first.size(); i++) { PlyProperty& p = (*mapIter).second.first[i]; bitType |= p.type; std::size_t found = p.name.find_first_of(separator); if (found != std::string::npos) { std::string suffix = p.name.substr(found + 1); if ((*mapIter).second.second == checkMask) tempProp[(*pointSuffixMap.find(suffix)).second] = p; else if ((*mapIter).second.second == (checkMask << 4)) tempProp[(*colorSuffixMap.find(suffix)).second] = p; else tempProp[i] = p; } else tempProp[i] = p; } unsigned int r = (bitType & (~tempProp[0].type)); if (tempProp.size() > 1 && ((bitType & (~tempProp[0].type)) == 0)) { if (tempProp.size() == 2) { switch (tempProp[0].type) { case NNP_FLOAT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_FLOAT64: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_INT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; case NNP_INT16: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_INT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_UINT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; case NNP_UINT16: AddPointAttrib>(m, (*mapIter).first, tempProp); break; case NNP_UINT32: AddPointAttrib>(m, (*mapIter).first, tempProp); break; } } else if (tempProp.size() == 3) { switch (tempProp[0].type) { case NNP_FLOAT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_FLOAT64: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_INT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; case NNP_INT16: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_INT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_UINT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; case NNP_UINT16: AddPointAttrib>(m, (*mapIter).first, tempProp); break; case NNP_UINT32: AddPointAttrib>(m, (*mapIter).first, tempProp); break; } } else if (tempProp.size() == 4 && (*mapIter).second.second != (checkMask << 4)) { switch (tempProp[0].type) { case NNP_FLOAT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_FLOAT64: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_INT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; case NNP_INT16: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_INT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_UINT8: AddPointAttrib>(m, (*mapIter).first, tempProp); break; case NNP_UINT16: AddPointAttrib>(m, (*mapIter).first, tempProp); break; case NNP_UINT32: AddPointAttrib>(m, (*mapIter).first, tempProp); break; } } else if (tempProp.size() == 4) { switch (tempProp[0].type) { case NNP_INT8: case NNP_INT16: case NNP_INT32: case NNP_UINT16: case NNP_UINT32: case NNP_FLOAT32: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_FLOAT64: AddPointAttrib(m, (*mapIter).first, tempProp); break; case NNP_UINT8: AddPointAttrib(m, (*mapIter).first, tempProp); break; } } } else { for (int i = 0; i < tempProp.size(); i++) { switch (tempProp[i].type) { case NNP_FLOAT32: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; case NNP_FLOAT64: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; case NNP_INT8: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; case NNP_INT16: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; case NNP_INT32: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; case NNP_UINT8: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; case NNP_UINT16: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; case NNP_UINT32: AddScalarAttrib(m, tempProp[i].name, tempProp[i].type); break; case NNP_LIST_UINT8_UINT32: case NNP_LIST_INT8_UINT32: AddListAttrib, unsigned int>(m, tempProp[i].name, tempProp[i].type); break; case NNP_LIST_UINT8_INT32: case NNP_LIST_INT8_INT32: AddListAttrib, int>(m, tempProp[i].name, tempProp[i].type); break; case NNP_LIST_UINT8_FLOAT32: case NNP_LIST_INT8_FLOAT32: AddListAttrib, float>(m, tempProp[i].name, tempProp[i].type); break; case NNP_LIST_UINT8_FLOAT64: case NNP_LIST_INT8_FLOAT64: AddListAttrib, double>(m, tempProp[i].name, tempProp[i].type); break; case NNP_LIST_UINT8_UINT8: case NNP_LIST_INT8_UINT8: AddListAttrib, unsigned char>(m, tempProp[i].name, tempProp[i].type); break; case NNP_LIST_UINT8_INT8: case NNP_LIST_INT8_INT8: AddListAttrib, char>(m, tempProp[i].name, tempProp[i].type); break; case NNP_LIST_UINT8_UINT16: case NNP_LIST_INT8_UINT16: AddListAttrib, unsigned short>(m, tempProp[i].name, tempProp[i].type); break; case NNP_LIST_UINT8_INT16: case NNP_LIST_INT8_INT16: AddListAttrib, short>(m, tempProp[i].name, tempProp[i].type); break; } } } } return true; } }; template struct OcfManager { typedef typename T::VertexType VType; typedef typename T::FaceType FType; typedef typename T::EdgeType EType; template >::value> static unsigned int EnableVertexOcf(typename T::VertContainer& cont, unsigned int mask) { return 0; } template <> static unsigned int EnableVertexOcf(typename T::VertContainer& cont, unsigned int mask ) { unsigned int enabledMask = 0; if ((mask & BitMask::IO_VERTNORMAL) && VType::HasNormalOcf() && !cont.IsNormalEnabled()) { cont.EnableNormal(); enabledMask |= BitMask::IO_VERTNORMAL; } if ((mask & BitMask::IO_VERTCOLOR) && VType::HasColorOcf() && !cont.IsColorEnabled()) { cont.EnableColor(); enabledMask |= BitMask::IO_VERTCOLOR; } if ((mask & BitMask::IO_VERTQUALITY) && VType::HasQualityOcf() && !cont.IsQualityEnabled()) { cont.EnableQuality(); enabledMask |= BitMask::IO_VERTQUALITY; } if ((mask & BitMask::IO_VERTCURV) && VType::HasCurvatureOcf() && !cont.IsCurvatureEnabled()) { cont.EnableCurvature(); enabledMask |= BitMask::IO_VERTCURV; } if ((mask & BitMask::IO_VERTCURVDIR) && VType::HasCurvatureDirOcf() && !cont.IsCurvatureDirEnabled()) { cont.EnableCurvatureDir(); enabledMask |= BitMask::IO_VERTCURVDIR; } if ((mask & BitMask::IO_VERTRADIUS) && VType::HasRadiusOcf() && !cont.IsRadiusEnabled()) { cont.EnableRadius(); enabledMask |= BitMask::IO_VERTRADIUS; } if ((mask & BitMask::IO_VERTTEXCOORD) && VType::HasTexCoordOcf() && !cont.IsTexCoordEnabled()) { cont.EnableTexCoord(); enabledMask |= BitMask::IO_VERTTEXCOORD; } return enabledMask; }; template >::value> static unsigned int EnableFaceOcf(typename T::FaceContainer& cont, unsigned int mask) { return 0; } template <> static unsigned int EnableFaceOcf(typename T::FaceContainer& cont, unsigned int mask) { unsigned int enabledMask = 0; if ((mask & BitMask::IO_FACENORMAL) && FType::HasNormalOcf() && !cont.IsNormalEnabled()) { cont.EnableNormal(); enabledMask |= BitMask::IO_FACENORMAL; } if ((mask & BitMask::IO_FACECOLOR) && FType::HasColorOcf() && !cont.IsColorEnabled()) { cont.EnableColor(); enabledMask |= BitMask::IO_FACECOLOR; } if ((mask & BitMask::IO_FACEQUALITY) && FType::HasQualityOcf() && !cont.IsQualityEnabled()) { cont.EnableQuality(); enabledMask |= BitMask::IO_FACEQUALITY; } if ((mask & BitMask::IO_FACECURVDIR) && FType::HasCurvatureDirOcf() && !cont.IsCurvatureDirEnabled()) { cont.EnableCurvatureDir(); enabledMask |= BitMask::IO_FACECURVDIR; } if ((mask & BitMask::IO_WEDGCOLOR) && FType::HasWedgeColorOcf() && !cont.IsWedgeColorEnabled()) { cont.EnableWedgeColor(); enabledMask |= BitMask::IO_WEDGCOLOR; } if ((mask & BitMask::IO_WEDGNORMAL) && FType::HasWedgeNormalOcf() && !cont.IsWedgeNormalEnabled()) { cont.EnableWedgeNormal(); enabledMask |= BitMask::IO_WEDGNORMAL; } if ((mask & BitMask::IO_WEDGTEXCOORD) && FType::HasWedgeTexCoordOcf() && !cont.IsWedgeTexCoordEnabled()) { cont.EnableWedgeTexCoord(); enabledMask |= BitMask::IO_WEDGTEXCOORD; } if ((mask & BitMask::IO_WEDGTEXMULTI) && FType::HasWedgeTexCoordOcf()) { if (!cont.IsWedgeTexCoordEnabled()) cont.EnableWedgeTexCoord(); enabledMask |= BitMask::IO_WEDGTEXMULTI; } return enabledMask; }; template >::value> static unsigned int VertexOcfMask(typename T::VertContainer& cont) { return 0; } template <> static unsigned int VertexOcfMask(typename T::VertContainer& cont) { unsigned int enabledMask = 0; if (VType::HasNormalOcf() && cont.IsNormalEnabled()) enabledMask |= BitMask::IO_VERTNORMAL; if (VType::HasColorOcf() && cont.IsColorEnabled()) enabledMask |= BitMask::IO_VERTCOLOR; if (VType::HasQualityOcf() && cont.IsQualityEnabled()) enabledMask |= BitMask::IO_VERTQUALITY; if (VType::HasCurvatureOcf() && cont.IsCurvatureEnabled()) enabledMask |= BitMask::IO_VERTCURV; if (VType::HasCurvatureDirOcf() && cont.IsCurvatureDirEnabled()) enabledMask |= BitMask::IO_VERTCURVDIR; if (VType::HasRadiusOcf() && cont.IsRadiusEnabled()) enabledMask |= BitMask::IO_VERTRADIUS; if (VType::HasTexCoordOcf() && cont.IsTexCoordEnabled()) enabledMask |= BitMask::IO_VERTTEXCOORD; return enabledMask; }; template >::value> static unsigned int FaceOcfMask(typename T::FaceContainer& cont) { return 0; } template <> static unsigned int FaceOcfMask(typename T::FaceContainer& cont) { unsigned int enabledMask = 0; if (FType::HasNormalOcf() && cont.IsNormalEnabled()) enabledMask |= BitMask::IO_FACENORMAL; if (FType::HasColorOcf() && cont.IsColorEnabled()) enabledMask |= BitMask::IO_FACECOLOR; if (FType::HasQualityOcf() && cont.IsQualityEnabled()) enabledMask |= BitMask::IO_FACEQUALITY; if (FType::HasCurvatureDirOcf() && cont.IsCurvatureDirEnabled()) enabledMask |= BitMask::IO_FACECURVDIR; if (FType::HasWedgeColorOcf() && cont.IsWedgeColorEnabled()) enabledMask |= BitMask::IO_WEDGCOLOR; if (FType::HasWedgeNormalOcf() && cont.IsWedgeNormalEnabled()) enabledMask |= BitMask::IO_WEDGNORMAL; if (FType::HasWedgeTexCoordOcf() && cont.IsWedgeTexCoordEnabled()) { enabledMask |= BitMask::IO_WEDGTEXCOORD; enabledMask |= BitMask::IO_WEDGTEXMULTI; } return enabledMask; }; }; static unsigned int GetFileBitMask(nanoply::Info& info) { unsigned int mask = 0; for (int j = 0; j < info.elemVec.size(); j++) { PlyElement& elem = info.elemVec[j]; if (elem.plyElem == PlyElemEntity::NNP_VERTEX_ELEM) { for (int i = 0; i < elem.propVec.size(); i++) { switch (elem.propVec[i].elem) { case NNP_PXYZ: mask |= BitMask::IO_VERTCOORD; break; case NNP_NXYZ: mask |= BitMask::IO_VERTNORMAL; break; case NNP_CRGB: case NNP_CRGBA: mask |= BitMask::IO_VERTCOLOR; break; case NNP_BITFLAG: mask |= BitMask::IO_VERTFLAGS; break; case NNP_QUALITY: mask |= BitMask::IO_VERTQUALITY; break; case NNP_DENSITY: mask |= BitMask::IO_VERTRADIUS; break; case NNP_TEXTURE2D: case NNP_TEXTURE3D: mask |= BitMask::IO_VERTTEXCOORD; break; case NNP_KH: case NNP_KG: mask |= BitMask::IO_VERTCURV; break; case NNP_K1: case NNP_K2: case NNP_K1DIR: case NNP_K2DIR: mask |= BitMask::IO_VERTCURVDIR; break; case NNP_UNKNOWN_ENTITY: mask |= BitMask::IO_VERTATTRIB; break; } } } else if (elem.plyElem == PlyElemEntity::NNP_EDGE_ELEM) { for (int i = 0; i < elem.propVec.size(); i++) { switch (elem.propVec[i].elem) { case NNP_EDGE_V1: case NNP_EDGE_V2: mask |= BitMask::IO_EDGEINDEX; break; case NNP_CRGB: case NNP_CRGBA: mask |= BitMask::IO_EDGECOLOR; break; case NNP_BITFLAG: mask |= BitMask::IO_EDGEFLAGS; break; case NNP_QUALITY: mask |= BitMask::IO_EDGEQUALITY; break; case NNP_UNKNOWN_ENTITY: mask |= BitMask::IO_EDGEATTRIB; break; } } } else if (elem.plyElem == PlyElemEntity::NNP_FACE_ELEM) { for (int i = 0; i < elem.propVec.size(); i++) { switch (elem.propVec[i].elem) { case NNP_FACE_VERTEX_LIST: mask |= BitMask::IO_FACEINDEX; break; case NNP_NXYZ: mask |= BitMask::IO_FACENORMAL; break; case NNP_CRGB: case NNP_CRGBA: mask |= BitMask::IO_FACECOLOR; break; case NNP_BITFLAG: mask |= BitMask::IO_FACEFLAGS; break; case NNP_QUALITY: mask |= BitMask::IO_FACEQUALITY; break; case NNP_K1: case NNP_K2: case NNP_K1DIR: case NNP_K2DIR: mask |= BitMask::IO_FACECURVDIR; break; case NNP_FACE_WEDGE_COLOR: mask |= BitMask::IO_WEDGCOLOR; break; case NNP_FACE_WEDGE_NORMAL: mask |= BitMask::IO_WEDGNORMAL; break; case NNP_FACE_WEDGE_TEX: mask |= BitMask::IO_WEDGTEXCOORD; break; case NNP_TEXTUREINDEX: mask |= BitMask::IO_WEDGTEXMULTI; break; case NNP_UNKNOWN_ENTITY: mask |= BitMask::IO_FACEATTRIB; break; } } } else if (elem.plyElem == PlyElemEntity::NNP_UNKNOWN_ELEM) { if (elem.name == "camera") mask |= BitMask::IO_CAMERA; else mask |= BitMask::IO_MESHATTRIB; } } return mask; }; static int LoadModel(const char* filename, MeshType& mesh, unsigned int bitMask, CustomAttributeDescriptor& custom) { nanoply::Info info(filename); if (info.errInfo != nanoply::NNP_OK) return info.errInfo; unsigned int headerMask = GetFileBitMask(info); bitMask &= headerMask; unsigned int ocfVertexMask = OcfManager::EnableVertexOcf(mesh.vert, bitMask); unsigned int ocfFaceMask = OcfManager::EnableFaceOcf(mesh.face, bitMask); //Camera ElementDescriptor cameraDescr(std::string("camera")); vcg::Point3 tra; vcg::Matrix44 rot; size_t count = info.GetElementCount(std::string("camera")); if (count > 0 && (bitMask & BitMask::IO_CAMERA)) { cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("view_px"), &tra[0])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("view_py"), &tra[1])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("view_pz"), &tra[2])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("x_axisx"), &rot[0][0])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("x_axisy"), &rot[0][1])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("x_axisz"), &rot[0][2])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("y_axisx"), &rot[1][0])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("y_axisy"), &rot[1][1])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("y_axisz"), &rot[1][2])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("z_axisx"), &rot[2][0])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("z_axisy"), &rot[2][1])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("z_axisz"), &rot[2][2])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("focal"), &mesh.shot.Intrinsics.FocalMm)); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("scalex"), &mesh.shot.Intrinsics.PixelSizeMm[0])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("scaley"), &mesh.shot.Intrinsics.PixelSizeMm[1])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("centerx"), &mesh.shot.Intrinsics.CenterPx[0])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("centery"), &mesh.shot.Intrinsics.CenterPx[1])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("viewportx"), &mesh.shot.Intrinsics.ViewportPx[0])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("viewporty"), &mesh.shot.Intrinsics.ViewportPx[1])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("k1"), &mesh.shot.Intrinsics.k[0])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("k2"), &mesh.shot.Intrinsics.k[1])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("k3"), &mesh.shot.Intrinsics.k[2])); cameraDescr.dataDescriptor.push_back(new DataDescriptor(std::string("k4"), &mesh.shot.Intrinsics.k[3])); } //Vertex std::vector nameList; VertexType::Name(nameList); ElementDescriptor vertexDescr(NNP_VERTEX_ELEM); count = info.GetVertexCount(); if (nameList.size() > 0 && count > 0) { vcg::tri::Allocator::AddVertices(mesh, count); if ((bitMask & BitMask::IO_VERTCOORD) && VertexType::HasCoord()) vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_PXYZ, (*mesh.vert.begin()).P().V())); if ((bitMask & BitMask::IO_VERTNORMAL) && vcg::tri::HasPerVertexNormal(mesh)) { if (ocfVertexMask & BitMask::IO_VERTNORMAL) vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_NXYZ, (*mesh.vert.begin()).N().V())); else vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_NXYZ, (*mesh.vert.begin()).N().V())); } if ((bitMask & BitMask::IO_VERTCOLOR) && vcg::tri::HasPerVertexColor(mesh)) { if (ocfVertexMask & BitMask::IO_VERTCOLOR) vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.vert.begin()).C().V())); else vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.vert.begin()).C().V())); } if ((bitMask & BitMask::IO_VERTQUALITY) && vcg::tri::HasPerVertexQuality(mesh)) { if (ocfVertexMask & BitMask::IO_VERTQUALITY) vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.vert.begin()).Q())); else vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.vert.begin()).Q())); } if ((bitMask & BitMask::IO_VERTFLAGS) && vcg::tri::HasPerVertexFlags(mesh)) vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_BITFLAG, &(*mesh.vert.begin()).Flags())); if ((bitMask & BitMask::IO_VERTRADIUS) && vcg::tri::HasPerVertexRadius(mesh)) { if (ocfVertexMask & BitMask::IO_VERTRADIUS) vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_DENSITY, &(*mesh.vert.begin()).R())); else vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_DENSITY, &(*mesh.vert.begin()).R())); } if ((bitMask & BitMask::IO_VERTTEXCOORD) && vcg::tri::HasPerVertexTexCoord(mesh)) { if (ocfVertexMask & BitMask::IO_VERTTEXCOORD) vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V())); else vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V())); } if ((bitMask & BitMask::IO_VERTCURV) && vcg::tri::HasPerVertexCurvature(mesh)) { if (ocfVertexMask & BitMask::IO_VERTCURV) { vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KG, &(*mesh.vert.begin()).Kg())); vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KH, &(*mesh.vert.begin()).Kh())); } else { vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KG, &(*mesh.vert.begin()).Kg())); vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_KH, &(*mesh.vert.begin()).Kh())); } } if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerVertexCurvatureDir(mesh)) { if (ocfVertexMask & BitMask::IO_VERTCURVDIR) { vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.vert.begin()).K1())); vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2, &(*mesh.vert.begin()).K2())); vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1DIR, (*mesh.vert.begin()).PD1().V())); vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2DIR, (*mesh.vert.begin()).PD2().V())); } else { vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.vert.begin()).K1())); vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2, &(*mesh.vert.begin()).K2())); vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1DIR, (*mesh.vert.begin()).PD1().V())); vertexDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2DIR, (*mesh.vert.begin()).PD2().V())); } } if (bitMask & BitMask::IO_VERTATTRIB) { custom.AddVertexAttrib(mesh, mesh.vert_attr, info.GetVertexElement()); for (int i = 0; i < custom.vertexAttrib.size(); i++) { if ((*custom.vertexAttrib[i]).base != NULL) vertexDescr.dataDescriptor.push_back(custom.vertexAttrib[i]); } } } //Edge nameList.clear(); EdgeType::Name(nameList); ElementDescriptor edgeDescr(NNP_EDGE_ELEM); count = info.GetEdgeCount(); std::vector edgeIndex; if (nameList.size() > 0 && count > 0) { vcg::tri::Allocator::AddEdges(mesh, count); if ((bitMask & BitMask::IO_EDGEINDEX) && MeshType::EdgeType::HasVertexRef()) { edgeIndex.resize(count); edgeDescr.dataDescriptor.push_back(new DataDescriptor(NNP_EDGE_V1, &(*edgeIndex.begin()).V()[0])); edgeDescr.dataDescriptor.push_back(new DataDescriptor(NNP_EDGE_V2, &(*edgeIndex.begin()).V()[1])); } if ((bitMask & BitMask::IO_EDGEQUALITY) && vcg::tri::HasPerEdgeQuality(mesh)) edgeDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.edge.begin()).Q())); if ((bitMask & BitMask::IO_EDGECOLOR) && vcg::tri::HasPerEdgeColor(mesh)) edgeDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.edge.begin()).C().V())); if ((bitMask & BitMask::IO_EDGEFLAGS) && vcg::tri::HasPerEdgeFlags(mesh)) edgeDescr.dataDescriptor.push_back(new DataDescriptor(NNP_BITFLAG, &(*mesh.edge.begin()).Flags())); if (bitMask & BitMask::IO_EDGEATTRIB) { custom.AddEdgeAttrib(mesh, mesh.edge_attr, info.GetEdgeElement()); for (int i = 0; i < custom.edgeAttrib.size(); i++) { if ((*custom.edgeAttrib[i]).base != NULL) edgeDescr.dataDescriptor.push_back(custom.edgeAttrib[i]); } } } //Face nameList.clear(); FaceType::Name(nameList); ElementDescriptor faceDescr(NNP_FACE_ELEM); count = info.GetFaceCount(); std::vector> faceIndex; std::vector> wedgeTexCoord; if (nameList.size() > 0 && count > 0) { vcg::tri::Allocator::AddFaces(mesh, count); if ((bitMask & BitMask::IO_FACEINDEX) && FaceType::HasVertexRef()) { faceIndex.resize(count); faceDescr.dataDescriptor.push_back(new DataDescriptor,0, unsigned int>(NNP_FACE_VERTEX_LIST, &faceIndex[0])); } if ((bitMask & BitMask::IO_FACEFLAGS) && vcg::tri::HasPerFaceFlags(mesh)) faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_BITFLAG, &(*mesh.face.begin()).Flags())); if ((bitMask & BitMask::IO_FACECOLOR) && vcg::tri::HasPerFaceColor(mesh)) { if (ocfFaceMask & BitMask::IO_FACECOLOR) faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.face.begin()).C().V())); else faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_CRGBA, (*mesh.face.begin()).C().V())); } if ((bitMask & BitMask::IO_FACEQUALITY) && vcg::tri::HasPerFaceQuality(mesh)) { if (ocfFaceMask & BitMask::IO_FACEQUALITY) faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.face.begin()).Q())); else faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_QUALITY, &(*mesh.face.begin()).Q())); } if ((bitMask & BitMask::IO_FACENORMAL) && vcg::tri::HasPerFaceNormal(mesh)) { if (ocfFaceMask & BitMask::IO_FACENORMAL) faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_NXYZ, (*mesh.face.begin()).N().V())); else faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_NXYZ, (*mesh.face.begin()).N().V())); } if ((bitMask & BitMask::IO_FACECURVDIR) && vcg::tri::HasPerFaceCurvatureDir(mesh)) { if (ocfFaceMask & BitMask::IO_FACECURVDIR) { faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.face.begin()).K1())); faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2, &(*mesh.face.begin()).K2())); faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1DIR, (*mesh.face.begin()).PD1().V())); faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2DIR, (*mesh.face.begin()).PD2().V())); } else { faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1, &(*mesh.face.begin()).K1())); faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2, &(*mesh.face.begin()).K2())); faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K1DIR, (*mesh.face.begin()).PD1().V())); faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_K2DIR, (*mesh.face.begin()).PD2().V())); } } if (((bitMask & BitMask::IO_WEDGTEXCOORD) || (bitMask & BitMask::IO_WEDGTEXMULTI)) && vcg::tri::HasPerWedgeTexCoord(mesh)) { wedgeTexCoord.resize(count); faceDescr.dataDescriptor.push_back(new DataDescriptor, 6, FaceTexScalar>(NNP_FACE_WEDGE_TEX, (*wedgeTexCoord.begin()).V())); } if ((bitMask & BitMask::IO_WEDGTEXMULTI) && vcg::tri::HasPerWedgeTexCoord(mesh)) { if (ocfFaceMask & BitMask::IO_WEDGTEXMULTI) faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTUREINDEX, &(*mesh.face.begin()).WT(0).N())); else faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_TEXTUREINDEX, &(*mesh.face.begin()).WT(0).N())); } if ((bitMask & BitMask::IO_WEDGCOLOR) && vcg::tri::HasPerWedgeColor(mesh)) { if (ocfFaceMask & BitMask::IO_WEDGCOLOR) faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_WEDGE_COLOR, (*mesh.face.begin()).WC(0).V())); else faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_WEDGE_COLOR, (*mesh.face.begin()).WC(0).V())); } if ((bitMask & BitMask::IO_WEDGNORMAL) && vcg::tri::HasPerWedgeNormal(mesh)) { if (ocfFaceMask & BitMask::IO_WEDGNORMAL) faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_WEDGE_NORMAL, (*mesh.face.begin()).WN(0).V())); else faceDescr.dataDescriptor.push_back(new DataDescriptor(NNP_FACE_WEDGE_NORMAL, (*mesh.face.begin()).WN(0).V())); } if (bitMask & BitMask::IO_FACEATTRIB) { custom.AddFaceAttrib(mesh, mesh.face_attr, info.GetFaceElement()); for (int i = 0; i < custom.faceAttrib.size(); i++) { if ((*custom.faceAttrib[i]).base != NULL) faceDescr.dataDescriptor.push_back(custom.faceAttrib[i]); } } } std::vector meshDescr; meshDescr.push_back(&cameraDescr); meshDescr.push_back(&vertexDescr); meshDescr.push_back(&edgeDescr); meshDescr.push_back(&faceDescr); //Mesh attribute if ((bitMask & BitMask::IO_MESHATTRIB)) { CustomAttributeDescriptor::MapMeshAttribIter iter = custom.meshAttrib.begin(); for (; iter != custom.meshAttrib.end(); iter++) { std::string name((*iter).first); meshDescr.push_back(new ElementDescriptor(name)); count = info.GetElementCount(name); if (count > 1) { meshDescr.back()->dataDescriptor = (*iter).second; } } } if (!OpenModel(info, meshDescr)) return info.errInfo; mesh.shot.SetViewPoint(tra); mesh.shot.Extrinsics.SetRot(rot); bool triangleMesh = true; for (int i = 0; i < faceIndex.size(); i++) if (faceIndex[i].size() > 3) triangleMesh = false; if (!triangleMesh && !vcg::tri::HasPolyInfo(mesh)) { bool hasFaceFlags = (bitMask & BitMask::IO_FACEFLAGS) && vcg::tri::HasPerFaceFlags(mesh); bool hasFaceColor = (bitMask & BitMask::IO_FACECOLOR) && vcg::tri::HasPerFaceColor(mesh); bool hasFaceQuality = (bitMask & BitMask::IO_FACEQUALITY) && vcg::tri::HasPerFaceQuality(mesh); bool hasFaceNormal = (bitMask & BitMask::IO_FACENORMAL) && vcg::tri::HasPerFaceNormal(mesh); for (int i = 0; i < faceIndex.size(); i++) { if (faceIndex[i].size() >= 3) { for (int j = 0; j < 3; j++) mesh.face[i].V(j) = &mesh.vert[faceIndex[i][j]]; if (hasFaceFlags) mesh.face[i].SetF(2); FaceIterator fi = vcg::tri::Allocator::AddFaces(mesh, faceIndex[i].size() - 3); for (int j = 3; j < faceIndex[i].size(); j++) { (*fi).V(0) = &mesh.vert[faceIndex[i][0]]; (*fi).V(1) = &mesh.vert[faceIndex[i][j - 1]]; (*fi).V(2) = &mesh.vert[faceIndex[i][j]]; if (hasFaceFlags) { (*fi).SetFlags(mesh.face[i].Flags()); (*fi).SetF(0); if (j == faceIndex[i].size() - 1) (*fi).ClearF(2); } if (hasFaceColor) (*fi).C() = mesh.face[i].C(); if (hasFaceQuality) (*fi).Q() = mesh.face[i].Q(); if (hasFaceNormal) (*fi).N() = mesh.face[i].N(); fi++; } } else mesh.face[i].V(0) = mesh.face[i].V(1) = mesh.face[i].V(2) = &mesh.vert[0]; } } else { for (int i = 0; i < faceIndex.size(); i++) { mesh.face[i].Alloc(faceIndex[i].size()); for (int j = 0; j < faceIndex[i].size(); j++) mesh.face[i].V(j) = &mesh.vert[faceIndex[i][j]]; } for (int i = 0; i < wedgeTexCoord.size(); i++) { for (int j = 0; j < 3; j++) { mesh.face[i].WT(j).U() = wedgeTexCoord[i][j * 2]; mesh.face[i].WT(j).V() = wedgeTexCoord[i][j * 2 + 1]; } } } for (int i = 0; i < edgeIndex.size(); i++) { mesh.edge[i].V(0) = &mesh.vert[edgeIndex[i].X()]; mesh.edge[i].V(1) = &mesh.vert[edgeIndex[i].Y()]; } for (int i = 0; i < cameraDescr.dataDescriptor.size(); i++) delete cameraDescr.dataDescriptor[i]; for (int i = 0; i < vertexDescr.dataDescriptor.size(); i++) if (vertexDescr.dataDescriptor[i]->elem != NNP_UNKNOWN_ENTITY) delete vertexDescr.dataDescriptor[i]; for (int i = 0; i < edgeDescr.dataDescriptor.size(); i++) if (edgeDescr.dataDescriptor[i]->elem != NNP_UNKNOWN_ENTITY) delete edgeDescr.dataDescriptor[i]; for (int i = 0; i < faceDescr.dataDescriptor.size(); i++) if (faceDescr.dataDescriptor[i]->elem != NNP_UNKNOWN_ENTITY) delete faceDescr.dataDescriptor[i]; mesh.textures = info.textureFile; return info.errInfo; } static int LoadModel(const char* filename, MeshType& mesh, unsigned int bitMask) { CustomAttributeDescriptor custom; return LoadModel(filename, mesh, bitMask, custom); } static bool SaveModel(const char* filename, MeshType& mesh, unsigned int bitMask, CustomAttributeDescriptor& custom, bool binary) { unsigned int ocfVertexMask = OcfManager::VertexOcfMask(mesh.vert); unsigned int ocfFaceMask = OcfManager::FaceOcfMask(mesh.face); //Camera std::vector cameraProp; ElementDescriptor cameraDescr(std::string("camera")); vcg::Point3 tra = mesh.shot.Extrinsics.Tra(); vcg::Matrix44 rot = mesh.shot.Extrinsics.Rot(); if (bitMask & BitMask::IO_CAMERA) { PushDescriport(cameraProp, cameraDescr, std::string("view_px"), &tra[0]); PushDescriport(cameraProp, cameraDescr, std::string("view_py"), &tra[1]); PushDescriport(cameraProp, cameraDescr, std::string("view_pz"), &tra[2]); PushDescriport(cameraProp, cameraDescr, std::string("x_axisx"), &rot[0][0]); PushDescriport(cameraProp, cameraDescr, std::string("x_axisy"), &rot[0][1]); PushDescriport(cameraProp, cameraDescr, std::string("x_axisz"), &rot[0][2]); PushDescriport(cameraProp, cameraDescr, std::string("y_axisx"), &rot[1][0]); PushDescriport(cameraProp, cameraDescr, std::string("y_axisy"), &rot[1][1]); PushDescriport(cameraProp, cameraDescr, std::string("y_axisz"), &rot[1][2]); PushDescriport(cameraProp, cameraDescr, std::string("z_axisx"), &rot[2][0]); PushDescriport(cameraProp, cameraDescr, std::string("z_axisy"), &rot[2][1]); PushDescriport(cameraProp, cameraDescr, std::string("z_axisz"), &rot[2][2]); PushDescriport(cameraProp, cameraDescr, std::string("focal"), &mesh.shot.Intrinsics.FocalMm); PushDescriport(cameraProp, cameraDescr, std::string("scalex"), &mesh.shot.Intrinsics.PixelSizeMm[0]); PushDescriport(cameraProp, cameraDescr, std::string("scaley"), &mesh.shot.Intrinsics.PixelSizeMm[1]); PushDescriport(cameraProp, cameraDescr, std::string("centerx"), &mesh.shot.Intrinsics.CenterPx[0]); PushDescriport(cameraProp, cameraDescr, std::string("centery"), &mesh.shot.Intrinsics.CenterPx[1]); PushDescriport(cameraProp, cameraDescr, std::string("viewportx"), &mesh.shot.Intrinsics.ViewportPx[0]); PushDescriport(cameraProp, cameraDescr, std::string("viewporty"), &mesh.shot.Intrinsics.ViewportPx[1]); PushDescriport(cameraProp, cameraDescr, std::string("k1"), &mesh.shot.Intrinsics.k[0]); PushDescriport(cameraProp, cameraDescr, std::string("k2"), &mesh.shot.Intrinsics.k[1]); PushDescriport(cameraProp, cameraDescr, std::string("k3"), &mesh.shot.Intrinsics.k[2]); PushDescriport(cameraProp, cameraDescr, std::string("k4"), &mesh.shot.Intrinsics.k[3]); } //Vertex std::vector nameList; VertexType::Name(nameList); std::vector vertexProp; ElementDescriptor vertexDescr(NNP_VERTEX_ELEM); if (nameList.size() > 0 && mesh.vert.size() > 0) { if ((bitMask & BitMask::IO_VERTCOORD) && VertexType::HasCoord()) PushDescriport(vertexProp, vertexDescr, NNP_PXYZ, (*mesh.vert.begin()).P().V()); if ((bitMask & BitMask::IO_VERTNORMAL) && vcg::tri::HasPerVertexNormal(mesh)) { if (ocfVertexMask & BitMask::IO_VERTNORMAL) PushDescriport(vertexProp, vertexDescr, NNP_NXYZ, (*mesh.vert.begin()).N().V()); else PushDescriport(vertexProp, vertexDescr, NNP_NXYZ, (*mesh.vert.begin()).N().V()); } if ((bitMask & BitMask::IO_VERTCOLOR) && vcg::tri::HasPerVertexColor(mesh)) { if (ocfVertexMask & BitMask::IO_VERTCOLOR) PushDescriport(vertexProp, vertexDescr, NNP_CRGBA, (*mesh.vert.begin()).C().V()); else PushDescriport(vertexProp, vertexDescr, NNP_CRGBA, (*mesh.vert.begin()).C().V()); } if ((bitMask & BitMask::IO_VERTQUALITY) && vcg::tri::HasPerVertexQuality(mesh)) { if (ocfVertexMask & BitMask::IO_VERTQUALITY) PushDescriport(vertexProp, vertexDescr, NNP_QUALITY, &(*mesh.vert.begin()).Q()); else PushDescriport(vertexProp, vertexDescr, NNP_QUALITY, &(*mesh.vert.begin()).Q()); } if ((bitMask & BitMask::IO_VERTFLAGS) && vcg::tri::HasPerVertexFlags(mesh)) PushDescriport(vertexProp, vertexDescr, NNP_BITFLAG, &(*mesh.vert.begin()).Flags()); if ((bitMask & BitMask::IO_VERTRADIUS) && vcg::tri::HasPerVertexRadius(mesh)) { if (ocfVertexMask & BitMask::IO_VERTRADIUS) PushDescriport(vertexProp, vertexDescr, NNP_DENSITY, &(*mesh.vert.begin()).R()); else PushDescriport(vertexProp, vertexDescr, NNP_DENSITY, &(*mesh.vert.begin()).R()); } if ((bitMask & BitMask::IO_VERTTEXCOORD) && vcg::tri::HasPerVertexTexCoord(mesh)) { if (ocfVertexMask & BitMask::IO_VERTTEXCOORD) PushDescriport(vertexProp, vertexDescr, NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V()); else PushDescriport(vertexProp, vertexDescr, NNP_TEXTURE2D, (*mesh.vert.begin()).T().P().V()); } if ((bitMask & BitMask::IO_VERTCURV) && vcg::tri::HasPerVertexCurvature(mesh)) { if (ocfVertexMask & BitMask::IO_VERTTEXCOORD) { PushDescriport(vertexProp, vertexDescr, NNP_KG, &(*mesh.vert.begin()).Kg()); PushDescriport(vertexProp, vertexDescr, NNP_KH, &(*mesh.vert.begin()).Kh()); } else { PushDescriport(vertexProp, vertexDescr, NNP_KG, &(*mesh.vert.begin()).Kg()); PushDescriport(vertexProp, vertexDescr, NNP_KH, &(*mesh.vert.begin()).Kh()); } } if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerVertexCurvatureDir(mesh)) { if (ocfVertexMask & BitMask::IO_VERTCURVDIR) { PushDescriport(vertexProp, vertexDescr, NNP_K1, &(*mesh.vert.begin()).K1()); PushDescriport(vertexProp, vertexDescr, NNP_K2, &(*mesh.vert.begin()).K2()); PushDescriportList(vertexProp, vertexDescr, NNP_K1DIR, (*mesh.vert.begin()).PD1().V()); PushDescriportList(vertexProp, vertexDescr, NNP_K2DIR, (*mesh.vert.begin()).PD2().V()); } else { PushDescriport(vertexProp, vertexDescr, NNP_K1, &(*mesh.vert.begin()).K1()); PushDescriport(vertexProp, vertexDescr, NNP_K2, &(*mesh.vert.begin()).K2()); PushDescriportList(vertexProp, vertexDescr, NNP_K1DIR, (*mesh.vert.begin()).PD1().V()); PushDescriportList(vertexProp, vertexDescr, NNP_K2DIR, (*mesh.vert.begin()).PD2().V()); } } if ((bitMask & BitMask::IO_VERTATTRIB)) { std::set::iterator ai; int userSize = custom.vertexAttrib.size(); for (ai = mesh.vert_attr.begin(); ai != mesh.vert_attr.end(); ++ai) { bool userDescr = false; for (int i = 0; i < userSize; i++) { if ((*custom.vertexAttrib[i]).name == (*ai)._name) { userDescr = true; break; } } if (!userDescr) custom.CreateVertexAttribDescriptor(&(*ai)); } for (int i = 0; i < custom.vertexAttrib.size(); i++) { vertexProp.push_back(custom.vertexAttribProp[i]); vertexDescr.dataDescriptor.push_back(custom.vertexAttrib[i]); } } } //Edge nameList.clear(); EdgeType::Name(nameList); std::vector edgeProp; ElementDescriptor edgeDescr(NNP_VERTEX_ELEM); std::vector edgeIndex; for (int i = 0; i < mesh.edge.size(); i++) edgeIndex.push_back(vcg::Point2i(vcg::tri::Index(mesh, mesh.edge[i].V(0)), vcg::tri::Index(mesh, mesh.edge[i].V(1)))); if (nameList.size() > 0 && mesh.edge.size() > 0) { if ((bitMask & BitMask::IO_EDGEINDEX) && EdgeType::HasVertexRef()) { PushDescriport(edgeProp, edgeDescr, NNP_EDGE_V1, &(*edgeIndex.begin()).V()[0]); PushDescriport(edgeProp, edgeDescr, NNP_EDGE_V2, &(*edgeIndex.begin()).V()[1]); } if ((bitMask & BitMask::IO_EDGEQUALITY) && vcg::tri::HasPerEdgeQuality(mesh)) PushDescriport(edgeProp, edgeDescr, NNP_QUALITY, &(*mesh.edge.begin()).Q()); if ((bitMask & BitMask::IO_EDGECOLOR) && vcg::tri::HasPerEdgeColor(mesh)) PushDescriport(edgeProp, edgeDescr, NNP_CRGBA, (*mesh.edge.begin()).C().V()); if ((bitMask & BitMask::IO_EDGEFLAGS) && vcg::tri::HasPerEdgeFlags(mesh)) PushDescriport(edgeProp, edgeDescr, NNP_BITFLAG, &(*mesh.edge.begin()).Flags()); if ((bitMask & BitMask::IO_EDGEATTRIB)) { std::set::iterator ai; int userSize = custom.edgeAttrib.size(); for (ai = mesh.edge_attr.begin(); ai != mesh.edge_attr.end(); ++ai) { bool userDescr = false; for (int i = 0; i < userSize; i++) { if ((*custom.edgeAttrib[i]).name == (*ai)._name) { userDescr = true; break; } } if (!userDescr) custom.CreateEdgeAttribDescriptor(&(*ai)); } for (int i = 0; i < custom.edgeAttrib.size(); i++) { edgeProp.push_back(custom.edgeAttribProp[i]); edgeDescr.dataDescriptor.push_back(custom.edgeAttrib[i]); } } } //Face nameList.clear(); FaceType::Name(nameList); std::vector faceProp; ElementDescriptor faceDescr(NNP_FACE_ELEM); std::vector> faceIndex; std::vector> wedgeTexCoord; for (int i = 0; i < mesh.face.size(); i++) { faceIndex.push_back(std::vector()); for (int j = 0; j < mesh.face[i].VN(); j++) faceIndex.back().push_back(vcg::tri::Index(mesh, mesh.face[i].V(j))); } if (((bitMask & BitMask::IO_WEDGTEXCOORD) || (bitMask & BitMask::IO_WEDGTEXMULTI)) && vcg::tri::HasPerWedgeTexCoord(mesh)) { for (int i = 0; i < mesh.face.size(); i++) { wedgeTexCoord.push_back(vcg::ndim::Point<6, FaceTexScalar>()); for (int j = 0; j < 3; j++) { wedgeTexCoord.back()[j * 2] = mesh.face[i].WT(j).U(); wedgeTexCoord.back()[j * 2 + 1] = mesh.face[i].WT(j).V(); } } } if (nameList.size() > 0 && mesh.face.size() > 0) { if ((bitMask & BitMask::IO_FACEINDEX) && FaceType::HasVertexRef()) PushDescriportList, unsigned int, 0>(faceProp, faceDescr, NNP_FACE_VERTEX_LIST, &faceIndex[0]); if ((bitMask & BitMask::IO_FACEFLAGS) && vcg::tri::HasPerFaceFlags(mesh)) PushDescriport(faceProp, faceDescr, NNP_BITFLAG, &(*mesh.face.begin()).Flags()); if ((bitMask & BitMask::IO_FACECOLOR) && vcg::tri::HasPerFaceColor(mesh)) { if (ocfFaceMask & BitMask::IO_FACECOLOR) PushDescriport(faceProp, faceDescr, NNP_CRGBA, (*mesh.face.begin()).C().V()); else PushDescriport(faceProp, faceDescr, NNP_CRGBA, (*mesh.face.begin()).C().V()); } if ((bitMask & BitMask::IO_FACEQUALITY) && vcg::tri::HasPerFaceQuality(mesh)) { if (ocfFaceMask & BitMask::IO_FACEQUALITY) PushDescriport(faceProp, faceDescr, NNP_QUALITY, &(*mesh.face.begin()).Q()); else PushDescriport(faceProp, faceDescr, NNP_QUALITY, &(*mesh.face.begin()).Q()); } if ((bitMask & BitMask::IO_FACENORMAL) && vcg::tri::HasPerFaceNormal(mesh)) { if (ocfFaceMask & BitMask::IO_FACENORMAL) PushDescriport(faceProp, faceDescr, NNP_NXYZ, (*mesh.face.begin()).N().V()); else PushDescriport(faceProp, faceDescr, NNP_NXYZ, (*mesh.face.begin()).N().V()); } if ((bitMask & BitMask::IO_VERTCURVDIR) && vcg::tri::HasPerFaceCurvatureDir(mesh)) { if (ocfFaceMask & BitMask::IO_VERTCURVDIR) { PushDescriport(faceProp, faceDescr, NNP_K1, &(*mesh.face.begin()).K1()); PushDescriport(faceProp, faceDescr, NNP_K2, &(*mesh.face.begin()).K2()); PushDescriportList(faceProp, faceDescr, NNP_K1DIR, (*mesh.face.begin()).PD1().V()); PushDescriportList(faceProp, faceDescr, NNP_K2DIR, (*mesh.face.begin()).PD2().V()); } else { PushDescriport(faceProp, faceDescr, NNP_K1, &(*mesh.face.begin()).K1()); PushDescriport(faceProp, faceDescr, NNP_K2, &(*mesh.face.begin()).K2()); PushDescriportList(faceProp, faceDescr, NNP_K1DIR, (*mesh.face.begin()).PD1().V()); PushDescriportList(faceProp, faceDescr, NNP_K2DIR, (*mesh.face.begin()).PD2().V()); } } if (((bitMask & BitMask::IO_WEDGTEXCOORD) || (bitMask & BitMask::IO_WEDGTEXMULTI)) && vcg::tri::HasPerWedgeTexCoord(mesh)) PushDescriportList, FaceTexScalar, 6>(faceProp, faceDescr, NNP_FACE_WEDGE_TEX, (*wedgeTexCoord.begin()).V()); if ((bitMask & BitMask::IO_WEDGTEXMULTI) && vcg::tri::HasPerWedgeTexCoord(mesh)) { if (ocfFaceMask & BitMask::IO_VERTCURVDIR) PushDescriport(faceProp, faceDescr, NNP_TEXTUREINDEX, &(*mesh.face.begin()).WT(0).N()); else PushDescriport(faceProp, faceDescr, NNP_TEXTUREINDEX, &(*mesh.face.begin()).WT(0).N()); } if ((bitMask & BitMask::IO_WEDGCOLOR) && vcg::tri::HasPerWedgeColor(mesh)) { if (ocfFaceMask & BitMask::IO_WEDGCOLOR) PushDescriportList(faceProp, faceDescr, NNP_FACE_WEDGE_COLOR, (*mesh.face.begin()).WC(0).V()); else PushDescriportList(faceProp, faceDescr, NNP_FACE_WEDGE_COLOR, (*mesh.face.begin()).WC(0).V()); } if ((bitMask & BitMask::IO_WEDGNORMAL) && vcg::tri::HasPerWedgeNormal(mesh)) { if (ocfFaceMask & BitMask::IO_WEDGNORMAL) PushDescriportList(faceProp, faceDescr, NNP_FACE_WEDGE_NORMAL, (*mesh.face.begin()).WN(0).V()); else PushDescriportList(faceProp, faceDescr, NNP_FACE_WEDGE_NORMAL, (*mesh.face.begin()).WN(0).V()); } if ((bitMask & BitMask::IO_FACEATTRIB)) { std::set::iterator ai; int userSize = custom.faceAttrib.size(); for (ai = mesh.face_attr.begin(); ai != mesh.face_attr.end(); ++ai) { bool userDescr = false; for (int i = 0; i < userSize; i++) { if ((*custom.faceAttrib[i]).name == (*ai)._name) { userDescr = true; break; } } if (!userDescr) custom.CreateFaceAttribDescriptor(&(*ai)); } for (int i = 0; i < custom.faceAttrib.size(); i++) { faceProp.push_back(custom.faceAttribProp[i]); faceDescr.dataDescriptor.push_back(custom.faceAttrib[i]); } } } Info infoSave; infoSave.filename = filename; infoSave.binary = binary; PlyElement cameraElem(std::string("camera"), cameraProp, 1); PlyElement vertexElem(NNP_VERTEX_ELEM, vertexProp, mesh.vert.size()); PlyElement edgeElem(NNP_EDGE_ELEM, edgeProp, mesh.edge.size()); PlyElement faceElem(NNP_FACE_ELEM, faceProp, mesh.face.size()); infoSave.AddPlyElement(cameraElem); infoSave.AddPlyElement(vertexElem); infoSave.AddPlyElement(edgeElem); infoSave.AddPlyElement(faceElem); infoSave.textureFile = mesh.textures; std::vector meshDescr; meshDescr.push_back(&cameraDescr); meshDescr.push_back(&vertexDescr); meshDescr.push_back(&edgeDescr); meshDescr.push_back(&faceDescr); //Mesh attribute if ((bitMask & BitMask::IO_MESHATTRIB)) { CustomAttributeDescriptor::MapMeshAttribIter iter = custom.meshAttrib.begin(); CustomAttributeDescriptor::MapMeshAttribPropIter iterProp = custom.meshAttribProp.begin(); for (; iter != custom.meshAttrib.end(); iter++, iterProp++) { std::string name((*iter).first); PlyElement customElem(name, (*iterProp).second, custom.meshAttribCnt[(*iter).first]); infoSave.AddPlyElement(customElem); meshDescr.push_back(new ElementDescriptor(name)); meshDescr.back()->dataDescriptor = (*iter).second; } } bool flag = nanoply::SaveModel(infoSave.filename, meshDescr, infoSave); for (int i = 0; i < cameraDescr.dataDescriptor.size(); i++) delete cameraDescr.dataDescriptor[i]; for (int i = 0; i < vertexDescr.dataDescriptor.size(); i++) if (vertexDescr.dataDescriptor[i]->elem != NNP_UNKNOWN_ENTITY) delete vertexDescr.dataDescriptor[i]; for (int i = 0; i < edgeDescr.dataDescriptor.size(); i++) if (edgeDescr.dataDescriptor[i]->elem != NNP_UNKNOWN_ENTITY) delete edgeDescr.dataDescriptor[i]; for (int i = 0; i < faceDescr.dataDescriptor.size(); i++) if (faceDescr.dataDescriptor[i]->elem != NNP_UNKNOWN_ENTITY) delete faceDescr.dataDescriptor[i]; return flag; } static bool SaveModel(const char* filename, MeshType& mesh, unsigned int bitMask, bool binary) { CustomAttributeDescriptor custom; return SaveModel(filename, mesh, bitMask, custom, binary); } }; } #endif