44#include "OBJImporter.hh"
58 vertices_.push_back( _point );
60 return vertices_.size()-1;
66 if ( vertices_.size() > _index )
67 return vertices_[ _index ];
76 texCoords_.push_back( _coord );
78 return texCoords_.size()-1;
85 normals_.push_back( _normal );
87 return normals_.size()-1;
124 if((
unsigned int)_groupId >= triMeshes_.size()) {
125 std::cerr <<
"Error: Group does not exist!" << std::endl;
139#ifdef ENABLE_BSPLINECURVE_SUPPORT
145#ifdef ENABLE_BSPLINESURFACE_SUPPORT
152 std::cerr <<
"Error: Cannot add object. Type is unknown!" << std::endl;
161 return currentGroup_;
169 return polyMeshes_[currentGroup_]->mesh();
177 return triMeshes_[currentGroup_]->mesh();
182#ifdef ENABLE_BSPLINECURVE_SUPPORT
186 return bSplineCurves_[currentGroup_]->splineCurve();
193#ifdef ENABLE_BSPLINESURFACE_SUPPORT
197 return bSplineSurfaces_[currentGroup_]->splineSurface();
207 if (isTriangleMesh(_groupId)) {
210 TriMesh* curMesh = triMeshes_[_groupId]->mesh();
216 if(usedVertices_.size() <=
static_cast<size_t>(_groupId))
return;
218 for(
auto it : usedVertices_[_groupId]) {
220 if (it.first >= (
int)vertices_.size()) {
221 std::cerr <<
"Error: Vertex ID too large" << std::endl;
225 if (vertexMapTri_[_groupId].find(it.first) == vertexMapTri_[_groupId].end()) {
226 vertexMapTri_[_groupId].insert(std::pair<int, TriMesh::VertexHandle>(it.first, curMesh->
add_vertex((
TriMesh::Point)vertices_[it.first])));
230 }
else if (isPolyMesh(_groupId)) {
233 PolyMesh* curMesh = polyMeshes_[_groupId]->mesh();
239 if(usedVertices_.size() <=
static_cast<size_t>(_groupId))
return;
241 for(
auto it : usedVertices_[_groupId]) {
243 if (it.first >= (
int)vertices_.size()) {
244 std::cerr <<
"Error: Vertex ID too large" << std::endl;
248 if (vertexMapPoly_[_groupId].find(it.first) == vertexMapPoly_[_groupId].end()) {
249 vertexMapPoly_[_groupId].insert(std::pair<int, PolyMesh::VertexHandle>(it.first, curMesh->
add_vertex((
PolyMesh::Point)vertices_[it.first])));
265 if ( _texCoordID < (
int) texCoords_.size() ){
272 if ( vertexMapTri_[currentGroup_].find( _vh ) != vertexMapTri_[currentGroup_].end() )
273 currentTriMesh()->set_texcoord2D( vertexMapTri_[currentGroup_][_vh], texCoords_[ _texCoordID ] );
276 std::cerr <<
"Error: TexCoord ID too large" << std::endl;
284 if ( _texCoordID < (
int) texCoords_.size() ){
291 if ( vertexMapPoly_[currentGroup_].find( _vh ) != vertexMapPoly_[currentGroup_].end() )
292 currentPolyMesh()->set_texcoord2D( vertexMapPoly_[currentGroup_][_vh], texCoords_[ _texCoordID ] );
295 std::cerr <<
"Error: TexCoord ID too large" << std::endl;
310 if ( _normalID < (
int) normals_.size() )
312 if ( vertexMapTri_[currentGroup_].find( _index ) != vertexMapTri_[currentGroup_].end() )
314 TriMesh::VertexHandle vh = vertexMapTri_[currentGroup_][_index];
317 currentMesh->set_normal( vh , normal );
318 objectOptions_[ currentGroup_ ] |= NORMALS;
320 storedTriHENormals_[vh] = normal;
324 std::cerr <<
"Error: normal ID too large" << std::endl;
332 if ( _normalID < (
int) normals_.size() )
334 if ( vertexMapPoly_[currentGroup_].find( _index ) != vertexMapPoly_[currentGroup_].end() )
336 PolyMesh::VertexHandle vh = vertexMapPoly_[currentGroup_][_index];
339 currentMesh->set_normal( vh , normal );
340 objectOptions_[ currentGroup_ ] |= NORMALS;
342 storedPolyHENormals_[vh] = normal;
346 std::cerr <<
"Error: normal ID too large" << std::endl;
361 addedFacesTri_[currentGroup_].clear();
363 for (
unsigned int i=0; i < _indices.size(); i++){
365 if ( vertexMapTri_[currentGroup_].find( _indices[i] ) != vertexMapTri_[currentGroup_].end() ){
367 _outTriVertices.push_back( vertexMapTri_[currentGroup_][ _indices[i] ] );
370 std::cerr <<
"Error: cannot add face. undefined index (" << _indices[i] <<
")" << std::endl;
382 invalidFaces_[currentGroup_].push_back(_outTriVertices);
399 std::map<TriMesh::VertexHandle,TriMesh::Normal>::iterator iter = storedTriHENormals_.find(vh);
400 if (iter != storedTriHENormals_.end())
403 storedTriHENormals_.clear();
414 for (
unsigned int i=0; i < _indices.size(); i++){
416 if ( vertexMapPoly_[currentGroup_].find( _indices[i] ) != vertexMapPoly_[currentGroup_].end() ){
418 _outPolyVertices.push_back( vertexMapPoly_[currentGroup_][ _indices[i] ] );
421 std::cerr <<
"Error: cannot add face. undefined index (" << _indices[i] <<
")" << std::endl;
426 if(!vertexListIsManifold(_outPolyVertices)) {
427 std::cerr <<
"Face consists of multiple occurrences of the same vertex!" << std::endl;
435 invalidFaces_[currentGroup_].push_back(_outPolyVertices);
448 PolyMesh::VertexHandle vh = heh.to();
449 std::map<PolyMesh::VertexHandle,PolyMesh::Normal>::iterator iter = storedTriHENormals_.find(vh);
450 if (iter != storedTriHENormals_.end())
453 storedPolyHENormals_.clear();
466 std::vector< TriMesh::VertexHandle > triVertices;
467 std::vector< PolyMesh::VertexHandle > polyVertices;
468 addFace(_indices,fh,triVertices,polyVertices);
474bool OBJImporter::vertexListIsManifold(
const std::vector<PolyMesh::VertexHandle>& _vertices)
const {
476 std::set<PolyMesh::VertexHandle> check;
477 for(
auto v_it : _vertices) {
481 return (check.size() == _vertices.size());
491 std::vector< TriMesh::VertexHandle > triVertices;
492 std::vector< PolyMesh::VertexHandle > polyVertices;
493 if(!
addFace(_indices, fh, triVertices, polyVertices) || !fh.
is_valid())
509 while(
currentTriMesh()->to_vertex_handle(cur_heh) != triVertices[0] && cur_heh != end_heh )
512 for(
unsigned int i=0; i<_face_texcoords.size(); ++i)
514 if ( _face_texcoords[i] < (
int)texCoords_.size() ){
516 PolyMesh::TexCoord2D tex = OpenMesh::vector_cast<TriMesh::TexCoord2D>( texCoords_[ _face_texcoords[i] ] );
522 std::cerr <<
"Error: cannot set texture coordinates. undefined index." << std::endl;
534 if ( addedFacePoly_.is_valid() ) {
540 while(
currentPolyMesh()->to_vertex_handle(cur_heh) != polyVertices[0] && cur_heh != end_heh )
543 for(
unsigned int i=0; i<_face_texcoords.size(); ++i)
545 if ( _face_texcoords[i] < (
int)texCoords_.size() ){
547 PolyMesh::TexCoord2D tex = OpenMesh::vector_cast<PolyMesh::TexCoord2D>( texCoords_[ _face_texcoords[i] ] );
553 std::cerr <<
"Error: cannot set texture coordinates. undefined index." << std::endl;
570 if ( materials_.find( _materialName ) != materials_.end() ){
572 Material& mat = materials_[ _materialName ];
581 bool textureAllowed = ! ( objectOptions_[
currentGroup() ] & FORCE_NOTEXTURES );
583 if ( textureAllowed ){
586 if (!
currentTriMesh()->get_property_handle(indexProperty,TEXTUREINDEX) )
593 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ka());
598 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Kd());
603 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ks());
608 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ke());
618 float shininess = mat.Ns();
622 if (mat.has_illum()) {
627 for (
unsigned int i=0; i < addedFacesTri_[currentGroup_].size(); i++){
629 if ( mat.has_Kd() ) {
630 bool colorAllowed = ! ( objectOptions_[
currentGroup() ] & FORCE_NOCOLOR );
634 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Kd() );
642 currentTriMesh()->set_color(addedFacesTri_[currentGroup_][i], color );
647 bool textureAllowed = ! ( objectOptions_[
currentGroup() ] & FORCE_NOTEXTURES );
650 if ( mat.has_Texture() ) {
653 currentTriMesh()->property(indexProperty, addedFacesTri_[currentGroup_][i]) = mat.map_Kd_index();
658 currentTriMesh()->property(indexProperty, addedFacesTri_[currentGroup_][i]) = 0;
669 if ( materials_.find( _materialName ) != materials_.end() ){
671 Material& mat = materials_[ _materialName ];
680 bool textureAllowed = ! ( objectOptions_[
currentGroup() ] & FORCE_NOTEXTURES );
682 if ( textureAllowed ){
684 if (!
currentPolyMesh()->get_property_handle(indexProperty,TEXTUREINDEX) )
689 if ( mat.has_Kd() ) {
690 bool colorAllowed = ! ( objectOptions_[
currentGroup() ] & FORCE_NOCOLOR );
692 if (
currentPolyMesh()->has_face_colors() && colorAllowed && addedFacePoly_.is_valid() ){
694 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Kd() );
711 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ka());
716 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ks());
721 TriMesh::Color color = OpenMesh::color_cast< OpenMesh::Vec4f >(mat.Ke());
731 float shininess = mat.Ns();
735 if (mat.has_illum()) {
739 bool textureAllowed = ! ( objectOptions_[
currentGroup() ] & FORCE_NOTEXTURES );
742 if ( mat.has_Texture() ) {
744 if ( hasTexture(
currentGroup() ) && textureAllowed && addedFacePoly_.is_valid())
745 currentPolyMesh()->property(indexProperty, addedFacePoly_) = mat.map_Kd_index();
749 if ( hasTexture(
currentGroup() ) && textureAllowed && addedFacePoly_.is_valid())
762 bool isMesh = (objectOptions_[currentGroup_] & TRIMESH) | (objectOptions_[currentGroup_] & POLYMESH);
763 bool correctType = objectOptions_[currentGroup_] & _meshType;
765 if ( isMesh && !correctType ) {
766 ObjectOptions options = objectOptions_[currentGroup_];
772 options |= _meshType;
774 objectOptions_[currentGroup_] = options;
781bool OBJImporter::isTriangleMesh(
int _objectID){
782 return objectOptions_[ _objectID ] & TRIMESH;
787bool OBJImporter::isPolyMesh(
int _objectID){
788 return objectOptions_[ _objectID ] & POLYMESH;
793bool OBJImporter::isCurve(
int _objectID){
794 return objectOptions_[ _objectID ] & CURVE;
799bool OBJImporter::isSurface(
int _objectID){
800 return objectOptions_[ _objectID ] & SURFACE;
803bool OBJImporter::isNone(
int _objectID) {
804 return objectOptions_[ _objectID ] == NONE;
811 return objectOptions_[ _objectID ] & NORMALS;
816bool OBJImporter::hasTexture(
int _objectID){
818 return objectOptions_[ _objectID ] & TEXTURE;
823bool OBJImporter::hasTextureCoords(
int _objectID){
824 return objectOptions_[ _objectID ] & TEXCOORDS;
830 objectOptions_[ currentGroup_ ] |= _option;
835 objectOptions_[ _groupId ] |= _option;
841 return vertices_.size();
846unsigned int OBJImporter::n_normals(){
847 return normals_.size();
852unsigned int OBJImporter::n_texCoords(){
853 return texCoords_.size();
859 return groupNames_.size();
869 if(triMeshes_[_groupId] != NULL)
return triMeshes_[_groupId];
870 else if(polyMeshes_[_groupId] != NULL)
return polyMeshes_[_groupId];
871#ifdef ENABLE_BSPLINECURVE_SUPPORT
872 else if(bSplineCurves_[_groupId] != NULL)
return bSplineCurves_[_groupId];
874#ifdef ENABLE_BSPLINESURFACE_SUPPORT
875 else if(bSplineSurfaces_[_groupId] != NULL)
return bSplineSurfaces_[_groupId];
895void OBJImporter::setPath(QString _path){
903 while((
unsigned int)currentGroup_ >= objectOptions_.size()) {
904 objectOptions_.push_back(NONE);
907 objectOptions_[currentGroup_] = _options;
913 return objectOptions_.empty();
921 if (_id >= objectOptions_.size())
924 return objectOptions_[_id] & _option;
939int OBJImporter::addGroup(
const QString& _groupName) {
941 QString group = _groupName.trimmed();
942 int id = groupId(group);
944 groupNames_.push_back(group);
945 vertexMapTri_.push_back(std::map<int,TriMesh::VertexHandle>());
946 vertexMapPoly_.push_back(std::map<int,TriMesh::VertexHandle>());
947 invalidFaces_.push_back(std::vector< OMVHandles >());
948 addedFacesTri_.push_back(std::vector< TriMesh::FaceHandle>());
950 triMeshes_.push_back(NULL);
951 polyMeshes_.push_back(NULL);
952#ifdef ENABLE_BSPLINECURVE_SUPPORT
953 bSplineCurves_.push_back(NULL);
955#ifdef ENABLE_BSPLINESURFACE_SUPPORT
956 bSplineSurfaces_.push_back(NULL);
958 return groupNames_.size() - 1;
965int OBJImporter::groupId(
const QString& _groupName)
const {
967 for(
unsigned int i = 0; i < groupNames_.size(); ++i) {
968 if(groupNames_[i] == _groupName.trimmed())
return i;
975const QString OBJImporter::groupName(
const int _grpId)
const {
977 if((
unsigned int)_grpId < groupNames_.size()) {
978 return groupNames_[_grpId];
985void OBJImporter::setGroupName(
const int _grp,
const QString& _name) {
987 if((
unsigned int)_grp >= groupNames_.size())
return;
989 groupNames_[_grp] = _name;
994void OBJImporter::setCurrentGroup(
const int _current) {
996 currentGroup_ = _current;
1003 return currentGroup_;
1012 if(invalidFaces_[currentGroup_].empty())
return;
1019 for(std::vector<OMVHandles>::iterator it = invalidFaces_[currentGroup_].begin();
1020 it != invalidFaces_[currentGroup_].end(); ++it) {
1022 OMVHandles& vhandles = *it;
1025 for (
unsigned int j = 0; j < vhandles.size(); ++j)
1034 currentTriMesh()->status(vhandles[j]).set_fixed_nonmanifold(
true);
1047 for(
auto fe_it : fh.
edges()) {
1058 for(std::vector<OMVHandles>::iterator it = invalidFaces_[currentGroup_].begin();
1059 it != invalidFaces_[currentGroup_].end(); ++it) {
1061 OMVHandles& vhandles = *it;
1064 for (
unsigned int j = 0; j < vhandles.size(); ++j)
1086 for(
auto fe_it : fh.
edges()) {
1094 invalidFaces_[currentGroup_].clear();
1099#ifdef ENABLE_BSPLINECURVE_SUPPORT
1100void OBJImporter::setCurveGroupId(
const unsigned int _count,
const int _id) {
1101 curvesMap_[_count] = _id;
1107#ifdef ENABLE_BSPLINECURVE_SUPPORT
1108int OBJImporter::getCurveGroupId(
const unsigned int _count) {
1109 return curvesMap_[_count];
1115#ifdef ENABLE_BSPLINECURVE_SUPPORT
1116void OBJImporter::setCurveParentId(
const int _curveGroup,
const int _parentGroup) {
1117 curveParentGroupMap_[_curveGroup] = _parentGroup;
1123#ifdef ENABLE_BSPLINECURVE_SUPPORT
1124int OBJImporter::getCurveParentId(
const int _curveGroup) {
1125 return curveParentGroupMap_[_curveGroup];
1131#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1132void OBJImporter::setSurfaceGroupId(
const unsigned int _count,
const int _id) {
1133 surfacesMap_[_count] = _id;
1139#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1140int OBJImporter::getSurfaceGroupId(
const unsigned int _count) {
1141 return surfacesMap_[_count];
1147#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1148void OBJImporter::setSurfaceParentId(
const int _surfaceGroup,
const int _parentGroup) {
1149 surfaceParentGroupMap_[_surfaceGroup] = _parentGroup;
1155#ifdef ENABLE_BSPLINESURFACE_SUPPORT
1156int OBJImporter::getSurfaceParentId(
const int _surfaceGroup) {
1157 return surfaceParentGroupMap_[_surfaceGroup];
1166 if (_objectID >= usedMaterials_.size())
1167 return std::vector<std::string>();
1169 return usedMaterials_[ _objectID ];
1174void OBJImporter::useMaterial( std::string _materialName ){
1176 while( (
int)usedMaterials_.size() - 1 <
currentGroup() )
1177 usedMaterials_.push_back( std::vector<std::string>() );
1180 for (
unsigned int i=0; i < usedMaterials_[
currentGroup() ].size(); i++ )
1181 if ( usedMaterials_[
currentGroup() ][i] == _materialName )
1184 usedMaterials_[
currentGroup() ].push_back( _materialName );
1193 while(currentGroup_ >= (
int)usedVertices_.size()) {
1194 usedVertices_.push_back(std::map<int,VertexHandle>());
1197 usedVertices_[currentGroup_].insert(std::pair<int,VertexHandle>(_vertex_index,-1));
void set_diffuse_color(const Vec4f &_d)
set the diffuse color.
void set_specular_color(const Vec4f &_s)
set the specular color
void set_refractive(bool _r)
set refractive flag
void set_indexOfRefraction(double _m)
set index of refraction
void set_ambient_color(const Vec4f &_a)
set the ambient color.
void set_emission(const Vec4f &_c)
set emission ( same as set_base_color(const Vec4f& _c) )
void set_shininess(float _s)
set shininess
MaterialNode * materialNode()
get a pointer to the materialnode
virtual void setName(QString _name)
path to the file from which the object is loaded ( defaults to "." )
unsigned int groupCount()
Number of groups currently stored in the importer.
Vec3d vertex(unsigned int _index)
get vertex with given index
void addMaterial(std::string _materialName)
Add a material.
void setDegreeV(int _degree)
set degree V direction
void setVertexTexCoord(VertexHandle _vh, int _texCoordID)
set vertex texture coordinate
unsigned int n_vertices()
Global Properties.
void useVertex(int _vertex_index)
used vertices
void setObjectOptions(ObjectOptions _options)
void addUsedVertices(int _groupId)
add all vertices that are used to the mesh (in correct order)
void addFace(const VHandles &_indices)
add a face with indices _indices refering to vertices
int addTexCoord(const Vec2f &_coord)
add texture coordinates
VertexHandle addVertex(const Vec3d &_point)
add a vertex with coordinate _point
int degreeU()
get current degree
void setDegreeU(int _degree)
set degree
bool noOptions()
Return true if the importer has no options stored.
QString path()
Path of the OBJ file.
void forceMeshType(ObjectOptions _meshType)
force all meshes to be opened with specific type
int addNormal(const Vec3d &_normal)
add a normal
void setNormal(int _index, int _normalID)
set vertex normal
bool hasOption(unsigned int _id, ObjectOptions _option)
check if object with given id has given option
BaseObject * object(int _groupId)
return object for the given group
void setObjectName(int _objectID, QString _name)
change the name of an object
TriMesh * currentTriMesh()
get a pointer to the active triMesh
void setOption(ObjectOptionsE _option)
Set Object Option.
void setObject(BaseObject *_object, int _groupId)
add an object
MaterialList & materials()
return all loaded materials
int degreeV()
get current degree
const std::vector< std::string > usedMaterials(unsigned int _objectID)
used materials
bool hasNormals(int _objectID)
Query Object Options.
int currentGroup()
Get the id of the current group.
PolyMesh * currentPolyMesh()
get a pointer to the active polyMesh
~OBJImporter()
base class needs virtual destructor
bool is_valid() const
The handle is valid iff the index is not negative.
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Kernel::Normal Normal
Normal type.
Kernel::TexCoord2D TexCoord2D
TexCoord2D type.
SmartVertexHandle add_vertex(const Point _p)
Kernel::FaceHandle FaceHandle
Scalar type.
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Kernel::Point Point
Coordinate type.
Kernel::Color Color
Color type.
BSplineSurfaceObject * bsplineSurfaceObject(BaseObjectData *_object)
Cast an BaseObject to a BSplineSurfaceObject if possible.
TriMeshObject * triMeshObject(BaseObjectData *_object)
Cast an BaseObject to a TriMeshObject if possible.
PolyMeshObject * polyMeshObject(BaseObjectData *_object)
Cast an BaseObject to a PolyMeshObject if possible.
BSplineCurveObject * bsplineCurveObject(BaseObjectData *_object)
Cast an BaseObject to a BSplineCurveObject if possible.
BaseObjectData * baseObjectData(BaseObject *_object)
Cast an BaseObject to a BaseObjectData if possible.
Handle for a face entity.
PolyConnectivity::ConstFaceEdgeRange edges() const
Returns a range of edges of the face (PolyConnectivity::fv_range())
PolyConnectivity::ConstFaceHalfedgeRange halfedges() const
Returns a range of halfedges of the face (PolyConnectivity::fh_range())