From 6aa2b93c62060abc9aab6cdb96df475371556571 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Mon, 27 Jun 2016 10:57:04 +0200 Subject: [PATCH 01/91] Updated gitignore to ignore html folder generated by oxygen --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4f22965f..d2566d9f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ debug/ release/ *-debug/ *-release/ +/docs/Doxygen/html/ \ No newline at end of file From cd3f0461bfde17630354a4cb82c00a039128d9f4 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Mon, 27 Jun 2016 11:12:33 +0200 Subject: [PATCH 02/91] updated documentation to reflect the github transfer --- apps/tridecimator/tridecimator.cpp | 1 - docs/Doxygen/install.dxy | 23 +++++++++-------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/apps/tridecimator/tridecimator.cpp b/apps/tridecimator/tridecimator.cpp index 6f4bc513..51c66bec 100644 --- a/apps/tridecimator/tridecimator.cpp +++ b/apps/tridecimator/tridecimator.cpp @@ -73,7 +73,6 @@ void Usage() "---------------------------------\n" " TriDecimator 1.0 \n" " http://vcg.isti.cnr.it\n" - " http://vcg.sourceforge.net\n" " release date: " __DATE__ "\n---------------------------------\n\n" "Copyright 2003-2016 Visual Computing Lab I.S.T.I. C.N.R.\n" diff --git a/docs/Doxygen/install.dxy b/docs/Doxygen/install.dxy index a1831cfb..5d72f675 100644 --- a/docs/Doxygen/install.dxy +++ b/docs/Doxygen/install.dxy @@ -3,33 +3,28 @@ Installation and folder structure ================ -VCG Lib uses a SVN repository hosted by sourceforge. -The main project page of the library is http://sourceforge.net/projects/vcg/ +VCG Lib uses a git repository hosted by github. +The main project page of the library is http://github.com/cnr-isti-vclab/vcglib/ -To get the right subset of the svn trunk in the devel folder you should issue the following svn command: +The stable version of the library are available under the release page +https://github.com/cnr-isti-vclab/vcglib/releases - svn checkout svn://svn.code.sf.net/p/vcg/code/trunk/vcglib vcglib +To get the development version of library clone the 'devel' branch of the library : -Windows users with tortoisesvn (http://www.tortoisesvn.net) installed should + git clone -b devel https://github.com/cnr-isti-vclab/vcglib.git -1. create a folder named vcglib. -2. right-click in the newly created vcglib folder and choose SVN Checkout -3. put in the first parameter: svn://svn.code.sf.net/p/vcg/code/trunk/vcglib -4. press ok and wait, it should start to check out the last revision of the whole tree. Folder Structure ================ -VCG Lib is mostly made of header files (and its core part it's only header files). +VCGLib is mostly made of header files (and its core part it's only header files) with no external dependencies. Just download the tarball from here and uncompress it in a folder, e.g. named vcg, inside you compiler "include" directory. -Afterwards, you have to just include the file you need. +Afterwards, you have to just include the files you need as shown in the apps/sample examples. Inside vcg folder you will find 5 sub-folders: - `vcg`: this is the core of the library, where all the algorithms and data structures are defined. This part is pure, quite heavily templated, C++ code with STL support for common data structures and algorithms. You will not find a single include from here to anything else than standard libraries. Note that core part is made of header files (.h files) only. - `wrap`: here you will find the wrapping of VCG concepts towards specific needs/contexts/libraries. For example you will find all the code to import/export meshes from the hard disk in many formats, or the routines for rendering triangle meshes with OpenGL, supports for common GUI tools like a trackball, and so on.. -- `apps`: this folder contains the command line applications developed with the VCG Lib. Many (much more) examples can be found in MeshLab. The apps/simple directory contains a sub-collection of very basic apps. A good starting point for beginners! +- `apps`: this folder contains the command line applications developed with the VCG Lib. Many (much more) examples can be found in MeshLab. The apps/sample directory contains a sub-collection of very basic apps. A good starting point for beginners! - `docs`: documentation lives here (including this tutorial) - `eigenlib` a copy of the latest stable version of the eigen library for linear algebra ( http://http://eigen.tuxfamily.org/ ). VCGlib relies on eigen for all the advanced matrix processing. - -You can browse the svn tree on the sourceforge page http://sourceforge.net/p/vcg/code/HEAD/tree/trunk/vcglib/ */ From 9194ade7e55a32202b24a1383a4f41a3152ea3f0 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Wed, 29 Jun 2016 12:08:20 +0200 Subject: [PATCH 03/91] Added intermediate files generated by emscripten --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d2566d9f..caf98bf3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,7 @@ debug/ release/ *-debug/ *-release/ -/docs/Doxygen/html/ \ No newline at end of file +/docs/Doxygen/html/ + +# Intermediate Files +*.bc \ No newline at end of file From 8374dd97e5cb3762741e93677a2b892629e2efcd Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Wed, 29 Jun 2016 14:19:20 +0200 Subject: [PATCH 04/91] Bug Fixing for the Rendering System --- wrap/gl/gl_mesh_attributes_info.h | 16 ++-- ..._mesh_attributes_multi_viewer_bo_manager.h | 79 +++++++++++-------- ..._mesh_attributes_multi_viewer_bo_manager.h | 2 +- 3 files changed, 54 insertions(+), 43 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_info.h b/wrap/gl/gl_mesh_attributes_info.h index 53a32e59..77e04ac8 100644 --- a/wrap/gl/gl_mesh_attributes_info.h +++ b/wrap/gl/gl_mesh_attributes_info.h @@ -2,7 +2,7 @@ * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * -* Copyright(C) 2004-2016 \/)\/ * +* Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -65,7 +65,7 @@ namespace vcg ATT_NAMES(unsigned int att) { - if (att >= ATT_NAMES::enumArity()) + if ((att < ATT_VERTPOSITION) || (att >= ATT_NAMES::enumArity())) throw Exception("Out of range value\n"); else _val = att; @@ -119,9 +119,9 @@ namespace vcg class RenderingAtts { public: - RenderingAtts() + RenderingAtts(bool defaultvalue = false) { - reset(); + reset(defaultvalue); } RenderingAtts(const RenderingAtts& att) @@ -174,12 +174,12 @@ namespace vcg return _atts[ind]; } - void reset() + void reset(bool defaultvalue = false) { //delete[] _atts; //_atts = new bool[ATT_NAMES_DERIVED_CLASS::enumArity()]; for(unsigned int ii = 0;ii < ATT_NAMES_DERIVED_CLASS::enumArity();++ii) - _atts[ii] = false; + _atts[ii] = defaultvalue; } static RenderingAtts unionSet(const RenderingAtts& a,const RenderingAtts& b) @@ -309,7 +309,7 @@ namespace vcg INT_ATT_NAMES(unsigned int att) :ATT_NAMES() { - if (att >= INT_ATT_NAMES::enumArity()) + if ((att < INT_ATT_NAMES::ATT_VERTPOSITION) || (att >= INT_ATT_NAMES::enumArity())) throw Exception("Out of range value\n"); else _val = att; @@ -429,4 +429,4 @@ namespace vcg }; } -#endif +#endif \ No newline at end of file diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index 7d245569..c1b34510 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -2,7 +2,7 @@ * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * -* Copyright(C) 2004-2016 \/)\/ * +* Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * @@ -426,6 +426,8 @@ namespace vcg glPopMatrix(); glPopAttrib(); + glFlush(); + glFinish(); } bool isBORenderingAvailable() const @@ -531,9 +533,9 @@ namespace vcg case(INT_ATT_NAMES::ATT_WEDGETEXTURE): return vcg::tri::HasPerWedgeTexCoord(_mesh); case(INT_ATT_NAMES::ATT_VERTINDICES): - return true; + return (_mesh.VN() != 0) && (_mesh.FN() != 0); case(INT_ATT_NAMES::ATT_EDGEINDICES): - return vcg::tri::HasPerVertexFlags(_mesh); + return vcg::tri::HasPerVertexFlags(_mesh) || ((_mesh.VN() != 0) && (_mesh.FN() == 0) && (_mesh.EN() == 0)); default: return false; } @@ -557,7 +559,7 @@ namespace vcg { //If a primitive_modality is not rendered (== no att_VERTPOSITION) all the referred attributes by this view can be eventually deallocated IF they are not used //by some other rendered primitive - //the vertindices is, as usual a diffrent case + //the vertindices is, as usual, a different case if (it->second._intatts[size_t(pm)][INT_ATT_NAMES::ATT_VERTPOSITION]) meaningfulrequiredbyatleastoneview = InternalRendAtts::unionSet(meaningfulrequiredbyatleastoneview,it->second._intatts[size_t(pm)]); else @@ -565,12 +567,16 @@ namespace vcg } } bool thereisreplicatedview = InternalRendAtts::replicatedPipelineNeeded(meaningfulrequiredbyatleastoneview); - meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_VERTINDICES] = !thereisreplicatedview; + meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_VERTINDICES] &= !thereisreplicatedview; InternalRendAtts reallyuseless = InternalRendAtts::complementSet(probabilyuseless,meaningfulrequiredbyatleastoneview); bool switchreplicatedindexed = (!InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt) && thereisreplicatedview) || (InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt) && !thereisreplicatedview); + /*in some way the vertices number changed. If i use the indexed pipeline i have to deallocate/allocate/update the vertex indices*/ + bool numvertchanged = boExpectedSize(INT_ATT_NAMES::ATT_VERTPOSITION,thereisreplicatedview) != _bo[INT_ATT_NAMES::ATT_VERTPOSITION]->_size; + bool vertindforcedupdate = numvertchanged && meaningfulrequiredbyatleastoneview[INT_ATT_NAMES::ATT_VERTINDICES]; + InternalRendAtts probablytoallocate = InternalRendAtts::complementSet(meaningfulrequiredbyatleastoneview,_currallocatedboatt); InternalRendAtts probablytodeallocate = InternalRendAtts::complementSet(_currallocatedboatt,meaningfulrequiredbyatleastoneview); for(unsigned int ii = 0;ii < INT_ATT_NAMES::enumArity();++ii) @@ -588,8 +594,11 @@ namespace vcg tobedeallocated[boname] = (notempty && !hasmeshattribute) || (notempty && probablytodeallocate[boname]) || (notempty && reallyuseless[boname]) || - (notempty && (_bo[boname]->_size != sz) && meaningfulrequiredbyatleastoneview[boname]); - tobeallocated[boname] = (hasmeshattribute && (sz > 0) && (sz != _bo[boname]->_size) && meaningfulrequiredbyatleastoneview[boname]) || (hasmeshattribute && (sz > 0) && probablytoallocate[boname]); + (notempty && (_bo[boname]->_size != sz) && meaningfulrequiredbyatleastoneview[boname]) || + (notempty && (boname == INT_ATT_NAMES::ATT_VERTINDICES) && (vertindforcedupdate)); + tobeallocated[boname] = (hasmeshattribute && (sz > 0) && (sz != _bo[boname]->_size) && meaningfulrequiredbyatleastoneview[boname]) || + (hasmeshattribute && (sz > 0) && probablytoallocate[boname]) || + (hasmeshattribute && (boname == INT_ATT_NAMES::ATT_VERTINDICES) && (vertindforcedupdate)); tobeupdated[boname] = tobeallocated[boname] || (hasmeshattribute && (sz > 0) && !(isvalid) && meaningfulrequiredbyatleastoneview[boname]); } else @@ -1290,14 +1299,14 @@ namespace vcg glPushAttrib(GL_ALL_ATTRIB_BITS); bool isgloptsvalid = (glopts != NULL); - - if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL]) || (req[INT_ATT_NAMES::ATT_FACENORMAL])) - { - glEnable(GL_LIGHTING); - } - else if (isgloptsvalid && glopts->_persolid_noshading) + + if (isgloptsvalid && glopts->_persolid_noshading) glDisable(GL_LIGHTING); - + else + if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL]) || (req[INT_ATT_NAMES::ATT_FACENORMAL])) + { + glEnable(GL_LIGHTING); + } glEnable(GL_COLOR_MATERIAL); if ((isgloptsvalid) && (glopts->_persolid_fixed_color_enabled)) @@ -1332,14 +1341,14 @@ namespace vcg bool isgloptsvalid = (glopts != NULL); - if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL])) - { - glEnable(GL_LIGHTING); - } - else if (isgloptsvalid && glopts->_perwire_noshading) + if (isgloptsvalid && glopts->_perwire_noshading) glDisable(GL_LIGHTING); - - + else + if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL])) + { + glEnable(GL_LIGHTING); + } + glEnable(GL_COLOR_MATERIAL); if ((isgloptsvalid) && (glopts->_perwire_fixed_color_enabled)) glColor(glopts->_perwire_fixed_color); @@ -1547,12 +1556,14 @@ namespace vcg bool isgloptsvalid = (glopts != NULL); - if ((!isgloptsvalid) || req[INT_ATT_NAMES::ATT_VERTNORMAL]) - { - glEnable(GL_LIGHTING); - } - else if (isgloptsvalid && glopts->_perpoint_noshading) + + if (isgloptsvalid && glopts->_perpoint_noshading) glDisable(GL_LIGHTING); + else + if ((!isgloptsvalid) || req[INT_ATT_NAMES::ATT_VERTNORMAL]) + { + glEnable(GL_LIGHTING); + } glEnable(GL_COLOR_MATERIAL); if ((isgloptsvalid) && ((glopts->_perpoint_fixed_color_enabled) || (glopts->_perpoint_mesh_color_enabled))) @@ -1651,13 +1662,13 @@ namespace vcg glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); - if ((!isgloptsvalid) || req[INT_ATT_NAMES::ATT_VERTNORMAL]) - { - glEnable(GL_LIGHTING); - } - else if (isgloptsvalid && glopts->_perwire_noshading) + if (isgloptsvalid && glopts->_perwire_noshading) glDisable(GL_LIGHTING); - + else + if ((!isgloptsvalid) || (req[INT_ATT_NAMES::ATT_VERTNORMAL])) + { + glEnable(GL_LIGHTING); + } bool colordefinedenabled = (isgloptsvalid) && ((glopts->_perwire_fixed_color_enabled) || (glopts->_perwire_mesh_color_enabled)); @@ -1910,7 +1921,7 @@ namespace vcg void setBufferPointer( INT_ATT_NAMES boname) const { unsigned int ii = boname; - if (ii >= INT_ATT_NAMES::enumArity()) + if ((ii < INT_ATT_NAMES::ATT_VERTPOSITION) || (ii >= INT_ATT_NAMES::enumArity())) return; GLBufferObject* cbo = _bo[ii]; if (cbo == NULL) @@ -1948,7 +1959,7 @@ namespace vcg void disableClientState( INT_ATT_NAMES boname,const RendAtts& req) const { - if (boname >= INT_ATT_NAMES::enumArity()) + if ((boname < INT_ATT_NAMES::ATT_VERTPOSITION) || (boname >= INT_ATT_NAMES::enumArity())) return; switch(boname) diff --git a/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h b/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h index ecd7e8e7..b1aede33 100644 --- a/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h @@ -113,7 +113,7 @@ namespace vcg vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::setDebugMode(activatedebugmodality); } - void getLog(vcg::GLMeshAttributesInfo::DebugInfo& info) + void getLog(DebugInfo& info) { QWriteLocker locker(&_lock); vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::getLog(info); From 18c30b9d1726c3bd946809d69ae4d99a45653409 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Wed, 29 Jun 2016 14:35:17 +0200 Subject: [PATCH 05/91] Updated the file preamble --- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index c1b34510..e629f5ed 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -2,7 +2,7 @@ * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * -* Copyright(C) 2004 \/)\/ * +* Copyright(C) 2004-2016 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * From 0207d2b0c59f546e21c1ace9c756779ab53da7c0 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Wed, 29 Jun 2016 15:06:46 +0200 Subject: [PATCH 06/91] removed useless code generating warnings --- wrap/gl/gl_mesh_attributes_info.h | 2 +- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_info.h b/wrap/gl/gl_mesh_attributes_info.h index 77e04ac8..49fd2ce3 100644 --- a/wrap/gl/gl_mesh_attributes_info.h +++ b/wrap/gl/gl_mesh_attributes_info.h @@ -309,7 +309,7 @@ namespace vcg INT_ATT_NAMES(unsigned int att) :ATT_NAMES() { - if ((att < INT_ATT_NAMES::ATT_VERTPOSITION) || (att >= INT_ATT_NAMES::enumArity())) + if (att >= INT_ATT_NAMES::enumArity()) throw Exception("Out of range value\n"); else _val = att; diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index e629f5ed..9201e39e 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -1921,7 +1921,7 @@ namespace vcg void setBufferPointer( INT_ATT_NAMES boname) const { unsigned int ii = boname; - if ((ii < INT_ATT_NAMES::ATT_VERTPOSITION) || (ii >= INT_ATT_NAMES::enumArity())) + if (ii >= INT_ATT_NAMES::enumArity()) return; GLBufferObject* cbo = _bo[ii]; if (cbo == NULL) @@ -1959,7 +1959,7 @@ namespace vcg void disableClientState( INT_ATT_NAMES boname,const RendAtts& req) const { - if ((boname < INT_ATT_NAMES::ATT_VERTPOSITION) || (boname >= INT_ATT_NAMES::enumArity())) + if (boname >= INT_ATT_NAMES::enumArity()) return; switch(boname) From 49f49efaf3c2d81cea9cbc5fccd887ba7b694526 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 30 Jun 2016 09:39:22 +0200 Subject: [PATCH 07/91] Small changes to allow the clang compilation of meshlab --- wrap/gl/gl_mesh_attributes_info.h | 4 ++-- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 3 ++- .../qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_info.h b/wrap/gl/gl_mesh_attributes_info.h index 49fd2ce3..b3fe0cdf 100644 --- a/wrap/gl/gl_mesh_attributes_info.h +++ b/wrap/gl/gl_mesh_attributes_info.h @@ -65,7 +65,7 @@ namespace vcg ATT_NAMES(unsigned int att) { - if ((att < ATT_VERTPOSITION) || (att >= ATT_NAMES::enumArity())) + if (att >= ATT_NAMES::enumArity()) throw Exception("Out of range value\n"); else _val = att; @@ -429,4 +429,4 @@ namespace vcg }; } -#endif \ No newline at end of file +#endif diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index 9201e39e..8dee6ed9 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -880,7 +880,8 @@ namespace vcg if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTINDICES]) { - size_t tsz = _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType() * chunksize; + + //size_t tsz = _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType() * chunksize; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_bohandle); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,chunkingpu * facechunk * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType(),_bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType() * chunksize,&ti[0]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h b/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h index b1aede33..82333932 100644 --- a/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h @@ -113,7 +113,7 @@ namespace vcg vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::setDebugMode(activatedebugmodality); } - void getLog(DebugInfo& info) + void getLog(GLMeshAttributesInfo::DebugInfo& info) { QWriteLocker locker(&_lock); vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::getLog(info); From febc30581adbdee46a8d32a15a2a1d4a1d929d7e Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Fri, 1 Jul 2016 10:05:50 +0200 Subject: [PATCH 08/91] - removed "per point fixed color provides same color of the per mesh color" bug --- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index 8dee6ed9..0c118367 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -880,8 +880,6 @@ namespace vcg if (attributestobeupdated[INT_ATT_NAMES::ATT_VERTINDICES]) { - - //size_t tsz = _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType() * chunksize; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_bohandle); glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,chunkingpu * facechunk * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType(),_bo[INT_ATT_NAMES::ATT_VERTINDICES]->_components * _bo[INT_ATT_NAMES::ATT_VERTINDICES]->getSizeOfGLType() * chunksize,&ti[0]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -1568,7 +1566,10 @@ namespace vcg glEnable(GL_COLOR_MATERIAL); if ((isgloptsvalid) && ((glopts->_perpoint_fixed_color_enabled) || (glopts->_perpoint_mesh_color_enabled))) - glColor(glopts->_perpoint_fixed_color); + if (glopts->_perpoint_fixed_color_enabled) + glColor(glopts->_perpoint_fixed_color); + else + glColor(glopts->_permesh_color); if (req[INT_ATT_NAMES::ATT_VERTCOLOR]) From 40073ddfd1280fe4c636c921777384cda5d9b801 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Sun, 3 Jul 2016 13:55:33 +0200 Subject: [PATCH 09/91] removed mesh color bug --- .../gl_mesh_attributes_multi_viewer_bo_manager.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index 0c118367..c4b1ba66 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -59,8 +59,6 @@ namespace vcg bool _perpoint_mesh_color_enabled; bool _perwire_mesh_color_enabled; bool _persolid_mesh_color_enabled; - - Color4b _permesh_color; bool _perpoint_noshading; bool _perwire_noshading; @@ -91,8 +89,6 @@ namespace vcg _perpoint_mesh_color_enabled = false; _perwire_mesh_color_enabled = false; - _permesh_color = Color4b(Color4d::Magenta); - _perpoint_dot_enabled = false; _perpoint_noshading = false; @@ -136,8 +132,6 @@ namespace vcg _perwire_fixed_color_enabled = opts._perwire_fixed_color_enabled; _persolid_fixed_color_enabled = opts._persolid_fixed_color_enabled; - _permesh_color = opts._permesh_color; - _perbbox_mesh_color_enabled = opts._perbbox_mesh_color_enabled; _perpoint_mesh_color_enabled = opts._perpoint_mesh_color_enabled; _perwire_mesh_color_enabled = opts._perwire_mesh_color_enabled; @@ -1313,7 +1307,8 @@ namespace vcg else { if ((isgloptsvalid) && (glopts->_persolid_mesh_color_enabled)) - glColor(glopts->_permesh_color); + glColor(_mesh.C()); + else { if ((req[INT_ATT_NAMES::ATT_VERTCOLOR]) || (req[INT_ATT_NAMES::ATT_FACECOLOR])) glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); @@ -1354,7 +1349,8 @@ namespace vcg else { if ((isgloptsvalid) && (glopts->_perwire_mesh_color_enabled)) - glColor(glopts->_permesh_color); + glColor(_mesh.C()); + else { if (req[INT_ATT_NAMES::ATT_VERTCOLOR]) glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); @@ -1569,7 +1565,7 @@ namespace vcg if (glopts->_perpoint_fixed_color_enabled) glColor(glopts->_perpoint_fixed_color); else - glColor(glopts->_permesh_color); + glColor(_mesh.C()); if (req[INT_ATT_NAMES::ATT_VERTCOLOR]) @@ -1784,7 +1780,7 @@ namespace vcg else { if ((isgloptsvalid) && (glopts->_perbbox_mesh_color_enabled)) - glColor(glopts->_permesh_color); + glColor(_mesh.C()); else glColor(vcg::Color4b(vcg::Color4b::White)); } From 59ffcd0e552ebc5fbf365a77a5cbb66da4f17551 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Tue, 12 Jul 2016 15:19:07 +0200 Subject: [PATCH 10/91] removed GL_TYPE_NM class from trimesh.h file --- wrap/gl/gl_type_name.h | 41 +++++++++++++++++++++++++++++++++++++++++ wrap/gl/trimesh.h | 22 +++------------------- 2 files changed, 44 insertions(+), 19 deletions(-) create mode 100644 wrap/gl/gl_type_name.h diff --git a/wrap/gl/gl_type_name.h b/wrap/gl/gl_type_name.h new file mode 100644 index 00000000..f56f24b2 --- /dev/null +++ b/wrap/gl/gl_type_name.h @@ -0,0 +1,41 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004-2016 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +namespace vcg +{ + template + class GL_TYPE_NM + {public: + static GLenum SCALAR() { assert(0); return 0;} + }; + template <> class GL_TYPE_NM + { public: + typedef GLfloat ScalarType; + static GLenum SCALAR() { return GL_FLOAT; } + }; + template <> class GL_TYPE_NM + {public: + typedef GLdouble ScalarType; + static GLenum SCALAR() { return GL_DOUBLE; } + }; +} \ No newline at end of file diff --git a/wrap/gl/trimesh.h b/wrap/gl/trimesh.h index deba3b37..43365152 100644 --- a/wrap/gl/trimesh.h +++ b/wrap/gl/trimesh.h @@ -34,26 +34,10 @@ #include #include #include +#include - -namespace vcg { - - template - class GL_TYPE_NM - {public: - static GLenum SCALAR() { assert(0); return 0;} - }; - template <> class GL_TYPE_NM - { public: - typedef GLfloat ScalarType; - static GLenum SCALAR() { return GL_FLOAT; } - }; - template <> class GL_TYPE_NM - {public: - typedef GLdouble ScalarType; - static GLenum SCALAR() { return GL_DOUBLE; } - }; - +namespace vcg +{ //template <> GL_TYPE::SCALAR() { return GL_DOUBLE; } // classe base di glwrap usata solo per poter usare i vari drawmode, normalmode senza dover From bdec7f527c56ff91fe7d159d40fd8c21e9b4ae15 Mon Sep 17 00:00:00 2001 From: Marco Callieri Date: Thu, 14 Jul 2016 18:37:08 +0200 Subject: [PATCH 11/91] added new Perlin coloring function New function ot mix two input colors according to perlin noise --- vcg/complex/algorithms/update/color.h | 29 ++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/update/color.h b/vcg/complex/algorithms/update/color.h index 30d8beb1..c4121f6a 100644 --- a/vcg/complex/algorithms/update/color.h +++ b/vcg/complex/algorithms/update/color.h @@ -368,7 +368,6 @@ Note: The faux bit is used to color polygonal faces uniformly } /*! \brief Perlin Noise. -\return the number of changed vertexes (the selected ones) Simple Perlin noise. To make things weirder each color band can have its own offset and frequency. Period is expressed in absolute terms. @@ -396,6 +395,34 @@ static void PerVertexPerlinNoise(MeshType& m, CoordType period, CoordType offset } + +/*! \brief Perlin Color mixing. + +Simple Perlin color mixing. Color 1 and 2 are mixed according the perlin noise function, with period and offset. +*/ +static void PerVertexPerlinColoring(MeshType& m, Scalarm period, CoordType offset = CoordType(0, 0, 0), Color4b color1 = Color4b(0, 0, 0, 255), Color4b color2 = Color4b(255, 255, 255, 255), bool onSelected = false) +{ + RequirePerVertexColor(m); + + CoordType p; + + for (VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi) + if (!(*vi).IsD()) + if ((!onSelected) || ((*vi).IsS())) + { + // perlin noise is defined in 022 + p = (vi->P() / period) + offset; + double factor = (math::Perlin::Noise(p[0], p[1], p[2]) + 1.0) / 2.0; + + int rr = (color1[0] * factor) + (color2[0] * (1.0 - factor)); + int gg = (color1[1] * factor) + (color2[1] * (1.0 - factor)); + int bb = (color1[2] * factor) + (color2[2] * (1.0 - factor)); + int aa = (color1[3] * factor) + (color2[3] * (1.0 - factor)); + + (*vi).C() = Color4b(rr, gg, bb, aa); + } +} + /*! \brief Simple Noise adding function. It simply add signed noise to the color of the mesh. The noise has uniform distribution and the amplitude is +/-2^(noisebits-1). */ From 6ec5b3373b5a0fbd92d05a999cd942301dabae0f Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Fri, 15 Jul 2016 11:06:57 +0200 Subject: [PATCH 12/91] Added explicit braces to avoid dangling else warning --- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index c4b1ba66..b300c62c 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -1561,12 +1561,12 @@ namespace vcg } glEnable(GL_COLOR_MATERIAL); - if ((isgloptsvalid) && ((glopts->_perpoint_fixed_color_enabled) || (glopts->_perpoint_mesh_color_enabled))) + if ((isgloptsvalid) && ((glopts->_perpoint_fixed_color_enabled) || (glopts->_perpoint_mesh_color_enabled))){ if (glopts->_perpoint_fixed_color_enabled) glColor(glopts->_perpoint_fixed_color); else glColor(_mesh.C()); - + } if (req[INT_ATT_NAMES::ATT_VERTCOLOR]) glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); From b4c76bc03cd87760c8eeaed1802bce627bc8ca54 Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 15 Jul 2016 14:36:08 +0200 Subject: [PATCH 13/91] fixed bug --- .../algorithms/parametrization/tangent_field_operators.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/parametrization/tangent_field_operators.h b/vcg/complex/algorithms/parametrization/tangent_field_operators.h index 0ed1caf6..3da1a33a 100644 --- a/vcg/complex/algorithms/parametrization/tangent_field_operators.h +++ b/vcg/complex/algorithms/parametrization/tangent_field_operators.h @@ -666,7 +666,7 @@ public: CoordType dirR=vcg::tri::CrossField::Rotate(f0,f1,dir0); ///then get the closest upf to K*PI/2 rotations CoordType dir1=f1.cPD1(); - CoordType ret=vcg::tri::CrossField::K_PI(dirR,dir1,f1.cN()); + CoordType ret=vcg::tri::CrossField::K_PI(dir1,dirR,f1.cN()); return ret; } From b76aed2fa0d963b4cd253416b10b6fa5dc53b6cf Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 15 Jul 2016 15:00:14 +0200 Subject: [PATCH 14/91] set the pointer to vertex as const --- vcg/simplex/edge/topology.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcg/simplex/edge/topology.h b/vcg/simplex/edge/topology.h index a52da7b3..c3e4c8b8 100644 --- a/vcg/simplex/edge/topology.h +++ b/vcg/simplex/edge/topology.h @@ -57,7 +57,7 @@ inline bool IsEdgeBorder(EdgeType const & e, const int j ) } template -void VVStarVE(VertexType* vp, std::vector &starVec) +void VVStarVE(const VertexType* vp, std::vector &starVec) { starVec.clear(); edge::VEIterator vei(vp); From f20540d563a1860381cddf5b081cb0d3b18fb37b Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Sun, 17 Jul 2016 16:48:25 +0200 Subject: [PATCH 15/91] Corrected a Meshlab leftover (Scalarm->ScalarType --- vcg/complex/algorithms/update/color.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/update/color.h b/vcg/complex/algorithms/update/color.h index c4121f6a..95ddc5aa 100644 --- a/vcg/complex/algorithms/update/color.h +++ b/vcg/complex/algorithms/update/color.h @@ -400,7 +400,7 @@ static void PerVertexPerlinNoise(MeshType& m, CoordType period, CoordType offset Simple Perlin color mixing. Color 1 and 2 are mixed according the perlin noise function, with period and offset. */ -static void PerVertexPerlinColoring(MeshType& m, Scalarm period, CoordType offset = CoordType(0, 0, 0), Color4b color1 = Color4b(0, 0, 0, 255), Color4b color2 = Color4b(255, 255, 255, 255), bool onSelected = false) +static void PerVertexPerlinColoring(MeshType& m, ScalarType period, CoordType offset = CoordType(0, 0, 0), Color4b color1 = Color4b::Black, Color4b color2 = Color4b::White, bool onSelected = false) { RequirePerVertexColor(m); From dbf3e0f6c9d87c67afc5239e3a64fa17603dc6fb Mon Sep 17 00:00:00 2001 From: gianpaolopalma Date: Fri, 22 Jul 2016 15:41:39 +0200 Subject: [PATCH 16/91] Bug fixing - Add method to cast an enum to unsigned int (DiBenedetto) - Add inline - Fix bug in the read and write of the texture filename --- wrap/nanoply/include/nanoply.hpp | 374 ++++++++++++------------ wrap/nanoply/include/nanoplyWrapper.hpp | 3 +- 2 files changed, 194 insertions(+), 183 deletions(-) diff --git a/wrap/nanoply/include/nanoply.hpp b/wrap/nanoply/include/nanoply.hpp index 63b26d79..810d6fd5 100644 --- a/wrap/nanoply/include/nanoply.hpp +++ b/wrap/nanoply/include/nanoply.hpp @@ -147,6 +147,25 @@ namespace nanoply NNP_LIST_INT8_INT16 = 0x800000 /**< List (size Char) of Short. */ } PlyType; + template + inline std::size_t hashEnum(const TEnum & value) + { + const std::hash h{}; + return h((unsigned int)value); + } + +} // end namespace nanoply + +// Cast of an enum to an unsigned int (maybe only for Android) +namespace std +{ + template <> struct hash { std::size_t operator () (const nanoply::PlyElemEntity & t) const { return nanoply::hashEnum(t); } }; + template <> struct hash { std::size_t operator () (const nanoply::PlyEntity & t) const { return nanoply::hashEnum(t); } }; + template <> struct hash { std::size_t operator () (const nanoply::PlyType & t) const { return nanoply::hashEnum(t); } }; +} // end namespace std + +namespace nanoply +{ /** * @cond HIDDEN_SYMBOLS @@ -161,8 +180,6 @@ namespace nanoply typedef std::unordered_map ElementMap; typedef std::unordered_map::iterator ElementMapIterator; - static NameVector emptyVec; - /* Names used for the PlyType */ static TypeMap mapType({ { PlyType::NNP_UNKNOWN_TYPE, NameVector({ "unknonw" }) }, @@ -246,8 +263,9 @@ namespace nanoply /* Returns the vector of possible name for the input PlyEntity */ - static const NameVector& PlyPropertyName(PlyEntity ent) + static inline const NameVector& PlyPropertyName(PlyEntity ent) { + static NameVector emptyVec; if (mapProp.find(ent) != mapProp.end()) return mapProp[ent]; return emptyVec; @@ -255,8 +273,9 @@ namespace nanoply /* Returns the vector of possible name for the input PlyType */ - static const NameVector& PlyTypeName(PlyType ent) + static inline const NameVector& PlyTypeName(PlyType ent) { + static NameVector emptyVec; if (mapType.find(ent) != mapType.end()) return mapType[ent]; return emptyVec; @@ -264,8 +283,9 @@ namespace nanoply /* Returns the vector of possible name for the input PlyElement */ - static const NameVector& PlyElementName(PlyElemEntity ent) + static inline const NameVector& PlyElementName(PlyElemEntity ent) { + static NameVector emptyVec; if (mapElem.find(ent) != mapElem.end()) return mapElem[ent]; return emptyVec; @@ -273,7 +293,7 @@ namespace nanoply /* Return 1 for little endian, 0 for big endian*/ - int checkEndianness() + inline int checkEndianness() { unsigned int x = 1; char *c = (char*)&x; @@ -281,7 +301,7 @@ namespace nanoply }; /* Adjust the endianess of the input buffer*/ - void adjustEndianess(unsigned char* buffer, int typeSize, int count) + inline void adjustEndianess(unsigned char* buffer, int typeSize, int count) { for (int i = 0; i < count; i++) { @@ -326,7 +346,7 @@ namespace nanoply * @param filename name of the file. * @return If successful returns true. Otherwise, it returns false. */ - bool OpenFileToRead(const std::string &filename); + inline bool OpenFileToRead(const std::string &filename); /** * Open the file in write mode. @@ -334,7 +354,7 @@ namespace nanoply * @param filename name of the file. * @return If successful returns true. Otherwise, it returns false. */ - bool OpenFileToWrite(const std::string &filename); + inline bool OpenFileToWrite(const std::string &filename); /** * Read the next header line. @@ -343,7 +363,7 @@ namespace nanoply * @param last true if the line is the last of header. * @return If successful returns true. Otherwise, it returns false. */ - bool NextHeaderLine(std::string &line, bool &last); + inline bool NextHeaderLine(std::string &line, bool &last); /** * Write the line in the header. @@ -351,7 +371,7 @@ namespace nanoply * @param line line to write. * @return If successful returns true. Otherwise, it returns false. */ - bool WriteHeaderLine(std::string &line); + inline bool WriteHeaderLine(const std::string &line); /** * Read binary data from the file. @@ -360,7 +380,7 @@ namespace nanoply * @param nByte number of byte to read. * @return If successful returns true. Otherwise, it returns false. */ - bool ReadBinaryData(void *dest, int nByte); + inline bool ReadBinaryData(char * & dest, int nByte); /** * Read ASCII data from the file. @@ -369,7 +389,7 @@ namespace nanoply * @return If successful returns true. Otherwise, it returns false. */ template - bool ReadAsciiData(T &dest); + inline bool ReadAsciiData(T &dest); /** * Write binary data in the file. @@ -378,7 +398,7 @@ namespace nanoply * @param nByte number of byte to write. * @return If successful returns true. Otherwise, it returns false. */ - bool WriteBinaryData(void *src, int nByte); + inline bool WriteBinaryData(void *src, int nByte); /** * Write ASCII data in the file. @@ -387,31 +407,31 @@ namespace nanoply * @return If successful returns true. Otherwise, it returns false. */ template - bool WriteAsciiData(T &src); + inline bool WriteAsciiData(const T &src); /** * Set the maximum size of the buffer. * * @return size size of the buffer. */ - void SetBufferSize(int64_t size); + inline void SetBufferSize(int64_t size); /** * Force the write of the buffer in the file. */ - void Flush(); + inline void Flush(); }; - PlyFile::PlyFile() + inline PlyFile::PlyFile() { buffer = NULL; - maxSize = 1000000; + maxSize = 10 * (1 << 20); mode = -1; } - PlyFile::~PlyFile() + inline PlyFile::~PlyFile() { Flush(); if (buffer != NULL) @@ -421,7 +441,7 @@ namespace nanoply } - bool PlyFile::OpenFileToRead(const std::string& filename) + inline bool PlyFile::OpenFileToRead(const std::string& filename) { if (fileStream.is_open()) fileStream.close(); @@ -434,7 +454,7 @@ namespace nanoply } - bool PlyFile::OpenFileToWrite(const std::string& filename) + inline bool PlyFile::OpenFileToWrite(const std::string& filename) { if (fileStream.is_open()) fileStream.close(); @@ -449,7 +469,7 @@ namespace nanoply } - bool PlyFile::NextHeaderLine(std::string& line, bool& last) + inline bool PlyFile::NextHeaderLine(std::string& line, bool& last) { if (mode != 0) return false; @@ -462,7 +482,7 @@ namespace nanoply } - bool PlyFile::WriteHeaderLine(std::string& line) + inline bool PlyFile::WriteHeaderLine(const std::string& line) { if (mode != 1) return false; @@ -471,7 +491,7 @@ namespace nanoply } - bool PlyFile::ReadBinaryData(void* dest, int nByte) + inline bool PlyFile::ReadBinaryData(char * & dest, int nByte) { if (mode != 0) return false; @@ -484,20 +504,21 @@ namespace nanoply } else if (bufferOffset + nByte > bufferSize) { - unsigned int lastByte = bufferSize - bufferOffset; + const size_t lastByte = bufferSize - bufferOffset; memcpy(buffer, &buffer[bufferOffset], lastByte); fileStream.read(&buffer[lastByte], maxSize - lastByte); bufferSize = fileStream.gcount() + lastByte; bufferOffset = 0; } - memcpy(dest, &buffer[bufferOffset], nByte); + //memcpy(dest, &buffer[bufferOffset], nByte); + dest = buffer + bufferOffset; bufferOffset += nByte; return true; } template - bool PlyFile::ReadAsciiData(T& dest) + inline bool PlyFile::ReadAsciiData(T& dest) { if (mode != 0) return false; @@ -505,7 +526,7 @@ namespace nanoply return true; } - bool PlyFile::WriteBinaryData(void* src, int nByte) + inline bool PlyFile::WriteBinaryData(void* src, int nByte) { if (mode != 1) return false; @@ -527,7 +548,7 @@ namespace nanoply template - bool PlyFile::WriteAsciiData(T& src) + inline bool PlyFile::WriteAsciiData(const T& src) { if (mode != 1) return false; @@ -535,13 +556,13 @@ namespace nanoply return true; } - void PlyFile::SetBufferSize(int64_t size) + inline void PlyFile::SetBufferSize(int64_t size) { maxSize = size; } - void PlyFile::Flush() + inline void PlyFile::Flush() { if (mode == 1) fileStream.write(buffer, bufferOffset); @@ -568,7 +589,7 @@ namespace nanoply * @param _t Property type. * @param _e Property entity. */ - PlyProperty(PlyType _t, PlyEntity _e) :type(_t), elem(_e), name(PlyPropertyName(_e)[0]), validToWrite(false){} + inline PlyProperty(PlyType _t, PlyEntity _e) :type(_t), elem(_e), name(PlyPropertyName(_e)[0]), validToWrite(false){} /** * Constructor that sets the type, the entity and the name of a standard PLY property. @@ -577,7 +598,7 @@ namespace nanoply * @param _e Property entity. * @param _n Property name. */ - PlyProperty(PlyType _t, PlyEntity _e, std::string _n) :type(_t), elem(_e), name(_n), validToWrite(false){} + inline PlyProperty(PlyType _t, PlyEntity _e, std::string _n) :type(_t), elem(_e), name(_n), validToWrite(false){} /** * Constructor that sets the type and the name of a custom PLY property. @@ -585,49 +606,49 @@ namespace nanoply * @param _t Property type. * @param _n Property name. */ - PlyProperty(PlyType _t, std::string _n) :type(_t), elem(PlyEntity::NNP_UNKNOWN_ENTITY), name(_n), validToWrite(false){} + inline PlyProperty(PlyType _t, std::string _n) :type(_t), elem(PlyEntity::NNP_UNKNOWN_ENTITY), name(_n), validToWrite(false){} /** * Get the description string of the property entity. * * @return Description string of the property entity. */ - const char* EntityStr(); + inline const char* EntityStr(); /** * Get the name of the property entity. * * @return Name of the property entity. */ - const char* EntityName(); + inline const char* EntityName(); /** * Get the description string of the property type. * * @return Description string of the property type. */ - const char* TypeStr(); + inline const char* TypeStr(); /** * Get the size in byte of the property type. * * @return Size in byte of the property type. */ - int TypeSize(); + inline int TypeSize(); /** * Get the number of component of the property entity. * * @return Number of component. */ - int CountValue(); + inline int CountValue(); /** * Check if the property type is signed or unsigned. * * @return true = signed, false = unsigned. */ - bool IsSigned(); + inline bool IsSigned(); /** * Skip the property in an Ascii file. @@ -635,7 +656,7 @@ namespace nanoply * @param file Opened file. * @return If successful returns true. Otherwise, it returns false. */ - bool SkipAsciiPropertyInFile(PlyFile &file); + inline bool SkipAsciiPropertyInFile(PlyFile &file); /** * Skip the property in a binary file. @@ -643,7 +664,7 @@ namespace nanoply * @param file Opened file. * @return If successful returns true. Otherwise, it returns false. */ - bool SkipBinaryPropertyInFile(PlyFile &file); + inline bool SkipBinaryPropertyInFile(PlyFile &file); /** * Write the property string in the header of the PLY file. @@ -651,11 +672,11 @@ namespace nanoply * @param file Opened file. * @return If successful returns true. Otherwise, it returns false. */ - bool WriteHeader(PlyFile &file); + inline bool WriteHeader(PlyFile &file); }; - const char* PlyProperty::EntityStr() + inline const char* PlyProperty::EntityStr() { switch (this->elem) { @@ -705,7 +726,7 @@ namespace nanoply } - const char* PlyProperty::EntityName() + inline const char* PlyProperty::EntityName() { if (this->elem == PlyEntity::NNP_UNKNOWN_ENTITY) @@ -732,7 +753,7 @@ namespace nanoply } - const char* PlyProperty::TypeStr() + inline const char* PlyProperty::TypeStr() { switch (this->type) { @@ -768,7 +789,7 @@ namespace nanoply } - int PlyProperty::TypeSize() + inline int PlyProperty::TypeSize() { switch (this->type) { @@ -814,7 +835,7 @@ namespace nanoply } - bool PlyProperty::IsSigned() + inline bool PlyProperty::IsSigned() { switch (this->type) { @@ -850,7 +871,7 @@ namespace nanoply } - int PlyProperty::CountValue() + inline int PlyProperty::CountValue() { if (this->elem == NNP_CRGB || this->elem == NNP_NXYZ || this->elem == NNP_PXYZ || this->elem == NNP_TEXTURE3D) return 3; @@ -862,7 +883,7 @@ namespace nanoply } - bool PlyProperty::SkipAsciiPropertyInFile(PlyFile &file) + inline bool PlyProperty::SkipAsciiPropertyInFile(PlyFile &file) { int count = CountValue(); if (this->type >= NNP_LIST_UINT8_UINT32) @@ -926,40 +947,35 @@ namespace nanoply } - bool PlyProperty::SkipBinaryPropertyInFile(PlyFile& file) + inline bool PlyProperty::SkipBinaryPropertyInFile(PlyFile& file) { - unsigned char* temp; + char * temp = nullptr; int count = CountValue(); if (this->type >= NNP_LIST_UINT8_UINT32) { int size; if (this->IsSigned()) { - unsigned char cntList = 0; - file.ReadBinaryData(&cntList, sizeof(char)); - size = this->TypeSize() * cntList; + file.ReadBinaryData(temp, sizeof(char)); + size = this->TypeSize() * int(*(reinterpret_cast(temp))); } else { - char cntList = 0; - file.ReadBinaryData(&cntList, sizeof(char)); - size = this->TypeSize() * cntList; + file.ReadBinaryData(temp, sizeof(char)); + size = this->TypeSize() * int(*(reinterpret_cast(temp))); } - temp = new unsigned char[size]; file.ReadBinaryData(temp, size); } else { - int size = this->TypeSize()*count; - temp = new unsigned char[size]; + int size = this->TypeSize() * count; file.ReadBinaryData(temp, size); } - delete[] temp; return true; } - bool PlyProperty::WriteHeader(PlyFile& file) + inline bool PlyProperty::WriteHeader(PlyFile& file) { if (!validToWrite) return true; @@ -1044,7 +1060,7 @@ namespace nanoply /** * Default Constructor */ - PlyElement() :validToWrite(false){}; + inline PlyElement() :validToWrite(false){}; /** * Constructor that sets the name, the properties and the number of instances of the element. @@ -1053,7 +1069,7 @@ namespace nanoply * @param prop Vector of properties. * @param nElem Number of instances. */ - PlyElement(std::string& _name, std::vector &prop, size_t nElem) :name(_name), cnt(nElem), propVec(prop), plyElem(PlyElemEntity::NNP_UNKNOWN_ELEM), validToWrite(false){}; + inline PlyElement(std::string& _name, std::vector &prop, size_t nElem) :name(_name), cnt(nElem), propVec(prop), plyElem(PlyElemEntity::NNP_UNKNOWN_ELEM), validToWrite(false){}; /** * Constructor that sets the entity, the properties and the number of instances of the element. @@ -1062,7 +1078,7 @@ namespace nanoply * @param prop Vector of properties. * @param nElem Number of instances. */ - PlyElement(PlyElemEntity ent, std::vector &prop, size_t nElem) :name(PlyElementName(ent)[0]), cnt(nElem), propVec(prop), plyElem(ent), validToWrite(false){}; + inline PlyElement(PlyElemEntity ent, std::vector &prop, size_t nElem) :name(PlyElementName(ent)[0]), cnt(nElem), propVec(prop), plyElem(ent), validToWrite(false){}; /** * Parse the input line and add the properties to the element. @@ -1071,7 +1087,7 @@ namespace nanoply * @param line Input line. * @return If successful returns true. Otherwise, it returns false. */ - bool AddProperty(std::string &line); + inline bool AddProperty(std::string &line); /** * Initialize an element from the header line. @@ -1080,7 +1096,7 @@ namespace nanoply * @param propStr Strings with the property definition. * @return If successful returns true. Otherwise, it returns false. */ - bool InitFromHeader(std::string &elemStr, std::vector &propStr); + inline bool InitFromHeader(std::string &elemStr, std::vector &propStr); /** * Write the element descriport in the file header. @@ -1088,7 +1104,7 @@ namespace nanoply * @param file Ply file. * @return If successful returns true. Otherwise, it returns false. */ - bool WriteHeader(PlyFile &file); + inline bool WriteHeader(PlyFile &file); /** * Skip the element in an Ascii file. @@ -1096,7 +1112,7 @@ namespace nanoply * @param file Ply file * @return If successful returns true. Otherwise, it returns false. */ - bool SkipAsciiElementsInFile(PlyFile &file); + inline bool SkipAsciiElementsInFile(PlyFile &file); /** * Skip the element in a binary file. @@ -1104,7 +1120,7 @@ namespace nanoply * @param file Ply file. * @return If successful returns true. Otherwise, it returns false. */ - bool SkipBinaryElementsInFile(PlyFile &file); + inline bool SkipBinaryElementsInFile(PlyFile &file); /** * Check if the input entity is in the property of the element. @@ -1112,11 +1128,11 @@ namespace nanoply * @param entity Input entity. * @return If successful returns true. Otherwise, it returns false. */ - bool Contains(NNP_ENTITY entity); + inline bool Contains(NNP_ENTITY entity); }; - bool PlyElement::InitFromHeader(std::string &elemStr, std::vector &propStr) + inline bool PlyElement::InitFromHeader(std::string &elemStr, std::vector &propStr) { char* token; char* tempStr = &elemStr[0]; @@ -1225,7 +1241,7 @@ namespace nanoply } - bool PlyElement::WriteHeader(PlyFile &file) + inline bool PlyElement::WriteHeader(PlyFile &file) { if (!validToWrite || cnt == 0) return true; @@ -1243,7 +1259,7 @@ namespace nanoply } - bool PlyElement::SkipAsciiElementsInFile(PlyFile &file) + inline bool PlyElement::SkipAsciiElementsInFile(PlyFile &file) { for (int i = 0; i < this->cnt; ++i) for (int j = 0; j < this->propVec.size(); ++j) @@ -1252,7 +1268,7 @@ namespace nanoply } - bool PlyElement::SkipBinaryElementsInFile(PlyFile &file) + inline bool PlyElement::SkipBinaryElementsInFile(PlyFile &file) { for (int i = 0; i < this->cnt; ++i) for (int j = 0; j < this->propVec.size(); ++j) @@ -1261,7 +1277,7 @@ namespace nanoply } - bool PlyElement::AddProperty(std::string &line) + inline bool PlyElement::AddProperty(std::string &line) { char* token; char* tempStr = &line[0]; @@ -1334,7 +1350,7 @@ namespace nanoply } - bool PlyElement::Contains(PlyEntity entity) + inline bool PlyElement::Contains(PlyEntity entity) { for (int i = 0; i < propVec.size(); i++) { @@ -1364,14 +1380,14 @@ namespace nanoply /** * Default Constructor */ - Info(); + inline Info(); /** * Constructor that reads the header info from a file. * * @param filename Path of the file to read. */ - Info(const std::string& filename); + inline Info(const std::string& filename); /** * Load the ply info from the header of the input filename. @@ -1379,7 +1395,7 @@ namespace nanoply * @param filename Path of the file to read. * @return If successful returns true. Otherwise, it returns false. */ - bool LoadHeader(const std::string& filename); + inline bool LoadHeader(const std::string& filename); /** * Write the ply info in the header of the input file. @@ -1387,19 +1403,19 @@ namespace nanoply * @param file File to write. * @return If successful returns true. Otherwise, it returns false. */ - bool WriteHeader(PlyFile& file); + inline bool WriteHeader(PlyFile& file); /** * Add the ply element to the header. * * @param pe Ply element to write in the header. */ - void AddPlyElement(PlyElement& pe); + inline void AddPlyElement(PlyElement& pe); /** * Clear the error code. */ - void Clear() { errInfo = NNP_OK; } + inline void Clear() { errInfo = NNP_OK; } /** * Return the number of instances of the element with the input name @@ -1407,7 +1423,7 @@ namespace nanoply * @param name Name of the element. * @return The number of instances */ - size_t GetElementCount(std::string& name); + inline size_t GetElementCount(std::string& name); /** * Return the number of instances of the element with the input element type @@ -1415,28 +1431,28 @@ namespace nanoply * @param e Element type. * @return The number of instances */ - size_t GetElementCount(PlyElemEntity e); + inline size_t GetElementCount(PlyElemEntity e); /** * Return the number of vertex instances * * @return The number of vertex instances */ - size_t GetVertexCount(); + inline size_t GetVertexCount(); /** * Return the number of face instances * * @return The number of face instances */ - size_t GetFaceCount(); + inline size_t GetFaceCount(); /** * Return the number of edge instances * * @return The number of edge instances */ - size_t GetEdgeCount(); + inline size_t GetEdgeCount(); /** * Return a reference to the element with a specific name @@ -1444,7 +1460,7 @@ namespace nanoply * @param name Name of the element. * @return The reference to the element */ - PlyElement* GetElement(std::string& name); + inline PlyElement* GetElement(std::string& name); /** * Return a reference to the element with a specific element type @@ -1452,33 +1468,33 @@ namespace nanoply * @param e Element type. * @return The reference to the element */ - PlyElement* GetElement(PlyElemEntity e); + inline PlyElement* GetElement(PlyElemEntity e); /** * Return a reference to the vertex element * * @return The reference to the vertex element */ - PlyElement* GetVertexElement(); + inline PlyElement* GetVertexElement(); /** * Return a reference to the face element * * @return The reference to the face element */ - PlyElement* GetFaceElement(); + inline PlyElement* GetFaceElement(); /** * Return a reference to the edge element * * @return The reference to the edge element */ - PlyElement* GetEdgeElement(); + inline PlyElement* GetEdgeElement(); }; - Info::Info() + inline Info::Info() { this->binary = true; this->bigEndian = true; @@ -1486,13 +1502,13 @@ namespace nanoply } - Info::Info(const std::string& filename) + inline Info::Info(const std::string& filename) { this->LoadHeader(filename); } - bool Info::LoadHeader(const std::string& filename) + inline bool Info::LoadHeader(const std::string& filename) { this->filename = filename; this->errInfo = NNP_OK; @@ -1542,20 +1558,24 @@ namespace nanoply return false; } std::getline(input, buffer); - std::transform(buffer.begin(), buffer.end(), buffer.begin(), ::tolower); - while (buffer != "end_header") + std::string lowBuffer; + lowBuffer.resize(buffer.size()); + std::transform(buffer.begin(), buffer.end(), lowBuffer.begin(), ::tolower); + while (lowBuffer != "end_header") { - if (buffer.find("element") != std::string::npos) + if (lowBuffer.find("element") != std::string::npos) { - std::string elemStr = buffer; + std::string elemStr = lowBuffer; std::vector propStr; do { std::getline(input, buffer); - std::transform(buffer.begin(), buffer.end(), buffer.begin(), ::tolower); - pos = buffer.find("property"); + lowBuffer.clear(); + lowBuffer.resize(buffer.size()); + std::transform(buffer.begin(), buffer.end(), lowBuffer.begin(), ::tolower); + pos = lowBuffer.find("property"); if (pos != std::string::npos) - propStr.push_back(buffer); + propStr.push_back(lowBuffer); } while (pos != std::string::npos); PlyElement pe; if (!pe.InitFromHeader(elemStr, propStr)) @@ -1568,10 +1588,12 @@ namespace nanoply } else { - if (buffer.find("comment TextureFile")) - textureFile.push_back(buffer.substr(21)); + if (lowBuffer.find("comment texture") != std::string::npos) + textureFile.push_back(buffer.substr(buffer.find(" ", 10) + 1)); std::getline(input, buffer); - std::transform(buffer.begin(), buffer.end(), buffer.begin(), ::tolower); + lowBuffer.clear(); + lowBuffer.resize(buffer.size()); + std::transform(buffer.begin(), buffer.end(), lowBuffer.begin(), ::tolower); } } input.close(); @@ -1579,7 +1601,7 @@ namespace nanoply } - bool Info::WriteHeader(PlyFile& file) + inline bool Info::WriteHeader(PlyFile& file) { bool ok = true; ok = file.WriteHeaderLine(std::string("ply\n")); @@ -1589,7 +1611,7 @@ namespace nanoply ok = file.WriteHeaderLine(std::string("format ascii 1.0\n")); ok = file.WriteHeaderLine(std::string("comment nanoply generated\n")); for (int i = 0; i < this->textureFile.size(); i++) - ok = file.WriteHeaderLine(std::string("comment TextureName ") + this->textureFile[i] + "\n"); + ok = file.WriteHeaderLine(std::string("comment TextureFile ") + this->textureFile[i] + "\n"); for (int i = 0; i < this->elemVec.size(); i++) ok = this->elemVec[i].WriteHeader(file); ok = file.WriteHeaderLine(std::string("end_header\n")); @@ -1597,13 +1619,13 @@ namespace nanoply } - void Info::AddPlyElement(PlyElement& pe) + inline void Info::AddPlyElement(PlyElement& pe) { elemVec.push_back(pe); } - size_t Info::GetElementCount(std::string& name) + inline size_t Info::GetElementCount(std::string& name) { PlyElement* pe = GetElement(name); if (pe != NULL) @@ -1612,7 +1634,7 @@ namespace nanoply } - size_t Info::GetElementCount(PlyElemEntity e) + inline size_t Info::GetElementCount(PlyElemEntity e) { PlyElement* pe = GetElement(e); if (pe != NULL) @@ -1621,25 +1643,25 @@ namespace nanoply } - size_t Info::GetVertexCount() + inline size_t Info::GetVertexCount() { return GetElementCount(PlyElemEntity::NNP_VERTEX_ELEM); } - size_t Info::GetFaceCount() + inline size_t Info::GetFaceCount() { return GetElementCount(PlyElemEntity::NNP_FACE_ELEM); } - size_t Info::GetEdgeCount() + inline size_t Info::GetEdgeCount() { return GetElementCount(PlyElemEntity::NNP_EDGE_ELEM); } - PlyElement* Info::GetElement(std::string& name) + inline PlyElement* Info::GetElement(std::string& name) { for (int i = 0; i < elemVec.size(); i++) { @@ -1650,7 +1672,7 @@ namespace nanoply } - PlyElement* Info::GetElement(PlyElemEntity e) + inline PlyElement* Info::GetElement(PlyElemEntity e) { for (int i = 0; i < elemVec.size(); i++) { @@ -1661,19 +1683,19 @@ namespace nanoply } - PlyElement* Info::GetVertexElement() + inline PlyElement* Info::GetVertexElement() { return GetElement(PlyElemEntity::NNP_VERTEX_ELEM); } - PlyElement* Info::GetFaceElement() + inline PlyElement* Info::GetFaceElement() { return GetElement(PlyElemEntity::NNP_FACE_ELEM); } - PlyElement* Info::GetEdgeElement() + inline PlyElement* Info::GetEdgeElement() { return GetElement(PlyElemEntity::NNP_EDGE_ELEM); } @@ -1702,7 +1724,7 @@ namespace nanoply * @param _e Ply entity managed by the descriptor. * @param _b Pointer to the memory location that contains the data of the property. */ - DescriptorInterface(PlyEntity _e, void *_b) :curPos(0), elem(_e), base(_b), name(PlyPropertyName(_e)[0]){}; + inline DescriptorInterface(PlyEntity _e, void *_b) :curPos(0), elem(_e), base(_b), name(PlyPropertyName(_e)[0]){}; /** * Constructor of the descriptor. @@ -1710,7 +1732,7 @@ namespace nanoply * @param _s Name of the PlyProperty. * @param _b Pointer to the memory location that contains the data of the property. */ - DescriptorInterface(std::string& _s, void *_b) :curPos(0), elem(PlyEntity::NNP_UNKNOWN_ENTITY), name(_s), base(_b){}; + inline DescriptorInterface(std::string& _s, void *_b) :curPos(0), elem(PlyEntity::NNP_UNKNOWN_ENTITY), name(_s), base(_b){}; /** * Restart the descriptor. @@ -1776,14 +1798,14 @@ namespace nanoply * * @param _e Ply Element entity managed by the descriptor. */ - ElementDescriptor(PlyElemEntity _e) : elem(_e), name(PlyElementName(_e)[0]){}; + inline ElementDescriptor(PlyElemEntity _e) : elem(_e), name(PlyElementName(_e)[0]){}; /** * Constructor of the Ply element descriptor. * * @param _s Name of the Ply element managed by the descriptor. */ - ElementDescriptor(std::string &_s) : elem(PlyElemEntity::NNP_UNKNOWN_ELEM), name(_s){}; + inline ElementDescriptor(std::string &_s) : elem(PlyElemEntity::NNP_UNKNOWN_ELEM), name(_s){}; /** * Read all the properties of the element from the binary file. @@ -1793,7 +1815,7 @@ namespace nanoply * @param fixEndian If true the method adjust the endianess of the data. * @return If successful returns true. Otherwise, it returns false. */ - bool ReadElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian); + inline bool ReadElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian); /** * Read all the property data of the element from the ascii file. @@ -1802,7 +1824,7 @@ namespace nanoply * @param elem PLY element to read from the file. * @return If successful returns true. Otherwise, it returns false. */ - bool ReadElemAscii(PlyFile &file, PlyElement &elem); + inline bool ReadElemAscii(PlyFile &file, PlyElement &elem); /** * Write all the property data of the element in the binary file. @@ -1812,7 +1834,7 @@ namespace nanoply * @param fixEndian If true the method adjust the endianess of the data. * @return If successful returns true. Otherwise, it returns false. */ - bool WriteElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian); + inline bool WriteElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian); /** * Write all the property data of the element in the ascii file. @@ -1821,7 +1843,7 @@ namespace nanoply * @param elem PLY element to write from the file. * @return If successful returns true. Otherwise, it returns false. */ - bool WriteElemAscii(PlyFile &file, PlyElement &elem); + inline bool WriteElemAscii(PlyFile &file, PlyElement &elem); /** * Check if the properties defined in input element have a proper data descriport to write in the file. @@ -1829,16 +1851,16 @@ namespace nanoply * * @param elem PLY element to write from the file. */ - void CheckDescriptor(PlyElement &elem); + inline void CheckDescriptor(PlyElement &elem); private: - void ExtractDescriptor(PropertyDescriptor &descr, PlyElement &elem); + inline void ExtractDescriptor(PropertyDescriptor &descr, PlyElement &elem); }; - void ElementDescriptor::ExtractDescriptor(PropertyDescriptor& descr, PlyElement &elem) + inline void ElementDescriptor::ExtractDescriptor(PropertyDescriptor& descr, PlyElement &elem) { for (int j = 0; j < elem.propVec.size(); j++) { @@ -1873,7 +1895,7 @@ namespace nanoply } - bool ElementDescriptor::ReadElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian) + inline bool ElementDescriptor::ReadElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian) { PropertyDescriptor descr; ExtractDescriptor(descr, elem); @@ -1892,7 +1914,7 @@ namespace nanoply } - bool ElementDescriptor::ReadElemAscii(PlyFile &file, PlyElement &elem) + inline bool ElementDescriptor::ReadElemAscii(PlyFile &file, PlyElement &elem) { PropertyDescriptor descr; ExtractDescriptor(descr, elem); @@ -1910,7 +1932,7 @@ namespace nanoply return true; } - bool ElementDescriptor::WriteElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian) + inline bool ElementDescriptor::WriteElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian) { PropertyDescriptor descr; ExtractDescriptor(descr, elem); @@ -1925,7 +1947,7 @@ namespace nanoply return true; } - bool ElementDescriptor::WriteElemAscii(PlyFile &file, PlyElement &elem) + inline bool ElementDescriptor::WriteElemAscii(PlyFile &file, PlyElement &elem) { PropertyDescriptor descr; ExtractDescriptor(descr, elem); @@ -1949,7 +1971,7 @@ namespace nanoply } - void ElementDescriptor::CheckDescriptor(PlyElement &elem) + inline void ElementDescriptor::CheckDescriptor(PlyElement &elem) { if (elem.propVec.size() == 0) { @@ -1980,7 +2002,7 @@ namespace nanoply { public: - DataDescriptor(); + inline DataDescriptor(); /** * Constructor of the descriptor. @@ -1988,7 +2010,7 @@ namespace nanoply * @param _e Ply entity managed by the descriptor. * @param _b Pointer to the memory location that contains the data of the property. */ - DataDescriptor(PlyEntity _e, void *_b) :DescriptorInterface(_e, _b){}; + inline DataDescriptor(PlyEntity _e, void *_b) :DescriptorInterface(_e, _b){}; /** * Constructor of the descriptor. @@ -1996,73 +2018,62 @@ namespace nanoply * @param _s Name of the PlyProperty. * @param _b Pointer to the memory location that contains the data of the property. */ - DataDescriptor(std::string& _s, void *_b) :DescriptorInterface(_s, _b){}; + inline DataDescriptor(std::string& _s, void *_b) :DescriptorInterface(_s, _b){}; - void Restart(); + inline void Restart(); - bool ReadElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); + inline bool ReadElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); - bool ReadElemAscii(PlyFile &file, PlyProperty &prop); + inline bool ReadElemAscii(PlyFile &file, PlyProperty &prop); - bool WriteElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); + inline bool WriteElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); - bool WriteElemAscii(PlyFile &file, PlyProperty &prop); + inline bool WriteElemAscii(PlyFile &file, PlyProperty &prop); private: template - void ReadBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); + inline void ReadBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); template - void ReadAscii(PlyFile &file, PlyProperty &prop); + inline void ReadAscii(PlyFile &file, PlyProperty &prop); template - void WriteBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); + inline void WriteBinary(PlyFile &file, PlyProperty &prop, bool fixEndian); template - void WriteAscii(PlyFile &file, PlyProperty &prop); + inline void WriteAscii(PlyFile &file, PlyProperty &prop); }; template - void DataDescriptor::Restart() + inline void DataDescriptor::Restart() { this->curPos = 0; } template template - void DataDescriptor::ReadBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) + inline void DataDescriptor::ReadBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) { - unsigned char* buffer; + char * buffer = nullptr; int size; int count = prop.CountValue(); int typeSize = prop.TypeSize(); if (prop.type >= NNP_LIST_UINT8_UINT32) { - if (prop.IsSigned()) - { - char cntList = 0; - file.ReadBinaryData(&cntList, sizeof(char)); - size = typeSize * cntList; - count = cntList; - } - else - { - unsigned char cntList = 0; - file.ReadBinaryData(&cntList, sizeof(char)); - size = typeSize * cntList; - count = cntList; - } + file.ReadBinaryData(buffer, sizeof(char)); + const int cntList = int(*(reinterpret_cast(buffer))); + size = typeSize * cntList; + count = cntList; } else size = typeSize * count; - buffer = new unsigned char[size]; file.ReadBinaryData(buffer, size); if (typeSize > 1 && fixEndian) - adjustEndianess(buffer, typeSize, count); + adjustEndianess(reinterpret_cast(buffer), typeSize, count); C* temp = (C*)buffer; float norm = 1.0f; @@ -2075,14 +2086,13 @@ namespace nanoply } unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); for (int i = 0; i < std::min(VectorSize, count); i++) - *(ScalarType *)(baseProp + i*sizeof(ScalarType)) = ScalarType(temp[i] * norm); + *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i] * norm); ++(this->curPos); - delete[] buffer; } template - bool DataDescriptor::ReadElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) + inline bool DataDescriptor::ReadElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) { if (prop.elem != elem) return false; @@ -2120,7 +2130,7 @@ namespace nanoply template template - void DataDescriptor::ReadAscii(PlyFile &file, PlyProperty &prop) + inline void DataDescriptor::ReadAscii(PlyFile &file, PlyProperty &prop) { int count = prop.CountValue(); if (prop.type >= NNP_LIST_UINT8_UINT32) @@ -2140,8 +2150,7 @@ namespace nanoply } unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); for (int i = 0; i < std::min(VectorSize, count); i++) - *(ScalarType *)(baseProp + i*sizeof(ScalarType)) = ScalarType(temp[i] * norm); - + *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i] * norm); delete[] temp; ++(this->curPos); } @@ -2149,7 +2158,7 @@ namespace nanoply template - bool DataDescriptor::ReadElemAscii(PlyFile &file, PlyProperty &prop) + inline bool DataDescriptor::ReadElemAscii(PlyFile &file, PlyProperty &prop) { if (prop.elem != elem) return false; @@ -2187,8 +2196,9 @@ namespace nanoply template template - void DataDescriptor::WriteBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) + inline void DataDescriptor::WriteBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) { + (void)fixEndian; int count = prop.CountValue(); C data[VectorSize]; if (prop.type >= NNP_LIST_UINT8_UINT32) @@ -2231,7 +2241,7 @@ namespace nanoply template - bool DataDescriptor::WriteElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) + inline bool DataDescriptor::WriteElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) { if (prop.elem != elem) return false; @@ -2268,7 +2278,7 @@ namespace nanoply template template - void DataDescriptor::WriteAscii(PlyFile &file, PlyProperty &prop) + inline void DataDescriptor::WriteAscii(PlyFile &file, PlyProperty &prop) { int count = prop.CountValue(); if (prop.type >= NNP_LIST_UINT8_UINT32) @@ -2315,7 +2325,7 @@ namespace nanoply template - bool DataDescriptor::WriteElemAscii(PlyFile &file, PlyProperty& prop) + inline bool DataDescriptor::WriteElemAscii(PlyFile &file, PlyProperty& prop) { if (prop.elem != elem) return false; @@ -2382,7 +2392,7 @@ namespace nanoply * @param meshElements Vector that defines how to manage the ply element data in memory. * @param info Info of the file to load. */ - bool OpenModel(Info& info, MeshDescriptor& meshElements) + inline bool OpenModel(Info& info, MeshDescriptor& meshElements) { PlyFile file; if (!file.OpenFileToRead(info.filename)) @@ -2415,7 +2425,7 @@ namespace nanoply PlyElement& pe = info.elemVec[i]; int j = 0; for (; j < meshElements.size(); j++) - if (ElemProcessing<0>(*meshElements[j], pe, file, false)) + if (ElemProcessing<0>(*meshElements[j], pe, file, fixEndian)) break; if (j == meshElements.size()) pe.SkipBinaryElementsInFile(file); @@ -2450,7 +2460,7 @@ namespace nanoply * @param meshElements Vector that defines how to manage the ply element data in memory. * @param info Info to saved in the PLY header. */ - bool SaveModel(std::string& filename, MeshDescriptor& meshElements, Info& info) + inline bool SaveModel(std::string& filename, MeshDescriptor& meshElements, Info& info) { PlyFile file; if (!file.OpenFileToWrite(filename)) diff --git a/wrap/nanoply/include/nanoplyWrapper.hpp b/wrap/nanoply/include/nanoplyWrapper.hpp index 197c0169..6fd77eab 100644 --- a/wrap/nanoply/include/nanoplyWrapper.hpp +++ b/wrap/nanoply/include/nanoplyWrapper.hpp @@ -496,7 +496,7 @@ namespace nanoply 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; } @@ -687,6 +687,7 @@ namespace nanoply infoSave.AddPlyElement(vertexElem); infoSave.AddPlyElement(edgeElem); infoSave.AddPlyElement(faceElem); + infoSave.textureFile = mesh.textures; std::vector meshDescr; meshDescr.push_back(&cameraDescr); meshDescr.push_back(&vertexDescr); From 037cf41afaa7a2784828296627239fc5d13bc34f Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Mon, 25 Jul 2016 12:34:12 +0200 Subject: [PATCH 17/91] - added missing namespace --- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index c4b1ba66..8b3b96ac 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -79,10 +79,10 @@ namespace vcg _perpoint_fixed_color_enabled = false; _perwire_fixed_color_enabled = true; - _perbbox_fixed_color = Color4b(Color4b::White); - _perpoint_fixed_color = Color4b(Color4b::White); + _perbbox_fixed_color = vcg::Color4b(Color4b::White); + _perpoint_fixed_color = vcg::Color4b(Color4b::White); _perwire_fixed_color = Color4b(Color4b::DarkGray); - _persolid_fixed_color = Color4b(Color4b::White); + _persolid_fixed_color = vcg::Color4b(Color4b::White); _persolid_fixed_color_enabled = false; _perbbox_mesh_color_enabled = false; From 9caa217af9411f2e2cec1a0e27d117243c672700 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Mon, 25 Jul 2016 12:36:23 +0200 Subject: [PATCH 18/91] - removed ply error in 3d model with wedge texture coord saved in ascii format --- wrap/io_trimesh/export_ply.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index 385b4487..5ac018ad 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -559,7 +559,7 @@ namespace vcg { else if( HasPerWedgeTexCoord(m) && (pi.mask & Mask::IOM_WEDGTEXCOORD) ) { fprintf(fpout,"%d ",fp->VN()*2); - for(int k=0;kVN()*2;++k) + for(int k=0;kVN();++k) fprintf(fpout,"%f %f " ,fp->WT(k).u() ,fp->WT(k).v() From 92eec412a5c37fdd03b4450c1e38a5816c024826 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Thu, 28 Jul 2016 12:32:13 +0200 Subject: [PATCH 19/91] - the DeletePerMeshAttribute signature (and semantics...) has been consistent with the other DeletePerXXXAttribute functions I discussed with Fabio about it --- vcg/complex/allocate.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 81da27ef..a664868e 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -1516,13 +1516,18 @@ public: return;} } - static void DeletePerMeshAttribute( MeshType & m, std::string name){ + // Generic DeleteAttribute. + // It must not crash if you try to delete a non existing attribute, + // because you do not have a way of asking for a handle of an attribute for which you do not know the type. + static bool DeletePerMeshAttribute( MeshType & m, std::string name){ AttrIterator i; PointerToAttribute h1; h1._name = name; i = m.mesh_attr.find(h1); - assert(i!=m.mesh_attr.end()); + if (i==m.mesh_attr.end()) + return false; delete ((SimpleTempDataBase *)(*i)._handle); m.mesh_attr.erase(i); + return true; } template From a1826b6adf46d8869dd71c1f93b035905f682c9b Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Fri, 29 Jul 2016 10:24:35 +0200 Subject: [PATCH 20/91] - added new functions to draw just a subset of the allocated buffers obj (just useful for some very specific meshlab plugins....other people should ignore them) --- ..._mesh_attributes_multi_viewer_bo_manager.h | 139 +++++++++++------- ..._mesh_attributes_multi_viewer_bo_manager.h | 6 + 2 files changed, 92 insertions(+), 53 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index 22e7949e..d34d6db6 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -369,61 +369,37 @@ namespace vcg const PVData& dt = it->second; //const InternalRendAtts& atts = it->second._intatts; - glPushAttrib(GL_ALL_ATTRIB_BITS); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glMultMatrix(_tr); - - if ((dt._glopts != NULL) && (dt._glopts->_perbbox_enabled)) - drawBBox(dt._glopts); - - if (dt.isPrimitiveActive(PR_SOLID)) - { - bool somethingmore = dt.isPrimitiveActive(PR_WIREFRAME_EDGES) || dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES) || dt.isPrimitiveActive(PR_POINTS); - if (somethingmore) - { - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.0, 1); - } - drawFilledTriangles(dt._intatts[size_t(PR_SOLID)],dt._glopts,textid); - if (somethingmore) - glDisable(GL_POLYGON_OFFSET_FILL); - } - - if (dt.isPrimitiveActive(PR_WIREFRAME_EDGES) || dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES)) - { - //InternalRendAtts tmpatts = atts; - bool pointstoo = dt.isPrimitiveActive(PR_POINTS); - - if (pointstoo) - { - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.0, 1); - } - bool solidtoo = dt.isPrimitiveActive(PR_SOLID); - - if (dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES)) - { - drawWiredTriangles(dt._intatts[size_t(PR_WIREFRAME_TRIANGLES)],dt._glopts,textid); - } - else - { - if (dt.isPrimitiveActive(PR_WIREFRAME_EDGES)) - drawEdges(dt._intatts[size_t(PR_WIREFRAME_EDGES)],dt._glopts); - } - - if (pointstoo || solidtoo) - glDisable(GL_POLYGON_OFFSET_FILL); - } - if (dt.isPrimitiveActive(PR_POINTS)) - drawPoints(dt._intatts[size_t(PR_POINTS)],it->second._glopts); - - glPopMatrix(); - glPopAttrib(); - glFlush(); - glFinish(); + drawFun(dt, textid); } + + void drawAllocatedAttributesSubset(UNIQUE_VIEW_ID_TYPE viewid,const PVData& dt, const std::vector& textid = std::vector()) const + { + typename ViewsMap::const_iterator it = _perviewreqatts.find(viewid); + if (it == _perviewreqatts.end()) + return; + + PVData tmp = dt; + + if (!(_currallocatedboatt[INT_ATT_NAMES::ATT_VERTPOSITION])) + { + for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm)) + { + tmp._pmmask[size_t(pm)] = 0; + tmp._intatts[size_t(pm)] = InternalRendAtts(); + } + } + else + { + for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm)) + { + tmp._intatts[size_t(pm)] = InternalRendAtts::intersectionSet(tmp._intatts[size_t(pm)],_meaningfulattsperprimitive[size_t(pm)]); + tmp._intatts[size_t(pm)] = InternalRendAtts::intersectionSet(tmp._intatts[size_t(pm)],_currallocatedboatt); + } + } + drawFun(dt, textid); + } + bool isBORenderingAvailable() const { return _borendering; @@ -1284,6 +1260,63 @@ namespace vcg return 0; } + void drawFun(const PVData& dt, const std::vector& textid = std::vector()) const + { + glPushAttrib(GL_ALL_ATTRIB_BITS); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glMultMatrix(_tr); + + if ((dt._glopts != NULL) && (dt._glopts->_perbbox_enabled)) + drawBBox(dt._glopts); + + if (dt.isPrimitiveActive(PR_SOLID)) + { + bool somethingmore = dt.isPrimitiveActive(PR_WIREFRAME_EDGES) || dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES) || dt.isPrimitiveActive(PR_POINTS); + if (somethingmore) + { + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1); + } + drawFilledTriangles(dt._intatts[size_t(PR_SOLID)], dt._glopts, textid); + if (somethingmore) + glDisable(GL_POLYGON_OFFSET_FILL); + } + + if (dt.isPrimitiveActive(PR_WIREFRAME_EDGES) || dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES)) + { + //InternalRendAtts tmpatts = atts; + bool pointstoo = dt.isPrimitiveActive(PR_POINTS); + + if (pointstoo) + { + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0, 1); + } + bool solidtoo = dt.isPrimitiveActive(PR_SOLID); + + if (dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES)) + { + drawWiredTriangles(dt._intatts[size_t(PR_WIREFRAME_TRIANGLES)], dt._glopts, textid); + } + else + { + if (dt.isPrimitiveActive(PR_WIREFRAME_EDGES)) + drawEdges(dt._intatts[size_t(PR_WIREFRAME_EDGES)], dt._glopts); + } + + if (pointstoo || solidtoo) + glDisable(GL_POLYGON_OFFSET_FILL); + } + if (dt.isPrimitiveActive(PR_POINTS)) + drawPoints(dt._intatts[size_t(PR_POINTS)], dt._glopts); + + glPopMatrix(); + glPopAttrib(); + glFlush(); + glFinish(); + } + void drawFilledTriangles(const InternalRendAtts& req,const GL_OPTIONS_DERIVED_TYPE* glopts,const std::vector& textureindex = std::vector()) const { if (_mesh.VN() == 0) diff --git a/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h b/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h index 82333932..470cec01 100644 --- a/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h @@ -74,6 +74,12 @@ namespace vcg vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::draw(viewid,_textids.textId()); } + void drawAllocatedAttributesSubset(UNIQUE_VIEW_ID_TYPE viewid,const PerViewData& dt) const + { + QReadLocker locker(&_lock); + vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::drawAllocatedAttributesSubset(viewid,dt,_textids.textId()); + } + bool isBORenderingAvailable() const { QReadLocker locker(&_lock); From 36ff9b0c58e8724283183ff30bbf309ced397d2d Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Sun, 31 Jul 2016 11:50:24 +0200 Subject: [PATCH 21/91] - added missing include file --- wrap/gl/pick.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wrap/gl/pick.h b/wrap/gl/pick.h index 70c6d90c..c8878491 100644 --- a/wrap/gl/pick.h +++ b/wrap/gl/pick.h @@ -26,6 +26,8 @@ #include #include +#include "gl_type_name.h" + namespace vcg{ template From f2731fccff7913ae0e4eeb64ca11f75f357c35f8 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Sun, 31 Jul 2016 12:37:51 +0200 Subject: [PATCH 22/91] Removed useless preserveSelection flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit it is meaningless to have this option in a function that start from current selection… --- vcg/complex/algorithms/update/selection.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vcg/complex/algorithms/update/selection.h b/vcg/complex/algorithms/update/selection.h index 6f5d0528..ef97bcaa 100644 --- a/vcg/complex/algorithms/update/selection.h +++ b/vcg/complex/algorithms/update/selection.h @@ -441,9 +441,8 @@ static size_t FaceOutOfRangeEdge(MeshType &m, ScalarType MinEdgeThr, ScalarType } /// \brief This function expand current selection to cover the whole connected component. -static size_t FaceConnectedFF(MeshType &m, bool preserveSelection=false) +static size_t FaceConnectedFF(MeshType &m) { - if(!preserveSelection) FaceClear(m); // it also assumes that the FF adjacency is well computed. RequireFFAdjacency(m); UpdateFlags::FaceClearV(m); From 64aaeaf2d0566cf822bb90dd1fe93ccaa512c2d8 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Tue, 30 Aug 2016 02:36:57 +0200 Subject: [PATCH 23/91] - added new setPerAllViewsInfo function --- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index d34d6db6..1833d742 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -347,6 +347,16 @@ namespace vcg _perviewreqatts[viewid] = copydt; } + void setPerAllViewsInfo(const PVData& data) + { + ///cleanup stage...if an attribute impossible for a primitive modality is still here (it should not be...) we change the required atts into the view + PVData copydt(data); + for (PRIMITIVE_MODALITY pm = PRIMITIVE_MODALITY(0); pm < PR_ARITY; pm = next(pm)) + copydt._intatts[pm] = InternalRendAtts::intersectionSet(copydt._intatts[size_t(pm)], _meaningfulattsperprimitive[size_t(pm)]); + for (typename ViewsMap::iterator it = _perviewreqatts.begin(); it != _perviewreqatts.end(); ++it) + it->second = copydt; + } + bool removeView(UNIQUE_VIEW_ID_TYPE viewid) { typename ViewsMap::iterator it = _perviewreqatts.find(viewid); @@ -1158,7 +1168,7 @@ namespace vcg { glDisableClientState(bobj->_clientstatetag); } - + //glBufferData(bobj->_target, sizeof(vcg::Point3f)*_primitivebatch, 0, GL_DYNAMIC_DRAW); glDeleteBuffers(1,&(bobj->_bohandle)); glFlush(); glFinish(); From 92dfeec652023c548d2cf239edef0dc602f96193 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Tue, 30 Aug 2016 02:37:19 +0200 Subject: [PATCH 24/91] - added missing ifndef --- wrap/gl/gl_type_name.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wrap/gl/gl_type_name.h b/wrap/gl/gl_type_name.h index f56f24b2..fa1b8fbc 100644 --- a/wrap/gl/gl_type_name.h +++ b/wrap/gl/gl_type_name.h @@ -21,6 +21,9 @@ * * ****************************************************************************/ +#ifndef __VCG_GL_TYPE_NAME +#define __VCG_GL_TYPE_NAME + namespace vcg { template @@ -38,4 +41,6 @@ namespace vcg typedef GLdouble ScalarType; static GLenum SCALAR() { return GL_DOUBLE; } }; -} \ No newline at end of file +} + +#endif \ No newline at end of file From cda696c536f1801e0eb363ebf4fac613d7d47874 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Tue, 30 Aug 2016 02:37:52 +0200 Subject: [PATCH 25/91] - properly rewritten ifndef for windows systems --- wrap/ply/plystuff.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wrap/ply/plystuff.h b/wrap/ply/plystuff.h index 54a056f5..e799d29a 100644 --- a/wrap/ply/plystuff.h +++ b/wrap/ply/plystuff.h @@ -56,12 +56,14 @@ Cleaning of the automatic bbox caching support for ply files. First working vers #include #include -#include #include #ifdef WIN32 #include +#else +#include #endif + #include #include using namespace vcg; From eacb3c0d46002ca362897b4a8dd2415380089466 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Tue, 30 Aug 2016 02:38:18 +0200 Subject: [PATCH 26/91] - added setPerAllViewsInfo function --- ..._thread_safe_mesh_attributes_multi_viewer_bo_manager.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h b/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h index 470cec01..f0c7f59c 100644 --- a/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h @@ -47,7 +47,7 @@ namespace vcg void meshAttributesUpdated(bool hasmeshconnectivitychanged,const GLMeshAttributesInfo::RendAtts& changedrendatts) { QWriteLocker locker(&_lock); - vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::meshAttributesUpdated(hasmeshconnectivitychanged,changedrendatts); + vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::meshAttributesUpdated(hasmeshconnectivitychanged, changedrendatts); } bool getPerViewInfo(UNIQUE_VIEW_ID_TYPE viewid,PerViewData& dt) const @@ -62,6 +62,12 @@ namespace vcg vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::setPerViewInfo(viewid,dt); } + void setPerAllViewsInfo(const PerViewData& dt) + { + QWriteLocker locker(&_lock); + vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::setPerAllViewsInfo(dt); + } + void removeView(UNIQUE_VIEW_ID_TYPE viewid) { QWriteLocker locker(&_lock); From 5c7279088476a342e0702b563325d76c676c9ec9 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Wed, 31 Aug 2016 13:45:11 +0200 Subject: [PATCH 27/91] - fixed RenderingModalityGLOptions init bug --- vcg/math/matrix44.h | 8 +++++++- vcg/math/shot.h | 5 ++++- wrap/gl/gl_mesh_attributes_info.h | 1 + wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 6 ++++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/vcg/math/matrix44.h b/vcg/math/matrix44.h index fb2442e6..ef440e93 100644 --- a/vcg/math/matrix44.h +++ b/vcg/math/matrix44.h @@ -138,7 +138,13 @@ public: void operator*=( const T k ); template - void ToMatrix(Matrix44Type & m) const {for(int i = 0; i < 16; i++) m.V()[i]=V()[i];} + void ToMatrix(Matrix44Type & m) const + { + for(int i = 0; i < 16; i++) + { + m.V()[i]= V()[i]; + } + } void ToEulerAngles(T &alpha, T &beta, T &gamma); diff --git a/vcg/math/shot.h b/vcg/math/shot.h index f0a4b1df..978100b2 100644 --- a/vcg/math/shot.h +++ b/vcg/math/shot.h @@ -75,7 +75,7 @@ public: RotoType rot; // rotation Point3 tra; // viewpoint public: - ReferenceFrame(){} + ReferenceFrame():rot(),tra(){} void SetIdentity(){ rot.SetIdentity(); tra = Point3(0.0,0.0,0.0);} void SetTra(const Point3 & tr) {tra = tr;} @@ -87,18 +87,21 @@ public: Camera Intrinsics; // the camera that made the shot ReferenceFrame Extrinsics; // the position and orientation of the camera Shot(const Camera &i, const ReferenceFrame &e) + :Intrinsics(),Extrinsics() { Intrinsics = i; Extrinsics = e; } Shot(const Camera &c) + :Intrinsics(),Extrinsics() { Intrinsics = c; Extrinsics.SetIdentity(); } Shot() + :Intrinsics(),Extrinsics() { Extrinsics.SetIdentity(); } diff --git a/wrap/gl/gl_mesh_attributes_info.h b/wrap/gl/gl_mesh_attributes_info.h index b3fe0cdf..60d96fb1 100644 --- a/wrap/gl/gl_mesh_attributes_info.h +++ b/wrap/gl/gl_mesh_attributes_info.h @@ -288,6 +288,7 @@ namespace vcg } }; + protected: struct INT_ATT_NAMES : public ATT_NAMES { diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index 1833d742..d1184a64 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -75,19 +75,21 @@ namespace vcg RenderingModalityGLOptions() { _perbbox_enabled = false; + _perbbox_fixed_color_enabled = true; _perpoint_fixed_color_enabled = false; _perwire_fixed_color_enabled = true; - + _persolid_fixed_color_enabled = true; + _perbbox_fixed_color = vcg::Color4b(Color4b::White); _perpoint_fixed_color = vcg::Color4b(Color4b::White); _perwire_fixed_color = Color4b(Color4b::DarkGray); _persolid_fixed_color = vcg::Color4b(Color4b::White); - _persolid_fixed_color_enabled = false; _perbbox_mesh_color_enabled = false; _perpoint_mesh_color_enabled = false; _perwire_mesh_color_enabled = false; + _persolid_mesh_color_enabled = false; _perpoint_dot_enabled = false; From 0e454e5c87eff5a39d4166bbd5f7394ff019fa22 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Thu, 1 Sep 2016 05:46:46 +0200 Subject: [PATCH 28/91] - added empty space in order to force github to recognize that something changed --- wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h | 1 + 1 file changed, 1 insertion(+) diff --git a/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h b/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h index f0c7f59c..cd09ff7a 100644 --- a/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/qt/qt_thread_safe_mesh_attributes_multi_viewer_bo_manager.h @@ -86,6 +86,7 @@ namespace vcg vcg::NotThreadSafeGLMeshAttributesMultiViewerBOManager::drawAllocatedAttributesSubset(viewid,dt,_textids.textId()); } + bool isBORenderingAvailable() const { QReadLocker locker(&_lock); From 16879ec6ca8ad1119e07b5b1a943064e2decedb0 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Thu, 8 Sep 2016 05:22:53 +0200 Subject: [PATCH 29/91] - removed "no texture binded with per points vertex texture modality" bug --- vcg/complex/algorithms/update/texture.h | 1 + ..._mesh_attributes_multi_viewer_bo_manager.h | 44 +++++++++++++++---- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/vcg/complex/algorithms/update/texture.h b/vcg/complex/algorithms/update/texture.h index d0a8339a..c454ddd1 100644 --- a/vcg/complex/algorithms/update/texture.h +++ b/vcg/complex/algorithms/update/texture.h @@ -111,6 +111,7 @@ static void WedgeTexFromVertexTex(ComputeMeshType &m) { (*fi).WT(i).U() = (*fi).V(i)->T().U(); (*fi).WT(i).V() = (*fi).V(i)->T().V(); + (*fi).WT(i).N() = 0; } } } diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index d1184a64..60fcf349 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -1321,7 +1321,7 @@ namespace vcg glDisable(GL_POLYGON_OFFSET_FILL); } if (dt.isPrimitiveActive(PR_POINTS)) - drawPoints(dt._intatts[size_t(PR_POINTS)], dt._glopts); + drawPoints(dt._intatts[size_t(PR_POINTS)], dt._glopts,textid); glPopMatrix(); glPopAttrib(); @@ -1587,7 +1587,7 @@ namespace vcg glEnd(); } - void drawPoints(const InternalRendAtts& req,GL_OPTIONS_DERIVED_TYPE* glopts) const + void drawPoints(const InternalRendAtts& req,GL_OPTIONS_DERIVED_TYPE* glopts, const std::vector& textureindex = std::vector()) const { if (_mesh.VN() == 0) return; @@ -1597,7 +1597,7 @@ namespace vcg bool isgloptsvalid = (glopts != NULL); - if (isgloptsvalid && glopts->_perpoint_noshading) + if ((isgloptsvalid && glopts->_perpoint_noshading) || (isgloptsvalid && glopts->_perpoint_dot_enabled)) glDisable(GL_LIGHTING); else if ((!isgloptsvalid) || req[INT_ATT_NAMES::ATT_VERTNORMAL]) @@ -1617,16 +1617,23 @@ namespace vcg glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); - if (req[INT_ATT_NAMES::ATT_VERTTEXTURE]) - glEnable(GL_TEXTURE_2D); - else - glDisable(GL_TEXTURE_2D); + if (req[INT_ATT_NAMES::ATT_VERTTEXTURE]) + { + glEnable(GL_TEXTURE_2D); + if (textureindex.size() > 0) + glBindTexture(GL_TEXTURE_2D, textureindex[0]); + else + glBindTexture(GL_TEXTURE_2D, 0); + } + else + glDisable(GL_TEXTURE_2D); //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _bo[GLMeshAttributesInfo::ATT_VERTINDEX]->_bohandle); if (glopts != NULL) { - glPointSize(glopts->_perpoint_pointsize); - if(glopts->_perpoint_pointsmooth_enabled) + if (!glopts->_perpoint_dot_enabled) + glPointSize(glopts->_perpoint_pointsize); + if ((glopts->_perpoint_pointsmooth_enabled) || (glopts->_perpoint_dot_enabled)) glEnable(GL_POINT_SMOOTH); else glDisable(GL_POINT_SMOOTH); @@ -1650,11 +1657,30 @@ namespace vcg pointsize = glopts->_perpoint_pointsize; glPointSize(pointsize); } + + if (glopts->_perpoint_dot_enabled) + { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor(vcg::Color4b(vcg::Color4b::Black)); + glDepthRange(0.0, 0.9999); + glDepthFunc(GL_LEQUAL); + glPointSize(glopts->_perpoint_pointsize + 0.5); + } } if (isBORenderingAvailable()) drawPointsBO(req); else drawPointsIM(req); + + if ((glopts != NULL) && (glopts->_perpoint_dot_enabled)) + { + glPointSize(glopts->_perpoint_pointsize - 1); + if (isBORenderingAvailable()) + drawPointsBO(req); + else + drawPointsIM(req); + } glPopAttrib(); } From 01787cad96c654ff82100d7fec42d936ce6efce6 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Thu, 8 Sep 2016 05:25:43 +0200 Subject: [PATCH 30/91] - rolled back to previous github version of the file --- vcg/complex/algorithms/update/texture.h | 1 - 1 file changed, 1 deletion(-) diff --git a/vcg/complex/algorithms/update/texture.h b/vcg/complex/algorithms/update/texture.h index c454ddd1..d0a8339a 100644 --- a/vcg/complex/algorithms/update/texture.h +++ b/vcg/complex/algorithms/update/texture.h @@ -111,7 +111,6 @@ static void WedgeTexFromVertexTex(ComputeMeshType &m) { (*fi).WT(i).U() = (*fi).V(i)->T().U(); (*fi).WT(i).V() = (*fi).V(i)->T().V(); - (*fi).WT(i).N() = 0; } } } From cb4f24383f7cce1c165f70f085eb5d8dee7cf550 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Mon, 12 Sep 2016 08:58:29 +0200 Subject: [PATCH 31/91] - various bugs fixed --- vcg/complex/algorithms/update/texture.h | 1 + ..._mesh_attributes_multi_viewer_bo_manager.h | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/vcg/complex/algorithms/update/texture.h b/vcg/complex/algorithms/update/texture.h index d0a8339a..c454ddd1 100644 --- a/vcg/complex/algorithms/update/texture.h +++ b/vcg/complex/algorithms/update/texture.h @@ -111,6 +111,7 @@ static void WedgeTexFromVertexTex(ComputeMeshType &m) { (*fi).WT(i).U() = (*fi).V(i)->T().U(); (*fi).WT(i).V() = (*fi).V(i)->T().V(); + (*fi).WT(i).N() = 0; } } } diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index 60fcf349..a7484f75 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -1307,14 +1307,21 @@ namespace vcg } bool solidtoo = dt.isPrimitiveActive(PR_SOLID); - if (dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES)) - { - drawWiredTriangles(dt._intatts[size_t(PR_WIREFRAME_TRIANGLES)], dt._glopts, textid); - } + /*EDGE | TRI | DRAW + --------------------------------- + TRUE TRUE EDGE + TRUE FALSE EDGE + FALSE TRUE TRI + FALSE FALSE NOTHING */ + + if (dt.isPrimitiveActive(PR_WIREFRAME_EDGES)) + drawEdges(dt._intatts[size_t(PR_WIREFRAME_EDGES)], dt._glopts); else { - if (dt.isPrimitiveActive(PR_WIREFRAME_EDGES)) - drawEdges(dt._intatts[size_t(PR_WIREFRAME_EDGES)], dt._glopts); + if (dt.isPrimitiveActive(PR_WIREFRAME_TRIANGLES)) + { + drawWiredTriangles(dt._intatts[size_t(PR_WIREFRAME_TRIANGLES)], dt._glopts, textid); + } } if (pointstoo || solidtoo) From 5e89a6a5f7bdb8160fa3b0f35f3585570028e881 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Mon, 12 Sep 2016 09:01:40 +0200 Subject: [PATCH 32/91] - roll back --- vcg/complex/algorithms/update/texture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/update/texture.h b/vcg/complex/algorithms/update/texture.h index c454ddd1..c6f0b9b0 100644 --- a/vcg/complex/algorithms/update/texture.h +++ b/vcg/complex/algorithms/update/texture.h @@ -111,7 +111,7 @@ static void WedgeTexFromVertexTex(ComputeMeshType &m) { (*fi).WT(i).U() = (*fi).V(i)->T().U(); (*fi).WT(i).V() = (*fi).V(i)->T().V(); - (*fi).WT(i).N() = 0; + //(*fi).WT(i).N() = 0; } } } From 684bb9ecfbd0ae94ddafd12b495170875fe40cef Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Thu, 15 Sep 2016 06:10:18 +0200 Subject: [PATCH 33/91] - fixed "no per mesh color applied on polygonal wire rendering" bug --- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index a7484f75..e084448e 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -1731,8 +1731,7 @@ namespace vcg if (_mesh.VN() == 0) return; glPushAttrib(GL_ALL_ATTRIB_BITS); - - + bool isgloptsvalid = (glopts != NULL); glEnable(GL_COLOR_MATERIAL); @@ -1751,8 +1750,13 @@ namespace vcg if (!(isgloptsvalid) || colordefinedenabled) { vcg::Color4b tmpcol = vcg::Color4b(vcg::Color4b::DarkGray); - if (colordefinedenabled) - tmpcol = glopts->_perwire_fixed_color; + if (colordefinedenabled) + { + if (glopts->_perwire_fixed_color_enabled) + tmpcol = glopts->_perwire_fixed_color; + else + tmpcol = _mesh.cC(); + } glColor(tmpcol); } From 9b9e4f668198141018fda2d8b6aee915c143cbc5 Mon Sep 17 00:00:00 2001 From: gianpaolopalma Date: Mon, 3 Oct 2016 10:09:27 +0200 Subject: [PATCH 34/91] Bug fixed for an implicit cast to float --- wrap/nanoply/include/nanoply.hpp | 61 +++++++++++++++++++++---------- wrap/nanoply/nanoply_vcg/main.cpp | 26 ++++++++----- 2 files changed, 57 insertions(+), 30 deletions(-) diff --git a/wrap/nanoply/include/nanoply.hpp b/wrap/nanoply/include/nanoply.hpp index 810d6fd5..071f5365 100644 --- a/wrap/nanoply/include/nanoply.hpp +++ b/wrap/nanoply/include/nanoply.hpp @@ -511,7 +511,7 @@ namespace nanoply bufferOffset = 0; } //memcpy(dest, &buffer[bufferOffset], nByte); - dest = buffer + bufferOffset; + dest = buffer + bufferOffset; bufferOffset += nByte; return true; } @@ -2075,18 +2075,23 @@ namespace nanoply if (typeSize > 1 && fixEndian) adjustEndianess(reinterpret_cast(buffer), typeSize, count); + unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); C* temp = (C*)buffer; - float norm = 1.0f; if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) { + float norm = 1.0f; if (std::is_same::value && std::is_same::value) norm = 1.0f / 255.0f; else if (std::is_same::value && std::is_same::value) norm = 255.0f; + for (int i = 0; i < std::min(VectorSize, count); i++) + *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i] * norm); } - unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); - for (int i = 0; i < std::min(VectorSize, count); i++) - *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i] * norm); + else + { + for (int i = 0; i < std::min(VectorSize, count); i++) + *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i]); + } ++(this->curPos); } @@ -2140,17 +2145,22 @@ namespace nanoply for (int i = 0; i < count; i++) file.ReadAsciiData(temp[i]); - float norm = 1.0f; + unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) { + float norm = 1.0f; if (std::is_same::value && prop.type == NNP_UINT8) norm = 1.0f / 255.0f; else if (std::is_same::value && prop.type == NNP_FLOAT32) norm = 255.0f; + for (int i = 0; i < std::min(VectorSize, count); i++) + *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i] * norm); } - unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); - for (int i = 0; i < std::min(VectorSize, count); i++) - *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i] * norm); + else + { + for (int i = 0; i < std::min(VectorSize, count); i++) + *((ScalarType *)(baseProp + i*sizeof(ScalarType))) = ScalarType(temp[i]); + } delete[] temp; ++(this->curPos); } @@ -2217,19 +2227,24 @@ namespace nanoply } } - float norm = 1.0f; + C temp = 0; + unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) { + float norm = 1.0f; if (std::is_same::value && std::is_same::value) norm = 255.0f; else if (std::is_same::value && std::is_same::value) norm = 1.0f / 255.0f; + for (int i = 0; i < std::min(VectorSize, count); i++) + data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType))) * norm); } + else + { + for (int i = 0; i < std::min(VectorSize, count); i++) + data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType)))); + } - C temp = 0; - unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); - for (int i = 0; i < std::min(VectorSize, count); i++) - data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType))) * norm); if (sizeof(C) > 1 && fixEndian) adjustEndianess((unsigned char*)data, sizeof(C), std::min(VectorSize, count)); @@ -2298,19 +2313,25 @@ namespace nanoply file.WriteAsciiData(std::string(" ")); } - float norm = 1.0; + C data[VectorSize]; + unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA)) { + float norm = 1.0; if (std::is_same::value && prop.type == NNP_UINT8) norm = 255.0f; else if (std::is_same::value && prop.type == NNP_FLOAT32) norm = 1.0f / 255.0f; + for (int i = 0; i < std::min(VectorSize, count); i++) + data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType))) * norm); } - - C data[VectorSize]; - unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType); - for (int i = 0; i < std::min(VectorSize, count); i++) - data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType))) * norm); + else + { + for (int i = 0; i < std::min(VectorSize, count); i++) + data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType)))); + } + + for (int i = 0; i < (count - VectorSize); i++) data[i] = 0; diff --git a/wrap/nanoply/nanoply_vcg/main.cpp b/wrap/nanoply/nanoply_vcg/main.cpp index 14236dd3..62a95b41 100644 --- a/wrap/nanoply/nanoply_vcg/main.cpp +++ b/wrap/nanoply/nanoply_vcg/main.cpp @@ -71,8 +71,8 @@ public: faceBarycenter[i] = vcg::Barycenter(face[i]); material().resize(2); - material()[0] = { vcg::Point3f(0.1, 0.2, 0.3), vcg::Point3f(0.3, 0.3, 0.3), 5.0 }; - material()[1] = { vcg::Point3f(0.1, 0.1, 0.1), vcg::Point3f(0.5, 0.3, 0.4), 50.0 }; + material()[0] = { vcg::Point3f(0.1f, 0.2f, 0.3f), vcg::Point3f(0.3f, 0.3f, 0.3f), 5.0f }; + material()[1] = { vcg::Point3f(0.1f, 0.1f, 0.1f), vcg::Point3f(0.5f, 0.3f, 0.4f), 50.0f }; } }; @@ -87,9 +87,12 @@ bool Load(const char* filename, MyMesh& mesh) mesh.material().resize(count); customAttrib.AddVertexAttribDescriptor(std::string("materialId"), nanoply::NNP_INT32, NULL); customAttrib.AddFaceAttribDescriptor(std::string("barycenter"), nanoply::NNP_LIST_UINT8_FLOAT32, NULL); - customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("kd"), nanoply::NNP_FLOAT32, mesh.material()[0].kd.V()); - customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("ks"), nanoply::NNP_FLOAT32, mesh.material()[0].ks.V()); - customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("rho"), nanoply::NNP_FLOAT32, &mesh.material()[0].rho); + if (count > 0) + { + customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("kd"), nanoply::NNP_FLOAT32, mesh.material()[0].kd.V()); + customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("ks"), nanoply::NNP_FLOAT32, mesh.material()[0].ks.V()); + customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("rho"), nanoply::NNP_FLOAT32, &mesh.material()[0].rho); + } //Load the ply file unsigned int mask = 0; @@ -102,7 +105,7 @@ bool Load(const char* filename, MyMesh& mesh) mask |= nanoply::NanoPlyWrapper::IO_FACENORMAL; mask |= nanoply::NanoPlyWrapper::IO_FACEATTRIB; mask |= nanoply::NanoPlyWrapper::IO_MESHATTRIB; - return (nanoply::NanoPlyWrapper::LoadModel(filename, mesh, mask, customAttrib) != 0); + return (nanoply::NanoPlyWrapper::LoadModel(filename, mesh, mask, customAttrib) != 0); } @@ -113,10 +116,13 @@ bool Save(const char* filename, MyMesh& mesh, bool binary) nanoply::NanoPlyWrapper::CustomAttributeDescriptor customAttrib; customAttrib.AddVertexAttribDescriptor(std::string("materialId"), nanoply::NNP_INT32, &mesh.vertexMaterial[0]); customAttrib.AddFaceAttribDescriptor(std::string("barycenter"), nanoply::NNP_LIST_UINT8_FLOAT32, mesh.faceBarycenter[0].V()); - customAttrib.AddMeshAttrib(std::string("material"), 2); - customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("kd"), nanoply::NNP_LIST_UINT8_FLOAT32, mesh.material()[0].kd.V()); - customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("ks"), nanoply::NNP_LIST_UINT8_FLOAT32, mesh.material()[0].ks.V()); - customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("rho"), nanoply::NNP_FLOAT32, &mesh.material()[0].rho); + if (mesh.material().size() > 0) + { + customAttrib.AddMeshAttrib(std::string("material"), mesh.material().size()); + customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("kd"), nanoply::NNP_LIST_UINT8_FLOAT32, mesh.material()[0].kd.V()); + customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("ks"), nanoply::NNP_LIST_UINT8_FLOAT32, mesh.material()[0].ks.V()); + customAttrib.AddMeshAttribDescriptor(std::string("material"), std::string("rho"), nanoply::NNP_FLOAT32, &mesh.material()[0].rho); + } //Save the ply file unsigned int mask = 0; From 07fe5908146d0c241ac581874c66abbf57947ee0 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Fri, 7 Oct 2016 00:49:34 +0200 Subject: [PATCH 35/91] Hue in HSV is wrapped if out of range for sake of robustness --- vcg/space/color4.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vcg/space/color4.h b/vcg/space/color4.h index a16381da..bcc31a53 100644 --- a/vcg/space/color4.h +++ b/vcg/space/color4.h @@ -180,6 +180,8 @@ public: (*this)[3]=255; return; } + float dummy; + h = modff(h,&dummy); if(h==1.0) h = 0.0; int i = int( floor(h*6.0) ); From 8b90ba72a36fb5e8b9a141cc4575369feecd0dfc Mon Sep 17 00:00:00 2001 From: gianpaolopalma Date: Fri, 7 Oct 2016 17:01:39 +0200 Subject: [PATCH 36/91] Bug fixed by removing the deferencing of the end() iterator of the container --- vcg/complex/allocate.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index a664868e..00df47b9 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -52,13 +52,13 @@ template size_t Index(MeshType &m, const typename MeshType::HEdgeType* h) {return h-&*m.hedge.begin();} template -bool IsValidPointer( MeshType & m, const typename MeshType::VertexType *vp) { return ( (vp >= &*m.vert.begin()) && ( vp < &*m.vert.end()) ); } +bool IsValidPointer( MeshType & m, const typename MeshType::VertexType *vp) { return ( m.vert.size() > 0 && (vp >= &*m.vert.begin()) && (vp <= &m.vert.back()) ); } template -bool IsValidPointer( MeshType & m, const typename MeshType::EdgeType *ep) { return ( (ep >= &*m.edge.begin()) && ( ep < &*m.edge.end()) ); } +bool IsValidPointer(MeshType & m, const typename MeshType::EdgeType *ep) { return ( m.edge.size() > 0 && (ep >= &*m.edge.begin()) && (ep <= &m.edge.back())); } template -bool IsValidPointer( MeshType & m, const typename MeshType::FaceType *fp) { return ( (fp >= &*m.face.begin()) && ( fp < &*m.face.end()) ); } +bool IsValidPointer(MeshType & m, const typename MeshType::FaceType *fp) { return ( m.face.size() > 0 && (fp >= &*m.face.begin()) && (fp <= &m.face.back())); } template -bool IsValidPointer( MeshType & m, const typename MeshType::HEdgeType *hp) { return ( (hp >= &*m.hedge.begin())&& ( hp < &*m.hedge.end()) ); } +bool IsValidPointer(MeshType & m, const typename MeshType::HEdgeType *hp) { return ( m.hedge.size() > 0 && (hp >= &*m.hedge.begin()) && (hp <= &m.hedge.back())); } template void ReorderAttribute(ATTR_CONT &c, std::vector & newVertIndex, MeshType & /* m */){ From 20fa52181fc0b127b6534f8507a7482b872db8c3 Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Thu, 13 Oct 2016 04:28:00 +0200 Subject: [PATCH 37/91] - fixed "if there is color both vertex/face colors are enabled even if there is just one of them" bug --- vcg/complex/algorithms/update/texture.h | 2 +- wrap/io_trimesh/import_off.h | 1409 ++++++++++++----------- 2 files changed, 708 insertions(+), 703 deletions(-) diff --git a/vcg/complex/algorithms/update/texture.h b/vcg/complex/algorithms/update/texture.h index c6f0b9b0..c454ddd1 100644 --- a/vcg/complex/algorithms/update/texture.h +++ b/vcg/complex/algorithms/update/texture.h @@ -111,7 +111,7 @@ static void WedgeTexFromVertexTex(ComputeMeshType &m) { (*fi).WT(i).U() = (*fi).V(i)->T().U(); (*fi).WT(i).V() = (*fi).V(i)->T().V(); - //(*fi).WT(i).N() = 0; + (*fi).WT(i).N() = 0; } } } diff --git a/wrap/io_trimesh/import_off.h b/wrap/io_trimesh/import_off.h index 4eb7b3ae..80e9f382 100644 --- a/wrap/io_trimesh/import_off.h +++ b/wrap/io_trimesh/import_off.h @@ -29,775 +29,780 @@ #include namespace vcg { -namespace tri { -namespace io { + namespace tri { + namespace io { -// /** \addtogroup */ -// /* @{ */ -/** - This class encapsulate a filter for importing OFF meshes. - A basic description of the OFF file format can be found at http://www.geomview.org/docs/html/geomview_41.html - */ -template -class ImporterOFF -{ -public: + // /** \addtogroup */ + // /* @{ */ + /** + This class encapsulate a filter for importing OFF meshes. + A basic description of the OFF file format can be found at http://www.geomview.org/docs/html/geomview_41.html + */ + template + class ImporterOFF + { + public: - typedef typename MESH_TYPE::VertexType VertexType; - typedef typename MESH_TYPE::VertexIterator VertexIterator; - typedef typename MESH_TYPE::VertexPointer VertexPointer; - typedef typename MESH_TYPE::FaceType FaceType; - typedef typename MESH_TYPE::FaceIterator FaceIterator; - typedef typename MESH_TYPE::FacePointer FacePointer; - typedef typename MESH_TYPE::CoordType CoordType; - typedef typename MESH_TYPE::ScalarType ScalarType; + typedef typename MESH_TYPE::VertexType VertexType; + typedef typename MESH_TYPE::VertexIterator VertexIterator; + typedef typename MESH_TYPE::VertexPointer VertexPointer; + typedef typename MESH_TYPE::FaceType FaceType; + typedef typename MESH_TYPE::FaceIterator FaceIterator; + typedef typename MESH_TYPE::FacePointer FacePointer; + typedef typename MESH_TYPE::CoordType CoordType; + typedef typename MESH_TYPE::ScalarType ScalarType; - // OFF codes - enum OFFCodes {NoError=0, CantOpen, InvalidFile, - InvalidFile_MissingOFF, - UnsupportedFormat, ErrorNotTriangularFace,ErrorHighDimension,ErrorDegenerateFace}; + // OFF codes + enum OFFCodes { + NoError = 0, CantOpen, InvalidFile, + InvalidFile_MissingOFF, + UnsupportedFormat, ErrorNotTriangularFace, ErrorHighDimension, ErrorDegenerateFace + }; - /*! - * Standard call for knowing the meaning of an error code - * \param message_code The code returned by Open - * \return The string describing the error code - */ - static const char* ErrorMsg(int message_code) - { - static const char* error_msg[] = - { - "No errors", "Can't open file", "Invalid file", - "Invalid file: OFF file should have in the first line the OFF keyword as a first token", - "Unsupported format", "Face with more than 3 vertices","File with high dimensional vertexes are not supported", "Error Degenerate Face with less than 3 vertices" }; + /*! + * Standard call for knowing the meaning of an error code + * \param message_code The code returned by Open + * \return The string describing the error code + */ + static const char* ErrorMsg(int message_code) + { + static const char* error_msg[] = + { + "No errors", "Can't open file", "Invalid file", + "Invalid file: OFF file should have in the first line the OFF keyword as a first token", + "Unsupported format", "Face with more than 3 vertices","File with high dimensional vertexes are not supported", "Error Degenerate Face with less than 3 vertices" }; - if(message_code>6 || message_code<0) - return "Unknown error"; - else - return error_msg[message_code]; - }; + if (message_code > 6 || message_code < 0) + return "Unknown error"; + else + return error_msg[message_code]; + }; - /** - * Load only the properties of the 3D objects. - * - * \param filename the name of the file to read from - * \param loadmask the mask which encodes the properties - * \return the operation result - */ - static bool LoadMask(const char *filename, int &loadmask) - { - // To obtain the loading mask all the file must be parsed - // to distinguish between per-vertex and per-face color attribute. - loadmask=0; - MESH_TYPE dummyMesh; - return (Open(dummyMesh, filename, loadmask)==NoError); - } + /** + * Load only the properties of the 3D objects. + * + * \param filename the name of the file to read from + * \param loadmask the mask which encodes the properties + * \return the operation result + */ + static bool LoadMask(const char *filename, int &loadmask) + { + // To obtain the loading mask all the file must be parsed + // to distinguish between per-vertex and per-face color attribute. + loadmask = 0; + MESH_TYPE dummyMesh; + return (Open(dummyMesh, filename, loadmask) == NoError); + } - static int Open(MESH_TYPE &mesh, const char *filename,CallBackPos *cb=0) - { - int loadmask; - return Open(mesh,filename,loadmask,cb); - } + static int Open(MESH_TYPE &mesh, const char *filename, CallBackPos *cb = 0) + { + int loadmask; + return Open(mesh, filename, loadmask, cb); + } - static int OpenMem(MESH_TYPE &mesh, const char *mem, size_t sz, int &loadmask, - CallBackPos *cb=0) - { - std::string str; - str.append(mem,sz); - std::istringstream strm(str); - return OpenStream(mesh,strm,loadmask,cb); - } + static int OpenMem(MESH_TYPE &mesh, const char *mem, size_t sz, int &loadmask, + CallBackPos *cb = 0) + { + std::string str; + str.append(mem, sz); + std::istringstream strm(str); + return OpenStream(mesh, strm, loadmask, cb); + } - /*! - * Standard call for reading a mesh. - * - * \param mesh the destination mesh - * \param filename the name of the file to read from - * \return the operation result - */ - static int Open(MESH_TYPE &mesh, const char *filename, int &loadmask, - CallBackPos *cb=0) - { - std::ifstream stream(filename); - if (stream.fail()) - return CantOpen; - return OpenStream(mesh,stream,loadmask,cb); - } + /*! + * Standard call for reading a mesh. + * + * \param mesh the destination mesh + * \param filename the name of the file to read from + * \return the operation result + */ + static int Open(MESH_TYPE &mesh, const char *filename, int &loadmask, + CallBackPos *cb = 0) + { + std::ifstream stream(filename); + if (stream.fail()) + return CantOpen; + return OpenStream(mesh, stream, loadmask, cb); + } - static int OpenStream(MESH_TYPE &mesh, std::istream &stream, int &loadmask, - CallBackPos *cb=0) - { - std::vector< std::string > tokens; - TokenizeNextLine(stream, tokens); - if(tokens.empty()) return InvalidFile_MissingOFF; + static int OpenStream(MESH_TYPE &mesh, std::istream &stream, int &loadmask, + CallBackPos *cb = 0) + { + std::vector< std::string > tokens; + TokenizeNextLine(stream, tokens); + if (tokens.empty()) return InvalidFile_MissingOFF; - bool isNormalDefined = false; - bool isColorDefined = false; - bool isTexCoordDefined = false; - int dimension = 3; - bool homogeneousComponents = false; + bool isNormalDefined = false; + bool isColorDefined = false; + bool isTexCoordDefined = false; + int dimension = 3; + bool homogeneousComponents = false; - /* - [ST][C][N][4][n]OFF # Header keyword - [Ndim] # Space dimension of vertices, present only if nOFF - NVertices NFaces NEdges # NEdges not used or checked + /* + [ST][C][N][4][n]OFF # Header keyword + [Ndim] # Space dimension of vertices, present only if nOFF + NVertices NFaces NEdges # NEdges not used or checked - x[0] y[0] z[0] # Vertices, possibly with normals, colors, and/or texture coordinates, in that order, if the prefixes N, C, ST are present. - # If 4OFF, each vertex has 4 components including a final homogeneous component. - # If nOFF, each vertex has Ndim components. - # If 4nOFF, each vertex has Ndim+1 components. - ... - x[NVertices-1] y[NVertices-1] z[NVertices-1] + x[0] y[0] z[0] # Vertices, possibly with normals, colors, and/or texture coordinates, in that order, if the prefixes N, C, ST are present. + # If 4OFF, each vertex has 4 components including a final homogeneous component. + # If nOFF, each vertex has Ndim components. + # If 4nOFF, each vertex has Ndim+1 components. + ... + x[NVertices-1] y[NVertices-1] z[NVertices-1] - # Faces - # Nv = # vertices on this face - # v[0] ... v[Nv-1]: vertex indices - # in range 0..NVertices-1 - Nv v[0] v[1] ... v[Nv-1] colorspec - ... - # colorspec continues past v[Nv-1] to end-of-line; may be 0 to 4 numbers - # nothing: default - # integer: colormap index - # 3 or 4 integers: RGB[A] values 0..255 - # 3 or 4 floats: RGB[A] values 0..1 - */ - std::string header = tokens[0]; - if (header.rfind("OFF") != std::basic_string::npos) - { // the OFF string is in the header go on parsing it. - for (int u = static_cast(header.rfind("OFF")-1); u>=0; u--) - { - if (header[u] == 'C') isColorDefined = true; - else if (header[u] == 'N') isNormalDefined = true; - else if (u>0 && header[u-1] == 'S' && header[u] == 'T') isTexCoordDefined = true; - else if (header[u] == '4') homogeneousComponents = true; - else if (header[u] == 'n') return ErrorHighDimension; - } - } - else return InvalidFile_MissingOFF; + # Faces + # Nv = # vertices on this face + # v[0] ... v[Nv-1]: vertex indices + # in range 0..NVertices-1 + Nv v[0] v[1] ... v[Nv-1] colorspec + ... + # colorspec continues past v[Nv-1] to end-of-line; may be 0 to 4 numbers + # nothing: default + # integer: colormap index + # 3 or 4 integers: RGB[A] values 0..255 + # 3 or 4 floats: RGB[A] values 0..1 + */ + std::string header = tokens[0]; + if (header.rfind("OFF") != std::basic_string::npos) + { // the OFF string is in the header go on parsing it. + for (int u = static_cast(header.rfind("OFF") - 1); u >= 0; u--) + { + if (header[u] == 'C') + isColorDefined = true; + else if (header[u] == 'N') + isNormalDefined = true; + else if (u > 0 && header[u - 1] == 'S' && header[u] == 'T') + isTexCoordDefined = true; + else if (header[u] == '4') + homogeneousComponents = true; + else if (header[u] == 'n') + return ErrorHighDimension; + } + } + else return InvalidFile_MissingOFF; - // If the file is slightly malformed and it has nvert and nface AFTER the OFF string instead of in the next line - // we manage it here... - if(tokens.size()==1) TokenizeNextLine(stream, tokens); - else tokens.erase(tokens.begin(),tokens.begin()+1); + // If the file is slightly malformed and it has nvert and nface AFTER the OFF string instead of in the next line + // we manage it here... + if (tokens.size() == 1) TokenizeNextLine(stream, tokens); + else tokens.erase(tokens.begin(), tokens.begin() + 1); - // Update loading mask - /////////////////////////////////////// + // Update loading mask + /////////////////////////////////////// - loadmask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX; + loadmask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX; - if (isNormalDefined) loadmask |= Mask::IOM_VERTNORMAL; - if (isTexCoordDefined) loadmask |= Mask::IOM_VERTTEXCOORD; - if (isColorDefined) { loadmask |= Mask::IOM_VERTCOLOR;loadmask |= Mask::IOM_FACECOLOR;} + if (isNormalDefined) loadmask |= Mask::IOM_VERTNORMAL; + if (isTexCoordDefined) loadmask |= Mask::IOM_VERTTEXCOORD; + //if (isColorDefined) { loadmask |= Mask::IOM_VERTCOLOR;loadmask |= Mask::IOM_FACECOLOR;} - //if(onlyMaskFlag) return NoError; + //if(onlyMaskFlag) return NoError; - mesh.Clear(); + mesh.Clear(); - // check on next 2 lines to detect corrupted files - if(tokens.size() < 3) - return InvalidFile; + // check on next 2 lines to detect corrupted files + if (tokens.size() < 3) + return InvalidFile; - unsigned int nVertices, nFaces, nEdges; - nVertices = atoi(tokens[0].c_str()); - nFaces = atoi(tokens[1].c_str()); - nEdges = atoi(tokens[2].c_str()); + unsigned int nVertices, nFaces, nEdges; + nVertices = atoi(tokens[0].c_str()); + nFaces = atoi(tokens[1].c_str()); + nEdges = atoi(tokens[2].c_str()); - // dimension is the space dimension of vertices => it must be three(!) - if (dimension != 3) - return UnsupportedFormat; + // dimension is the space dimension of vertices => it must be three(!) + if (dimension != 3) + return UnsupportedFormat; - if (homogeneousComponents) - return UnsupportedFormat; + if (homogeneousComponents) + return UnsupportedFormat; - // READ VERTICES - ////////////////////////////////////////////////////// + // READ VERTICES + ////////////////////////////////////////////////////// - VertexIterator v_iter = Allocator::AddVertices(mesh, nVertices); - TokenizeNextLine(stream, tokens); - size_t k = 0; // next token to read + VertexIterator v_iter = Allocator::AddVertices(mesh, nVertices); + TokenizeNextLine(stream, tokens); + size_t k = 0; // next token to read - for (unsigned int i=0; i(tokens.size()) - - static_cast(k) /* tokens already parsed */ - - 2 * (isTexCoordDefined ? 1 : 0); + // NOTE: It is assumed that colored vertex takes exactly one text line + // (otherwise it is impossible to parse color information since + // color components can vary) + if (isColorDefined) + { + // The number of color components varies from 0 to 4. + // The OFF format guaranties that there is 1 vertex per line. + int nb_color_components = static_cast(tokens.size()) + - static_cast(k) /* tokens already parsed */ + - 2 * (isTexCoordDefined ? 1 : 0); - if (nb_color_components < 0 || nb_color_components > 4) - return InvalidFile; + if (nb_color_components < 0 || nb_color_components > 4) + return InvalidFile; - // set per-vertex color attribute - if (nb_color_components > 0) - loadmask |= Mask::IOM_VERTCOLOR; + // set per-vertex color attribute + if (nb_color_components > 0) + loadmask |= Mask::IOM_VERTCOLOR; - // Store color components - if (tri::HasPerVertexColor(mesh)) - { - // Read color components + // Store color components + if (tri::HasPerVertexColor(mesh)) + { + // Read color components - if (nb_color_components == 1) - { - // read color index - (*v_iter).C().Import(ColorMap(atoi(tokens[k].c_str()))); - } - else if (nb_color_components == 3) - { - // read RGB color - if (tokens[k].find(".") == size_t(-1))// if it is a float there is a dot - { - // integers - unsigned char r = - static_cast(atoi(tokens[k].c_str())); - unsigned char g = - static_cast(atoi(tokens[k+1].c_str())); - unsigned char b = - static_cast(atoi(tokens[k+2].c_str())); + if (nb_color_components == 1) + { + // read color index + (*v_iter).C().Import(ColorMap(atoi(tokens[k].c_str()))); + } + else if (nb_color_components == 3) + { + // read RGB color + if (tokens[k].find(".") == size_t(-1))// if it is a float there is a dot + { + // integers + unsigned char r = + static_cast(atoi(tokens[k].c_str())); + unsigned char g = + static_cast(atoi(tokens[k + 1].c_str())); + unsigned char b = + static_cast(atoi(tokens[k + 2].c_str())); - vcg::Color4b color(r, g, b, 255); - (*v_iter).C().Import(color); - } - else - { - // floats - float r = static_cast(atof(tokens[k].c_str())); - float g = static_cast(atof(tokens[k+1].c_str())); - float b = static_cast(atof(tokens[k+2].c_str())); + vcg::Color4b color(r, g, b, 255); + (*v_iter).C().Import(color); + } + else + { + // floats + float r = static_cast(atof(tokens[k].c_str())); + float g = static_cast(atof(tokens[k + 1].c_str())); + float b = static_cast(atof(tokens[k + 2].c_str())); - vcg::Color4f color(r, g, b, 1.0); - (*v_iter).C().Import(color); - } - } - else if (nb_color_components == 4) - { - // read RGBA color - if (tokens[k].find(".") == size_t(-1)) - { - // integers - unsigned char r = - static_cast(atoi(tokens[k].c_str())); - unsigned char g = - static_cast(atoi(tokens[k+1].c_str())); - unsigned char b = - static_cast(atoi(tokens[k+2].c_str())); - unsigned char a = - static_cast(atoi(tokens[k+3].c_str())); + vcg::Color4f color(r, g, b, 1.0); + (*v_iter).C().Import(color); + } + } + else if (nb_color_components == 4) + { + // read RGBA color + if (tokens[k].find(".") == size_t(-1)) + { + // integers + unsigned char r = + static_cast(atoi(tokens[k].c_str())); + unsigned char g = + static_cast(atoi(tokens[k + 1].c_str())); + unsigned char b = + static_cast(atoi(tokens[k + 2].c_str())); + unsigned char a = + static_cast(atoi(tokens[k + 3].c_str())); - Color4b color(r, g, b, a); - (*v_iter).C().Import(color); - } - else - { - // floats - float r = static_cast(atof(tokens[k].c_str())); - float g = static_cast(atof(tokens[k+1].c_str())); - float b = static_cast(atof(tokens[k+2].c_str())); - float a = static_cast(atof(tokens[k+3].c_str())); + Color4b color(r, g, b, a); + (*v_iter).C().Import(color); + } + else + { + // floats + float r = static_cast(atof(tokens[k].c_str())); + float g = static_cast(atof(tokens[k + 1].c_str())); + float b = static_cast(atof(tokens[k + 2].c_str())); + float a = static_cast(atof(tokens[k + 3].c_str())); - vcg::Color4f color(r, g, b, a); - (*v_iter).C().Import(color); - } - } - } + vcg::Color4f color(r, g, b, a); + (*v_iter).C().Import(color); + } + } + } - k += nb_color_components; - } + k += nb_color_components; + } - if (isTexCoordDefined) - { - for (unsigned int j=0; j<2; j++) - { - // Go to next line when needed - if (k == tokens.size()) // if EOL - { - TokenizeNextLine(stream, tokens); - if (tokens.size() == 0) // if EOF - return InvalidFile; - k = 0; - } + if (isTexCoordDefined) + { + for (unsigned int j = 0; j < 2; j++) + { + // Go to next line when needed + if (k == tokens.size()) // if EOL + { + TokenizeNextLine(stream, tokens); + if (tokens.size() == 0) // if EOF + return InvalidFile; + k = 0; + } - std::string str = tokens[k]; - k++; + std::string str = tokens[k]; + k++; - // Store texture coordinates - if (tri::HasPerWedgeTexCoord(mesh)) - { - //...TODO... - } - } - } - } // for i=... + // Store texture coordinates + if (tri::HasPerWedgeTexCoord(mesh)) + { + //...TODO... + } + } + } + } // for i=... - // READ FACES - ////////////////////////////////////////////////////// - if(FaceType::HasPolyInfo()) - { - for (unsigned int f=0; f < nFaces; f++) - { - if(cb && (f%1000)==0) cb(50+f*50/nFaces,"Face Loading"); - TokenizeNextLine(stream, tokens); - int vert_per_face = atoi(tokens[0].c_str()); - std::vector vInd(vert_per_face); - k = 1; - for (int j=0; j < vert_per_face; j++) - { - if (k == tokens.size()) // if EOL // Go to next line when needed - { - TokenizeNextLine(stream, tokens); - if (tokens.size() == 0) return InvalidFile; // if EOF - k = 0; - } - vInd[j] = atoi(tokens[k].c_str()); - k++; - } - if(vert_per_face==3) - Allocator::AddFace(mesh, &mesh.vert[ vInd[0] ], &mesh.vert[ vInd[1] ], &mesh.vert[ vInd[2] ]); + // READ FACES + ////////////////////////////////////////////////////// + if (FaceType::HasPolyInfo()) + { + for (unsigned int f = 0; f < nFaces; f++) + { + if (cb && (f % 1000) == 0) cb(50 + f * 50 / nFaces, "Face Loading"); + TokenizeNextLine(stream, tokens); + int vert_per_face = atoi(tokens[0].c_str()); + std::vector vInd(vert_per_face); + k = 1; + for (int j = 0; j < vert_per_face; j++) + { + if (k == tokens.size()) // if EOL // Go to next line when needed + { + TokenizeNextLine(stream, tokens); + if (tokens.size() == 0) return InvalidFile; // if EOF + k = 0; + } + vInd[j] = atoi(tokens[k].c_str()); + k++; + } + if (vert_per_face == 3) + Allocator::AddFace(mesh, &mesh.vert[vInd[0]], &mesh.vert[vInd[1]], &mesh.vert[vInd[2]]); - if(vert_per_face==4) - Allocator::AddQuadFace(mesh, &mesh.vert[ vInd[0] ], &mesh.vert[ vInd[1] ], &mesh.vert[ vInd[2] ],&mesh.vert[ vInd[3] ]); + if (vert_per_face == 4) + Allocator::AddQuadFace(mesh, &mesh.vert[vInd[0]], &mesh.vert[vInd[1]], &mesh.vert[vInd[2]], &mesh.vert[vInd[3]]); - } - } - else // Standard Triangular Mesh Loading - { - Allocator::AddFaces(mesh, nFaces); - unsigned int f0=0; + } + } + else // Standard Triangular Mesh Loading + { + Allocator::AddFaces(mesh, nFaces); + unsigned int f0 = 0; - // Initial call to the QuadTriangulate with an empty vector to just reset the static set of existing diagonals - std::vector qtmp; - BitQuad::QuadTriangulate(qtmp); + // Initial call to the QuadTriangulate with an empty vector to just reset the static set of existing diagonals + std::vector qtmp; + BitQuad::QuadTriangulate(qtmp); - for (unsigned int f=0; f < nFaces; f++) - { - f0 = f; - if (stream.fail()) - return InvalidFile; + for (unsigned int f = 0; f < nFaces; f++) + { + f0 = f; + if (stream.fail()) + return InvalidFile; - if(cb && (f%1000)==0) - cb(50+f*50/nFaces,"Face Loading"); + if (cb && (f % 1000) == 0) + cb(50 + f * 50 / nFaces, "Face Loading"); - TokenizeNextLine(stream, tokens); - int vert_per_face = atoi(tokens[0].c_str()); - if(vert_per_face < 3) - return ErrorDegenerateFace; - k = 1; - if (vert_per_face == 3) - { - for (int j = 0; j < 3; j++) - { - if (k == tokens.size()) // if EOL // Go to next line when needed - { - TokenizeNextLine(stream, tokens); - if (tokens.size() == 0) return InvalidFile; // if EOF - k = 0; - } + TokenizeNextLine(stream, tokens); + int vert_per_face = atoi(tokens[0].c_str()); + if (vert_per_face < 3) + return ErrorDegenerateFace; + k = 1; + if (vert_per_face == 3) + { + for (int j = 0; j < 3; j++) + { + if (k == tokens.size()) // if EOL // Go to next line when needed + { + TokenizeNextLine(stream, tokens); + if (tokens.size() == 0) return InvalidFile; // if EOF + k = 0; + } - mesh.face[f].V(j) = &(mesh.vert[ atoi(tokens[k].c_str()) ]); - k++; - } - } - else - { - // The face must be triangulated - unsigned int trigs = vert_per_face-3; // number of extra faces to add - nFaces += trigs; - Allocator::AddFaces(mesh, trigs); - std::vector vertIndices(vert_per_face); - std::vector polygonVect(vert_per_face); // vec of polygon loops used for the triangulation of polygonal face - for (int j=0; j < vert_per_face; j++) - { - if (k == tokens.size()) // if EOL // Go to next line when needed - { - TokenizeNextLine(stream, tokens); - if (tokens.size() == 0) return InvalidFile; // if EOF - k = 0; - } - vertIndices[j] = atoi(tokens[k].c_str()); - polygonVect[j].Import (mesh.vert[ vertIndices[j] ].P()); - k++; - } - if(vert_per_face==4) - { // To well triangulate use the bitquad support function that reorders vertex for a simple fan - std::vector q(4); - for(int qqi=0;qqi<4;++qqi) - q[qqi]=& mesh.vert[vertIndices[qqi]]; - BitQuad::QuadTriangulate(q); - for(int qqi=0;qqi<4;++qqi) - vertIndices[qqi] = q[qqi]- & mesh.vert[0]; - // build a two face fan - for (int j=0; j<2; j++) - { - mesh.face[f+j].V(0) = &(mesh.vert[ vertIndices[0 ] ]); - mesh.face[f+j].V(1) = &(mesh.vert[ vertIndices[1+j] ]); - mesh.face[f+j].V(2) = &(mesh.vert[ vertIndices[2+j] ]); - if (tri::HasPerFaceFlags(mesh)) { - // tag internal polygonal edges as "faux" - if (j>0) mesh.face[f+j].SetF(0); - if (j indexTriangulatedVect; - // TessellatePlanarPolygon3(polygonVect,indexTriangulatedVect); - std::vector< std::vector > loopVect; - loopVect.push_back(polygonVect); + mesh.face[f].V(j) = &(mesh.vert[atoi(tokens[k].c_str())]); + k++; + } + } + else + { + // The face must be triangulated + unsigned int trigs = vert_per_face - 3; // number of extra faces to add + nFaces += trigs; + Allocator::AddFaces(mesh, trigs); + std::vector vertIndices(vert_per_face); + std::vector polygonVect(vert_per_face); // vec of polygon loops used for the triangulation of polygonal face + for (int j = 0; j < vert_per_face; j++) + { + if (k == tokens.size()) // if EOL // Go to next line when needed + { + TokenizeNextLine(stream, tokens); + if (tokens.size() == 0) return InvalidFile; // if EOF + k = 0; + } + vertIndices[j] = atoi(tokens[k].c_str()); + polygonVect[j].Import(mesh.vert[vertIndices[j]].P()); + k++; + } + if (vert_per_face == 4) + { // To well triangulate use the bitquad support function that reorders vertex for a simple fan + std::vector q(4); + for (int qqi = 0; qqi < 4; ++qqi) + q[qqi] = &mesh.vert[vertIndices[qqi]]; + BitQuad::QuadTriangulate(q); + for (int qqi = 0; qqi < 4; ++qqi) + vertIndices[qqi] = q[qqi] - &mesh.vert[0]; + // build a two face fan + for (int j = 0; j < 2; j++) + { + mesh.face[f + j].V(0) = &(mesh.vert[vertIndices[0]]); + mesh.face[f + j].V(1) = &(mesh.vert[vertIndices[1 + j]]); + mesh.face[f + j].V(2) = &(mesh.vert[vertIndices[2 + j]]); + if (tri::HasPerFaceFlags(mesh)) { + // tag internal polygonal edges as "faux" + if (j > 0) mesh.face[f + j].SetF(0); + if (j < vert_per_face - 3) mesh.face[f + j].SetF(2); + loadmask |= Mask::IOM_BITPOLYGONAL; + } + } + } + else // standard fan triangulation (we hope the polygon is convex...) + { + std::vector indexTriangulatedVect; + // TessellatePlanarPolygon3(polygonVect,indexTriangulatedVect); + std::vector< std::vector > loopVect; + loopVect.push_back(polygonVect); #ifdef __gl_h_ - //qDebug("OK: using opengl tessellation for a polygon of %i vertices",vertexesPerFace); - vcg::glu_tesselator::tesselate(loopVect, indexTriangulatedVect); + //qDebug("OK: using opengl tessellation for a polygon of %i vertices",vertexesPerFace); + vcg::glu_tesselator::tesselate(loopVect, indexTriangulatedVect); #else - //qDebug("Warning: using fan tessellation for a polygon of %i vertices",vertexesPerFace); - tri::io::FanTessellator(loopVect, indexTriangulatedVect); + //qDebug("Warning: using fan tessellation for a polygon of %i vertices",vertexesPerFace); + tri::io::FanTessellator(loopVect, indexTriangulatedVect); #endif - for (size_t j=0; j0); - if(isColorDefined) loadmask |= Mask::IOM_FACECOLOR; + // NOTE: It is assumed that colored face takes exactly one text line + // (otherwise it is impossible to parse color information since + // color components can vary) + size_t color_elements = tokens.size() - vert_per_face - 1; + //isColorDefined |= (color_elements>0); + //if(isColorDefined) loadmask |= Mask::IOM_FACECOLOR; - if( (color_elements>0) && tri::HasPerFaceColor(mesh) ) - { + if (color_elements > 0) + { + loadmask |= Mask::IOM_FACECOLOR; + if (tri::HasPerFaceColor(mesh)) + { + switch (color_elements) + { + case 0: + { + for (; f0 <= f; f0++) + mesh.face[f0].C().Import(vcg::Color4f(.666f, .666f, .666f, .666f)); + break; + } + case 1: + { + for (; f0 <= f; f0++) + mesh.face[f0].C().Import(ColorMap(atoi(tokens[vert_per_face + 1].c_str()))); + break; + } + case 3: + { + if (tokens[vert_per_face + 1].find('.') == std::string::npos) // if there is a float there is a dot + { + Color4b cc(Color4b::White); + cc[0] = (unsigned char)atoi(tokens[vert_per_face + 1].c_str()); + cc[1] = (unsigned char)atoi(tokens[vert_per_face + 2].c_str()); + cc[2] = (unsigned char)atoi(tokens[vert_per_face + 3].c_str()); + for (; f0 <= f; f0++) + mesh.face[f0].C() = cc; + } + else + { + float color[3]; + color[0] = (float)atof(tokens[vert_per_face + 1].c_str()); + color[1] = (float)atof(tokens[vert_per_face + 2].c_str()); + color[2] = (float)atof(tokens[vert_per_face + 3].c_str()); + for (; f0 <= f; f0++) + mesh.face[f0].C().Import(vcg::Color4f(color[0], color[1], color[2], 1.0f)); + } + break; + } + case 4: + { + if (tokens[vert_per_face + 1].find('.') == std::string::npos) // if it is a float there is a dot + { + Color4b cc; + cc[0] = (unsigned char)atoi(tokens[vert_per_face + 1].c_str()); + cc[1] = (unsigned char)atoi(tokens[vert_per_face + 2].c_str()); + cc[2] = (unsigned char)atoi(tokens[vert_per_face + 3].c_str()); + cc[3] = (unsigned char)atoi(tokens[vert_per_face + 4].c_str()); + for (; f0 <= f; f0++) + mesh.face[f0].C() = cc; + } + else + { + float color[4]; + color[0] = float(atof(tokens[vert_per_face + 1].c_str())); + color[1] = float(atof(tokens[vert_per_face + 2].c_str())); + color[2] = float(atof(tokens[vert_per_face + 3].c_str())); + color[3] = float(atof(tokens[vert_per_face + 4].c_str())); + for (; f0 <= f; f0++) + mesh.face[f0].C().Import(vcg::Color4f(color[0], color[1], color[2], color[3])); + } + break; + } + } //end switch + } + } // end if (isColorDefined) + } // end of for f=... + } + return NoError; - // set per-face color attribute - if (color_elements > 0) - loadmask |= Mask::IOM_FACECOLOR; + } // end Open - switch (color_elements) - { - case 0: - { - for ( ; f0<=f; f0++) - mesh.face[f0].C().Import(vcg::Color4f(.666f, .666f, .666f, .666f)); - break; - } - case 1: - { - for ( ; f0<=f; f0++) - mesh.face[f0].C().Import( ColorMap( atoi(tokens[vert_per_face+1].c_str()) ) ); - break; - } - case 3: - { - if (tokens[vert_per_face+1].find('.')==std::string::npos) // if there is a float there is a dot - { - Color4b cc(Color4b::White); - cc[0] = (unsigned char)atoi( tokens[vert_per_face+1].c_str() ); - cc[1] = (unsigned char)atoi( tokens[vert_per_face+2].c_str() ); - cc[2] = (unsigned char)atoi( tokens[vert_per_face+3].c_str() ); - for ( ; f0<=f; f0++) - mesh.face[f0].C()=cc; - } - else - { - float color[3]; - color[0] = (float) atof( tokens[vert_per_face+1].c_str() ); - color[1] = (float) atof( tokens[vert_per_face+2].c_str() ); - color[2] = (float) atof( tokens[vert_per_face+3].c_str() ); - for ( ; f0<=f; f0++) - mesh.face[f0].C().Import(vcg::Color4f(color[0], color[1], color[2], 1.0f)); - } - break; - } - case 4: - { - if (tokens[vert_per_face+1].find('.')==std::string::npos) // if it is a float there is a dot - { - Color4b cc; - cc[0] = (unsigned char) atoi(tokens[vert_per_face+1].c_str()); - cc[1] = (unsigned char) atoi(tokens[vert_per_face+2].c_str()); - cc[2] = (unsigned char) atoi(tokens[vert_per_face+3].c_str()); - cc[3] = (unsigned char) atoi(tokens[vert_per_face+4].c_str()); - for ( ; f0<=f; f0++) - mesh.face[f0].C()=cc; - } - else - { - float color[4]; - color[0] = float( atof(tokens[vert_per_face+1].c_str()) ); - color[1] = float( atof(tokens[vert_per_face+2].c_str()) ); - color[2] = float( atof(tokens[vert_per_face+3].c_str()) ); - color[3] = float( atof(tokens[vert_per_face+4].c_str()) ); - for ( ; f0<=f; f0++) - mesh.face[f0].C().Import(vcg::Color4f(color[0], color[1], color[2], color[3])); - } - break; - } - } //end switch - } // end if (isColorDefined) - } // end of for f=... - } - return NoError; + protected: - } // end Open + /*! + * Read the next valid line and parses it into "tokens", allowing the tokens to be read one at a time. + * \param stream The object providing the input stream + * \param tokens The "tokens" in the next line + */ + inline static void TokenizeNextLine(std::istream &stream, std::vector< std::string > &tokens) + { + std::string line; + do + std::getline(stream, line, '\n'); + while ((line[0] == '#' || line.length() == 0 || line[0] == '\r') && (!stream.eof())); -protected: + size_t from = 0; + size_t to = 0; + size_t length = line.size(); + tokens.clear(); + do + { + while (from != length && (line[from] == ' ' || line[from] == '\t' || line[from] == '\r')) + from++; + if (from != length) + { + to = from + 1; + while (to != length && (((line[to] != ' ') && (line[to] != '\t')) || (line[to] == '\r'))) + to++; + tokens.push_back(line.substr(from, to - from).c_str()); + from = to; + } + } while (from < length); + } // end Tokenize - /*! - * Read the next valid line and parses it into "tokens", allowing the tokens to be read one at a time. - * \param stream The object providing the input stream - * \param tokens The "tokens" in the next line - */ - inline static void TokenizeNextLine(std::istream &stream, std::vector< std::string > &tokens) - { - std::string line; - do - std::getline(stream, line, '\n'); - while ((line[0] == '#' || line.length()==0 || line[0]=='\r' ) && (!stream.eof())); - - size_t from = 0; - size_t to = 0; - size_t length = line.size(); - tokens.clear(); - do - { - while (from!=length && (line[from]==' ' || line[from] == '\t' || line[from] == '\r')) - from++; - if(from!=length) - { - to = from+1; - while ( to!=length && (((line[to]!=' ') && (line[to] != '\t')) || (line[to] == '\r'))) - to++; - tokens.push_back(line.substr(from, to-from).c_str()); - from = to; - } - } - while (fromcolor mapping, according to the Geomview's `cmap.fmap' file. - * \param i the color index - * \return the corresponding vcg::Color4f color - */ - static const vcg::Color4f ColorMap(int i) - { - static const float colorMap[148][4] = - { - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.2f, 0.2f, 0.2f, 0.2f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.1f, 0.1f, 0.1f, 0.1f }, - { 0.1f, 0.1f, 0.1f, 0.1f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.2f, 0.2f, 0.2f, 0.2f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.75f, 0.75f, 0.75f, 0.75f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.75f, 0.75f, 0.75f, 0.75f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.75f, 0.75f, 0.75f, 0.75f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.75f, 0.75f, 0.75f, 0.75f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f }, - { 0.05f, 0.05f, 0.05f, 0.05f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.2f, 0.2f, 0.2f, 0.2f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.1f, 0.1f, 0.1f, 0.1f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.75f, 0.75f, 0.75f, 0.75f }, - { 0.75f, 0.75f, 0.75f, 0.75f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.75f, 0.75f, 0.75f, 0.75f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.75f, 0.75f, 0.75f, 0.75f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.7f, 0.7f, 0.7f, 0.7f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.9f, 0.9f, 0.9f, 0.9f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.75f, 0.75f, 0.75f, 0.75f }, - { 0.8f, 0.8f, 0.8f, 0.8f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f }, - { 0.4f, 0.4f, 0.4f, 0.4f }, - { 0.8f, 0.8f, 0.8f, 0.8f } - }; - return Color4f(colorMap[i][0], colorMap[i][1], colorMap[i][2], colorMap[i][3]); - } -}; -// /*! @} */ -} //namespace io -}//namespace tri + /*! + * Provide the int->color mapping, according to the Geomview's `cmap.fmap' file. + * \param i the color index + * \return the corresponding vcg::Color4f color + */ + static const vcg::Color4f ColorMap(int i) + { + static const float colorMap[148][4] = + { + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.2f, 0.2f, 0.2f, 0.2f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.1f, 0.1f, 0.1f, 0.1f }, + { 0.1f, 0.1f, 0.1f, 0.1f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.2f, 0.2f, 0.2f, 0.2f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.75f, 0.75f, 0.75f, 0.75f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.75f, 0.75f, 0.75f, 0.75f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.75f, 0.75f, 0.75f, 0.75f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.75f, 0.75f, 0.75f, 0.75f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f, 1.0f }, + { 0.05f, 0.05f, 0.05f, 0.05f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.2f, 0.2f, 0.2f, 0.2f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.1f, 0.1f, 0.1f, 0.1f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.75f, 0.75f, 0.75f, 0.75f }, + { 0.75f, 0.75f, 0.75f, 0.75f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.75f, 0.75f, 0.75f, 0.75f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.75f, 0.75f, 0.75f, 0.75f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.7f, 0.7f, 0.7f, 0.7f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.9f, 0.9f, 0.9f, 0.9f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.75f, 0.75f, 0.75f, 0.75f }, + { 0.8f, 0.8f, 0.8f, 0.8f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 0.4f, 0.4f, 0.4f, 0.4f }, + { 0.8f, 0.8f, 0.8f, 0.8f } + }; + return Color4f(colorMap[i][0], colorMap[i][1], colorMap[i][2], colorMap[i][3]); + } + }; + // /*! @} */ + } //namespace io + }//namespace tri } // namespace vcg #endif //__VCGLIB_IMPORT_OFF From 052e7242fe33ac02bd66485b328490a20a15919d Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Fri, 14 Oct 2016 05:34:04 +0200 Subject: [PATCH 38/91] - fixed "glerror for 0 argument passed to glpointsize" bug --- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index e084448e..d5a5125a 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -1664,12 +1664,11 @@ namespace vcg pointsize = glopts->_perpoint_pointsize; glPointSize(pointsize); } - + GLenum err; if (glopts->_perpoint_dot_enabled) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor(vcg::Color4b(vcg::Color4b::Black)); glDepthRange(0.0, 0.9999); glDepthFunc(GL_LEQUAL); glPointSize(glopts->_perpoint_pointsize + 0.5); @@ -1682,7 +1681,10 @@ namespace vcg if ((glopts != NULL) && (glopts->_perpoint_dot_enabled)) { - glPointSize(glopts->_perpoint_pointsize - 1); + float psize = 0.0001; + if ((glopts->_perpoint_pointsize - 1) > 0) + psize = (glopts->_perpoint_pointsize - 1); + glPointSize(psize); if (isBORenderingAvailable()) drawPointsBO(req); else @@ -1696,10 +1698,8 @@ namespace vcg size_t pointsnum = _mesh.VN(); if (InternalRendAtts::replicatedPipelineNeeded(_currallocatedboatt)) pointsnum = _mesh.FN() * 3; - updateClientState(req); glDrawArrays(GL_POINTS,0,GLsizei(pointsnum)); - /*disable all client state buffers*/ InternalRendAtts tmp; updateClientState(tmp); From 48818b4e40b8b9bd8aea19c20eb318ddcbddec9e Mon Sep 17 00:00:00 2001 From: gianpaolopalma Date: Tue, 18 Oct 2016 13:38:10 +0200 Subject: [PATCH 39/91] Added functions for FaceType in the EmptyTMark class --- vcg/complex/algorithms/closest.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/closest.h b/vcg/complex/algorithms/closest.h index f98f48d1..062404d0 100644 --- a/vcg/complex/algorithms/closest.h +++ b/vcg/complex/algorithms/closest.h @@ -82,7 +82,8 @@ namespace vcg { { public: typedef typename MESH_TYPE::VertexType VertexType; - typedef typename MESH_TYPE::EdgeType EdgeType; + typedef typename MESH_TYPE::EdgeType EdgeType; + typedef typename MESH_TYPE::FaceType FaceType; inline EmptyTMark(){} inline EmptyTMark(MESH_TYPE *){} inline void UnMarkAll() const {} @@ -90,6 +91,8 @@ namespace vcg { inline void Mark(VertexType*) const {} inline bool IsMarked(EdgeType*) const { return false; } inline void Mark(EdgeType*) const {} + inline bool IsMarked(FaceType*) const { return false; } + inline void Mark(FaceType*) const {} inline void SetMesh(void * /*m=0*/) const {} }; From be72f858e4b84c35213accd013e95ee0876bb43d Mon Sep 17 00:00:00 2001 From: Marco Callieri Date: Thu, 20 Oct 2016 12:24:09 +0200 Subject: [PATCH 40/91] updated rubberband drawing mode (for meshlab measurement filter) --- wrap/gui/rubberband.cpp | 55 ++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/wrap/gui/rubberband.cpp b/wrap/gui/rubberband.cpp index 4ba2001b..f08d0002 100644 --- a/wrap/gui/rubberband.cpp +++ b/wrap/gui/rubberband.cpp @@ -146,36 +146,39 @@ void Rubberband::RenderLine(QGLWidget* gla, Point3f AA, Point3f BB) glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDepthMask(false); - glLineWidth(2.5); - glPointSize(6.0); - glEnable(GL_BLEND); - glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); glColor(color); - glLineWidth(2.0); - glPointSize(5.0); - glBegin(GL_LINES); - glVertex(AA); - glVertex(BB); - glEnd(); - glBegin(GL_POINTS); - glVertex(AA); - glVertex(BB); - glEnd(); - glDepthFunc(GL_GREATER); - glLineWidth(1.0f); - glPointSize(2.0f); - glBegin(GL_LINES); - glVertex(AA); - glVertex(BB); - glEnd(); - glBegin(GL_POINTS); - glVertex(AA); - glVertex(BB); - glEnd(); - glDepthFunc(GL_LESS); + // IN FRONT OF SURFACE + glDepthFunc(GL_LESS); + glLineWidth(2.5); + glPointSize(6.0); + glBegin(GL_LINES); + glVertex(AA); + glVertex(BB); + glEnd(); + glBegin(GL_POINTS); + glVertex(AA); + glVertex(BB); + glEnd(); + + // BEHIND SURFACE + glDepthFunc(GL_GREATER); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR); + glLineWidth(1.5f); + glPointSize(4.0f); + glBegin(GL_LINES); + glVertex(AA); + glVertex(BB); + glEnd(); + glBegin(GL_POINTS); + glVertex(AA); + glVertex(BB); + glEnd(); + + glDepthFunc(GL_LESS); glPopAttrib(); assert(!glGetError()); } From 73d84303def5355f36dae6da809c814309c2916c Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 20 Oct 2016 12:40:01 +0200 Subject: [PATCH 41/91] Translated a number of comments and corrected a small bug (adding a null box does nothing also for transformed box) --- vcg/space/box3.h | 70 +++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/vcg/space/box3.h b/vcg/space/box3.h index dfdba174..f9e3fccd 100644 --- a/vcg/space/box3.h +++ b/vcg/space/box3.h @@ -72,35 +72,36 @@ public: { return min!=p.min || max!=p.max; } - /** Varia le dimensioni del bounding box scalandole rispetto al parametro scalare. - @param s Valore scalare che indica di quanto deve variare il bounding box + /** Offset of a vector (s,s,s) */ void Offset( const BoxScalarType s ) { Offset( Point3 (s,s,s)); } - /** Varia le dimensioni del bounding box del valore fornito attraverso il parametro. - @param delta Point in 3D space + /** Offset the two corner of the box of a vector delta. + * adding delta to max and -delta to min. + @param delta offset vector */ void Offset( const Point3 & delta ) { min -= delta; max += delta; } - /// Initializing the bounding box + /// Initializing the bounding box void Set( const Point3 & p ) { min = max = p; } - /// Set the bounding box to a null value + + /// Set the bounding box to a null value void SetNull() { min.X()= 1; max.X()= -1; min.Y()= 1; max.Y()= -1; min.Z()= 1; max.Z()= -1; } - /** Function to add two bounding box - @param b Il bounding box che si vuole aggiungere + /** Modify the current bbox to contain also the passed box. + * Adding a null bounding box does nothing */ void Add( Box3 const & b ) { @@ -117,9 +118,7 @@ public: if(max.Z() < b.max.Z()) max.Z() = b.max.Z(); } } - /** Funzione per aggiungere un punto al bounding box. Il bounding box viene modificato se il punto - cade fuori da esso. - @param p The point 3D + /** Modify the current bbox to contain also the passed point */ void Add( const Point3 & p ) { @@ -136,9 +135,7 @@ public: } } - /** Function to add a sphere (a point + radius) to a bbox - @param p The point 3D - @param radius the radius of the sphere centered on p + /** Modify the current bbox to contain also the passed sphere */ void Add( const Point3 & p, const BoxScalarType radius ) { @@ -154,19 +151,22 @@ void Add( const Point3 & p, const BoxScalarType radius ) max.Z() = std::max(max.Z(),p.Z()+radius); } } - // Aggiunge ad un box un altro box trasformato secondo la matrice m + /** Modify the current bbox to contain also the box b trasformed according to the matrix m + */ void Add( const Matrix44 &m, const Box3 & b ) { - const Point3 &mn= b.min; - const Point3 &mx= b.max; + if(b.IsNull()) return; // Adding a null bbox should do nothing + + const Point3 &mn= b.min; + const Point3 &mx= b.max; Add(m*(Point3(mn[0],mn[1],mn[2]))); - Add(m*(Point3(mx[0],mn[1],mn[2]))); - Add(m*(Point3(mn[0],mx[1],mn[2]))); - Add(m*(Point3(mx[0],mx[1],mn[2]))); - Add(m*(Point3(mn[0],mn[1],mx[2]))); - Add(m*(Point3(mx[0],mn[1],mx[2]))); - Add(m*(Point3(mn[0],mx[1],mx[2]))); - Add(m*(Point3(mx[0],mx[1],mx[2]))); + Add(m*(Point3(mx[0],mn[1],mn[2]))); + Add(m*(Point3(mn[0],mx[1],mn[2]))); + Add(m*(Point3(mx[0],mx[1],mn[2]))); + Add(m*(Point3(mn[0],mn[1],mx[2]))); + Add(m*(Point3(mx[0],mn[1],mx[2]))); + Add(m*(Point3(mn[0],mx[1],mx[2]))); + Add(m*(Point3(mx[0],mx[1],mx[2]))); } /** Calcola l'intersezione tra due bounding box. Al bounding box viene assegnato il valore risultante. @param b Il bounding box con il quale si vuole effettuare l'intersezione @@ -191,9 +191,7 @@ void Add( const Point3 & p, const BoxScalarType radius ) min += p; max += p; } - /** Verifica se un punto appartiene ad un bounding box. - @param p The point 3D - @return True se p appartiene al bounding box, false altrimenti + /** true if the point belong to the closed box */ bool IsIn( Point3 const & p ) const { @@ -203,9 +201,8 @@ void Add( const Point3 & p, const BoxScalarType radius ) min.Z() <= p.Z() && p.Z() <= max.Z() ); } - /** Verifica se un punto appartiene ad un bounding box aperto sul max. - @param p The point 3D - @return True se p appartiene al bounding box, false altrimenti + /** true if the point belong to the open box (open on the max side) + * e.g. if p in [min,max) */ bool IsInEx( Point3 const & p ) const { @@ -234,15 +231,14 @@ void Add( const Point3 & p, const BoxScalarType radius ) b.min.Y()min.Y() && b.min.Z()min.Z() ; } - /** Controlla se il bounding box e' nullo. - @return True se il bounding box e' nullo, false altrimenti + /** + return true if the box is null (e.g. invalid or not initialized); */ bool IsNull() const { return min.X()>max.X() || min.Y()>max.Y() || min.Z()>max.Z(); } - /** Controlla se il bounding box e' vuoto. - @return True se il bounding box e' vuoto, false altrimenti + /** return true if the box is empty (e.g. if min == max) */ bool IsEmpty() const { return min==max; } - /// Restituisce la lunghezza della diagonale del bounding box. + /// Return the lenght of the diagonal of the box . BoxScalarType Diag() const { return Distance(min,max); @@ -252,7 +248,7 @@ void Add( const Point3 & p, const BoxScalarType radius ) { return SquaredDistance(min,max); } - /// Calcola il centro del bounding box. + /// Return the center of the box. Point3 Center() const { return (min+max)/2; @@ -277,7 +273,7 @@ void Add( const Point3 & p, const BoxScalarType radius ) (p[2]-min[2])/(max[2]-min[2]) ); } - /// Calcola il volume del bounding box. + /// Return the volume of the box. BoxScalarType Volume() const { return (max.X()-min.X())*(max.Y()-min.Y())*(max.Z()-min.Z()); From 680d903ad5888e08ec5b1846de2b81215ff783b6 Mon Sep 17 00:00:00 2001 From: gianpaolopalma Date: Fri, 21 Oct 2016 11:06:11 +0200 Subject: [PATCH 42/91] Indentation --- vcg/space/deprecated_point3.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vcg/space/deprecated_point3.h b/vcg/space/deprecated_point3.h index 793b9c0e..bf52253d 100644 --- a/vcg/space/deprecated_point3.h +++ b/vcg/space/deprecated_point3.h @@ -145,10 +145,10 @@ public: _v[1] = nv[1]; _v[2] = nv[2]; } - inline Point3 & operator =( Point3 const & p ) + inline Point3 & operator =(Point3 const & p) { - _v[0]= p._v[0]; _v[1]= p._v[1]; _v[2]= p._v[2]; - return *this; + _v[0] = p._v[0]; _v[1] = p._v[1]; _v[2] = p._v[2]; + return *this; } inline void SetZero() { From 9f2f60850df45f1ec91bc633cfc2dbfb68b33fbe Mon Sep 17 00:00:00 2001 From: Marco Callieri Date: Tue, 25 Oct 2016 14:32:29 +0200 Subject: [PATCH 43/91] added cameraType in XML export/import added "cameraType" property in Intrinsics XML export and import, for better handling of orthographic cameras in MeshLab --- wrap/qt/shot_qt.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wrap/qt/shot_qt.h b/wrap/qt/shot_qt.h index 4313ab8e..cf0bd586 100644 --- a/wrap/qt/shot_qt.h +++ b/wrap/qt/shot_qt.h @@ -30,6 +30,7 @@ template shot.Extrinsics.SetRot(rot); vcg::Camera &cam = shot.Intrinsics; + if(attr.contains("CameraType")) cam.cameraType = attr.namedItem("CameraType").nodeValue().toInt(); cam.FocalMm = attr.namedItem("FocalMm").nodeValue().toDouble(); cam.ViewportPx.X() = attr.namedItem("ViewportPx").nodeValue().section(' ',0,0).toInt(); cam.ViewportPx.Y() = attr.namedItem("ViewportPx").nodeValue().section(' ',1,1).toInt(); @@ -118,6 +119,8 @@ template const vcg::Camera &cam = shot.Intrinsics; + shotElem.setAttribute("CameraType", cam.cameraType); + shotElem.setAttribute( "FocalMm", cam.FocalMm); str = QString("%1 %2").arg(cam.k[0]).arg(cam.k[1]); From 16de4693b21efc08a642116aff38f8b91182177b Mon Sep 17 00:00:00 2001 From: gianpaolopalma Date: Fri, 28 Oct 2016 15:00:24 +0200 Subject: [PATCH 44/91] Bug fixed in the loading of the per-vertex and per-face color alpha value --- wrap/io_trimesh/import_ply.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wrap/io_trimesh/import_ply.h b/wrap/io_trimesh/import_ply.h index 171f39c1..57edbfd0 100644 --- a/wrap/io_trimesh/import_ply.h +++ b/wrap/io_trimesh/import_ply.h @@ -469,12 +469,14 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi ) { pf.AddToRead(VertDesc(6)); pf.AddToRead(VertDesc(7)); + pf.AddToRead(VertDesc(8)); pi.mask |= Mask::IOM_VERTCOLOR; } if( pf.AddToRead(VertDesc(9))!=-1 ) { pf.AddToRead(VertDesc(10)); pf.AddToRead(VertDesc(11)); + pf.AddToRead(VertDesc(12)); pi.mask |= Mask::IOM_VERTCOLOR; } if( pf.AddToRead(VertDesc(21))!=-1 ) @@ -518,6 +520,7 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi ) { pf.AddToRead(FaceDesc(7)); pf.AddToRead(FaceDesc(8)); + pf.AddToRead(FaceDesc(9)); pi.mask |= Mask::IOM_FACECOLOR; } } @@ -646,6 +649,7 @@ static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi ) for(j=0;j Date: Wed, 2 Nov 2016 11:23:25 +0100 Subject: [PATCH 45/91] Added OnlyEdgeMesh precondition in MeshAssert --- vcg/complex/algorithms/mesh_assert.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/vcg/complex/algorithms/mesh_assert.h b/vcg/complex/algorithms/mesh_assert.h index f469e38c..7f4d2d5c 100644 --- a/vcg/complex/algorithms/mesh_assert.h +++ b/vcg/complex/algorithms/mesh_assert.h @@ -104,6 +104,14 @@ public: } } + static void OnlyEdgeMesh(MeshType &m) + { + if(m.FN()>0) + throw vcg::MissingPreconditionException("Expecting a mesh composed only by edges (no faces needed or allowed)"); + } + } + + }; } // end namespace tri From 0b135dbc0178b84a944cec5456bf2c030613e4c3 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Wed, 2 Nov 2016 11:44:06 +0100 Subject: [PATCH 46/91] Stupid me. Wrong braces in previous commit --- vcg/complex/algorithms/mesh_assert.h | 1 - 1 file changed, 1 deletion(-) diff --git a/vcg/complex/algorithms/mesh_assert.h b/vcg/complex/algorithms/mesh_assert.h index 7f4d2d5c..09632022 100644 --- a/vcg/complex/algorithms/mesh_assert.h +++ b/vcg/complex/algorithms/mesh_assert.h @@ -108,7 +108,6 @@ public: { if(m.FN()>0) throw vcg::MissingPreconditionException("Expecting a mesh composed only by edges (no faces needed or allowed)"); - } } From f9169b8ec221d1e0e73b6781a27e69b6008ac67c Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Wed, 2 Nov 2016 12:11:18 +0100 Subject: [PATCH 47/91] Refactored a number of cleaning algorithms Issues resolved: - removed assert and used the correct meshassert exceptions - removed wrong use of selection instead of visiting flag (various filters destroyed selection when called) - rewrote a totally clumsy count hole. --- vcg/complex/algorithms/clean.h | 159 ++++++++++----------------------- 1 file changed, 48 insertions(+), 111 deletions(-) diff --git a/vcg/complex/algorithms/clean.h b/vcg/complex/algorithms/clean.h index 65606b59..c8f62c68 100644 --- a/vcg/complex/algorithms/clean.h +++ b/vcg/complex/algorithms/clean.h @@ -79,8 +79,6 @@ public: mp=&m; while(!sf.empty()) sf.pop(); UnMarkAll(m); - assert(p); - assert(!p->IsD()); tri::Mark(m,p); sf.push(p); } @@ -272,7 +270,6 @@ public: tri::Index(m,(*fi).V(2)), &*fi)); } - assert (size_t(m.fn) == fvec.size()); std::sort(fvec.begin(),fvec.end()); int total=0; for(int i=0;i::DeleteEdge(m, *(eVec[i].fp) ); - //qDebug("deleting face %i (pos in fvec %i)",tri::Index(m,fvec[i].fp) ,i); } } return total; @@ -440,12 +434,10 @@ public: CountNonManifoldVertexFF(m,true); tri::UpdateSelection::FaceFromVertexLoose(m); int count_removed = 0; - FaceIterator fi; - for(fi=m.face.begin(); fi!=m.face.end();++fi) + for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi) if(!(*fi).IsD() && (*fi).IsS()) Allocator::DeleteFace(m,*fi); - VertexIterator vi; - for(vi=m.vert.begin(); vi!=m.vert.end();++vi) + for(VertexIterator vi=m.vert.begin(); vi!=m.vert.end();++vi) if(!(*vi).IsD() && (*vi).IsS()) { ++count_removed; Allocator::DeleteVertex(m,*vi); @@ -631,22 +623,15 @@ public: return count_fd; } - /* - The following functions remove faces that are geometrically "bad" according to edges and area criteria. - They remove the faces that are out of a given range of area or edges (e.g. faces too large or too small, or with edges too short or too long) - but that could be topologically correct. - These functions can optionally take into account only the selected faces. - */ - template - static int RemoveFaceOutOfRangeAreaSel(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits::max)()) + /* Remove the faces that are out of a given range of area */ + static int RemoveFaceOutOfRangeArea(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits::max)(), bool OnlyOnSelected=false) { - FaceIterator fi; int count_fd = 0; MinAreaThr*=2; MaxAreaThr*=2; - for(fi=m.face.begin(); fi!=m.face.end();++fi) + for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi){ if(!(*fi).IsD()) - if(!Selected || (*fi).IsS()) + if(!OnlyOnSelected || (*fi).IsS()) { const ScalarType doubleArea=DoubleArea(*fi); if((doubleArea<=MinAreaThr) || (doubleArea>=MaxAreaThr) ) @@ -655,17 +640,13 @@ public: count_fd++; } } + } return count_fd; } - // alias for the old style. Kept for backward compatibility - static int RemoveZeroAreaFace(MeshType& m) { return RemoveFaceOutOfRangeArea(m);} + static int RemoveZeroAreaFace(MeshType& m) { return RemoveFaceOutOfRangeArea(m,0);} - // Aliases for the functions that do not look at selection - static int RemoveFaceOutOfRangeArea(MeshType& m, ScalarType MinAreaThr=0, ScalarType MaxAreaThr=(std::numeric_limits::max)()) - { - return RemoveFaceOutOfRangeAreaSel(m,MinAreaThr,MaxAreaThr); - } + /** * Is the mesh only composed by quadrilaterals? @@ -850,7 +831,7 @@ public: */ static int CountNonManifoldEdgeEE( MeshType & m, bool SelectFlag=false) { - assert(m.fn == 0 && m.en >0); // just to be sure we are using an edge mesh... + MeshAssert::OnlyEdgeMesh(m); RequireEEAdjacency(m); tri::UpdateTopology::EdgeEdge(m); @@ -1031,61 +1012,27 @@ public: static int CountHoles( MeshType & m) { - int numholev=0; - FaceIterator fi; - - FaceIterator gi; - vcg::face::Pos he; - vcg::face::Pos hei; - - std::vector< std::vector > holes; //indices of vertices - - vcg::tri::UpdateFlags::VertexClearS(m); - - gi=m.face.begin(); fi=gi; - - for(fi=m.face.begin();fi!=m.face.end();fi++)//for all faces do + UpdateFlags::FaceClearV(m); + int loopNum=0; + for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi) if(!fi->IsD()) { - for(int j=0;j<3;j++)//for all edges - { - if(fi->V(j)->IsS()) continue; - - if(face::IsBorder(*fi,j))//found an unvisited border edge + for(int j=0;j<3;++j) { - he.Set(&(*fi),j,fi->V(j)); //set the face-face iterator to the current face, edge and vertex - std::vector hole; //start of a new hole - hole.push_back(fi->P(j)); // including the first vertex - numholev++; - he.v->SetS(); //set the current vertex as selected - he.NextB(); //go to the next boundary edge - - - while(fi->V(j) != he.v)//will we do not encounter the first boundary edge. + if(!fi->IsV() && face::IsBorder(*fi,j)) { - CoordType newpoint = he.v->P(); //select its vertex. - if(he.v->IsS())//check if this vertex was selected already, because then we have an additional hole. + face::Pos startPos(&*fi,j); + face::Pos curPos=startPos; + do { - //cut and paste the additional hole. - std::vector hole2; - int index = static_cast(find(hole.begin(),hole.end(),newpoint) - - hole.begin()); - for(unsigned int i=index; iSetV(); } - hole.push_back(newpoint); - numholev++; - he.v->SetS(); //set the current vertex as selected - he.NextB(); //go to the next boundary edge + while(curPos!=startPos); + ++loopNum; } - holes.push_back(hole); } - } } - return static_cast(holes.size()); + return loopNum; } /* @@ -1102,14 +1049,14 @@ public: { tri::RequireFFAdjacency(m); CCV.clear(); - tri::UpdateSelection::FaceClear(m); + tri::UpdateFlags::FaceClearV(m); std::stack sf; FacePointer fpt=&*(m.face.begin()); for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) { - if(!((*fi).IsD()) && !(*fi).IsS()) + if(!((*fi).IsD()) && !(*fi).IsV()) { - (*fi).SetS(); + (*fi).SetV(); CCV.push_back(std::make_pair(0,&*fi)); sf.push(&*fi); while (!sf.empty()) @@ -1122,9 +1069,9 @@ public: if( !face::IsBorder(*fpt,j) ) { FacePointer l = fpt->FFp(j); - if( !(*l).IsS() ) + if( !(*l).IsV() ) { - (*l).SetS(); + (*l).SetV(); sf.push(l); } } @@ -1260,6 +1207,8 @@ public: static bool IsCoherentlyOrientedMesh(MeshType &m) { + RequireFFAdjacency(m); + MeshAssert::FFAdjacencyIsInitialized(m); for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) for(int i=0;i<3;++i) @@ -1269,26 +1218,22 @@ public: return true; } - static void OrientCoherentlyMesh(MeshType &m, bool &Oriented, bool &Orientable) + static void OrientCoherentlyMesh(MeshType &m, bool &_IsOriented, bool &_IsOrientable) { RequireFFAdjacency(m); - assert(&Oriented != &Orientable); - assert(m.face.back().FFp(0)); // This algorithms require FF topology initialized + MeshAssert::FFAdjacencyIsInitialized(m); + bool IsOrientable = true; + bool IsOriented = true; - Orientable = true; - Oriented = true; - - tri::UpdateSelection::FaceClear(m); + UpdateFlags::FaceClearV(m); std::stack faces; for (FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) { - if (!fi->IsD() && !fi->IsS()) + if (!fi->IsD() && !fi->IsV()) { // each face put in the stack is selected (and oriented) - fi->SetS(); + fi->SetV(); faces.push(&(*fi)); - - // empty the stack while (!faces.empty()) { FacePointer fp = faces.top(); @@ -1297,42 +1242,35 @@ public: // make consistently oriented the adjacent faces for (int j = 0; j < 3; j++) { - // get one of the adjacent face - FacePointer fpaux = fp->FFp(j); - int iaux = fp->FFi(j); - - if (!fpaux->IsD() && fpaux != fp && face::IsManifold(*fp, j)) + if (!face::IsBorder(*fp,j) && face::IsManifold(*fp, j)) { + FacePointer fpaux = fp->FFp(j); + int iaux = fp->FFi(j); if (!CheckOrientation(*fpaux, iaux)) { - Oriented = false; + IsOriented = false; - if (!fpaux->IsS()) - { + if (!fpaux->IsV()) face::SwapEdge(*fpaux, iaux); - assert(CheckOrientation(*fpaux, iaux)); - } else { - Orientable = false; + IsOrientable = false; break; } } - - // put the oriented face into the stack - - if (!fpaux->IsS()) + if (!fpaux->IsV()) { - fpaux->SetS(); + fpaux->SetV(); faces.push(fpaux); } } } } } - - if (!Orientable) break; + if (!IsOrientable) break; } + _IsOriented = IsOriented; + _IsOrientable = IsOrientable; } @@ -1666,7 +1604,6 @@ public: */ static bool TestFaceFaceIntersection(FaceType *f0,FaceType *f1) { - assert(f0!=f1); int sv = face::CountSharedVertex(f0,f1); if(sv==3) return true; if(sv==0) return (vcg::IntersectionTriangleTriangle((*f0),(*f1))); From 5a12a2899a640a17f187ef3740b4b53888cb025d Mon Sep 17 00:00:00 2001 From: nico Date: Wed, 2 Nov 2016 12:13:36 +0100 Subject: [PATCH 48/91] Generalized FaceFromVertex to works on polyhedral faces --- vcg/complex/algorithms/update/quality.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/update/quality.h b/vcg/complex/algorithms/update/quality.h index d9779392..ba7a6afc 100644 --- a/vcg/complex/algorithms/update/quality.h +++ b/vcg/complex/algorithms/update/quality.h @@ -164,7 +164,10 @@ static void FaceFromVertex( MeshType &m) tri::RequirePerVertexQuality(m); for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) { - (*fi).Q() = ((*fi).V(0)->Q()+(*fi).V(1)->Q()+(*fi).V(2)->Q())/3.0f; + (*fi).Q() =0; + for (size_t i=0;i<(*fi).VN();i++) + (*fi).Q() += (*fi).V(i)->Q(); + (*fi).Q()/=(ScalarType)(*fi).VN(); } } From 102a2117285624f233958dd22067386992dbaa0d Mon Sep 17 00:00:00 2001 From: nico Date: Wed, 2 Nov 2016 12:14:06 +0100 Subject: [PATCH 49/91] Updated Face face Topology before Quadrangulation --- vcg/complex/algorithms/quadrangulator.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vcg/complex/algorithms/quadrangulator.h b/vcg/complex/algorithms/quadrangulator.h index 1e2bdffe..b3f7d057 100644 --- a/vcg/complex/algorithms/quadrangulator.h +++ b/vcg/complex/algorithms/quadrangulator.h @@ -676,6 +676,8 @@ public: UV.clear(); Pmesh.Clear(); + vcg::tri::UpdateTopology::FaceFace(Tmesh); + TestIsProper(Tmesh); RoundInitial(Tmesh); From e6cac33ec8acf11b9773c25de1506db95e7b4f84 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 3 Nov 2016 12:55:29 +0100 Subject: [PATCH 50/91] removed an unused var --- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 1 - 1 file changed, 1 deletion(-) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index d5a5125a..05bb98d2 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -1664,7 +1664,6 @@ namespace vcg pointsize = glopts->_perpoint_pointsize; glPointSize(pointsize); } - GLenum err; if (glopts->_perpoint_dot_enabled) { glEnable(GL_BLEND); From fd3c661efc3b6327da517feaadba33ae11df728d Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 3 Nov 2016 12:55:46 +0100 Subject: [PATCH 51/91] commented out unused param --- wrap/gui/trackutils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/gui/trackutils.h b/wrap/gui/trackutils.h index 08c9cc0c..b9438dc1 100644 --- a/wrap/gui/trackutils.h +++ b/wrap/gui/trackutils.h @@ -176,7 +176,7 @@ bool HitHyper (Point3f center, float radius, Point3f viewpoint, Plane3f viewplan * in the simple ortho case, the hit point is just the value of * y = 1/x * (r^2 /2 ) on the hitOnViewPlane */ -bool HitHyperOrtho(Point3f center, float radius, Point3f viewpoint, Plane3f viewplane, +bool HitHyperOrtho(Point3f center, float radius, Point3f /*viewpoint*/, Plane3f viewplane, Point3f hitOnViewplane, Point3f & hit) { float xval = Distance (center, hitOnViewplane); From a8e244e73b204e0c3bc8520ea59d2a8f13e788a7 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Mon, 7 Nov 2016 22:52:58 +0100 Subject: [PATCH 52/91] added link to GitHub in the first page --- docs/Doxygen/index.dxy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Doxygen/index.dxy b/docs/Doxygen/index.dxy index f9b78370..9f9099bd 100644 --- a/docs/Doxygen/index.dxy +++ b/docs/Doxygen/index.dxy @@ -3,6 +3,8 @@ The Visualization and Computer Graphics Library (VCG for short) is a open source portable C++ templated library for manipulation, processing and displaying with OpenGL of triangle and tetrahedral meshes. +VCG Lib uses a git repository hosted by github at http://github.com/cnr-isti-vclab/vcglib/ + The library, composed by more than 100k lines of code, is released under the GPL license, and it is the base of most of the software tools of the Visual Computing Lab of the Italian National Research Council Institute ISTI From c21c89b35c6a6aa0bd828145035d535ca2ac511f Mon Sep 17 00:00:00 2001 From: Marco Callieri Date: Thu, 10 Nov 2016 09:46:49 +0100 Subject: [PATCH 53/91] symmetry: added FaceMark to plane-generating sphere if the parametric sphere used for plane geenration does not have FaceMark, the votation function throws an exception of missing component. --- vcg/complex/algorithms/symmetry.h | 1 + 1 file changed, 1 insertion(+) diff --git a/vcg/complex/algorithms/symmetry.h b/vcg/complex/algorithms/symmetry.h index ec147268..f5f4d890 100644 --- a/vcg/complex/algorithms/symmetry.h +++ b/vcg/complex/algorithms/symmetry.h @@ -226,6 +226,7 @@ public: //create the sphere vcg::tri::Sphere(*sphere,SubDirections); vcg::tri::UpdateBounding::Box(*sphere); + sphere->face.EnableMark(); ///initialize grid GridSph.Set(sphere->face.begin(),sphere->face.end()); From a42c27925569a3a7460d2df26dcdc50a87c65de0 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 10 Nov 2016 16:41:51 +0100 Subject: [PATCH 54/91] Corrected various warning in an old importer/exporter --- wrap/io_trimesh/export_gts.h | 2 +- wrap/io_trimesh/import_gts.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wrap/io_trimesh/export_gts.h b/wrap/io_trimesh/export_gts.h index ea7c0c7b..83bf9cfe 100644 --- a/wrap/io_trimesh/export_gts.h +++ b/wrap/io_trimesh/export_gts.h @@ -53,7 +53,7 @@ namespace vcg { typedef typename SaveMeshType::VertexIterator VertexIterator; typedef typename SaveMeshType::FaceIterator FaceIterator; - static int Save(SaveMeshType &m, const char * filename, int mask=0 ) + static int Save(SaveMeshType &m, const char * filename, int /*mask*/ ) { QFile device(filename); if (!device.open(QFile::WriteOnly)) diff --git a/wrap/io_trimesh/import_gts.h b/wrap/io_trimesh/import_gts.h index daa48a18..9753e1db 100644 --- a/wrap/io_trimesh/import_gts.h +++ b/wrap/io_trimesh/import_gts.h @@ -185,7 +185,7 @@ namespace vcg } sa = line.split(' '); - if (!sa.size()>=3) + if (!(sa.size()>=3)) { std::cerr << "Error parsing vertex " << line.toLocal8Bit().data() << "\n"; return InvalidFile; @@ -213,7 +213,7 @@ namespace vcg } sa = line.split(' '); - if (!sa.size()>=2) + if (!(sa.size()>=2)) { std::cerr << "Error parsing edge " << line.toLocal8Bit().data() << "\n"; return InvalidFile; @@ -238,7 +238,7 @@ namespace vcg } sa = line.split(' '); - if (!sa.size()>=3) + if (!(sa.size()>=3)) { std::cerr << "Error parsing face " << line.toLocal8Bit().data() << "\n"; return InvalidFile; From 0906212a1f262df8952ae9508fa40e8a7cc0e702 Mon Sep 17 00:00:00 2001 From: gianpaolopalma Date: Wed, 16 Nov 2016 11:12:42 +0100 Subject: [PATCH 55/91] Minor improvements -Added the possibility to create a balanced tree -Added methods to get the protected members -Bug fixed in the size of the stack used in the query methods --- vcg/space/index/kdtree/kdtree.h | 905 ++++++++++++++++---------------- 1 file changed, 461 insertions(+), 444 deletions(-) diff --git a/vcg/space/index/kdtree/kdtree.h b/vcg/space/index/kdtree/kdtree.h index 0ff9052f..51ddc574 100755 --- a/vcg/space/index/kdtree/kdtree.h +++ b/vcg/space/index/kdtree/kdtree.h @@ -35,481 +35,498 @@ namespace vcg { - template - class ConstDataWrapper + template + class ConstDataWrapper + { + public: + typedef _DataType DataType; + inline ConstDataWrapper() + : mpData(0), mStride(0), mSize(0) + {} + inline ConstDataWrapper(const DataType* pData, int size, int64_t stride = sizeof(DataType)) + : mpData(reinterpret_cast(pData)), mStride(stride), mSize(size) + {} + inline const DataType& operator[] (int i) const { - public: - typedef _DataType DataType; - inline ConstDataWrapper() - : mpData(0), mStride(0), mSize(0) - {} - inline ConstDataWrapper(const DataType* pData, int size, int64_t stride = sizeof(DataType)) - : mpData(reinterpret_cast(pData)), mStride(stride), mSize(size) - {} - inline const DataType& operator[] (int i) const - { - return *reinterpret_cast(mpData + i*mStride); - } - inline size_t size() const { return mSize; } - protected: - const unsigned char* mpData; - int64_t mStride; - size_t mSize; - }; + return *reinterpret_cast(mpData + i*mStride); + } + inline size_t size() const { return mSize; } + protected: + const unsigned char* mpData; + int64_t mStride; + size_t mSize; + }; - template - class VectorConstDataWrapper :public ConstDataWrapper + template + class VectorConstDataWrapper :public ConstDataWrapper + { + public: + inline VectorConstDataWrapper(StdVectorType &vec) : + ConstDataWrapper(&(vec[0]), vec.size(), sizeof(typename StdVectorType::value_type)) + {} + }; + + template + class VertexConstDataWrapper :public ConstDataWrapper + { + public: + inline VertexConstDataWrapper(MeshType &m) : + ConstDataWrapper(&(m.vert[0].P()), m.vert.size(), sizeof(typename MeshType::VertexType)) + {} + }; + + /** + * This class allows to create a Kd-Tree thought to perform the neighbour query (radius search, knn-nearest serach and closest search). + * The class implemetantion is thread-safe. + */ + template + class KdTree + { + public: + + typedef _Scalar Scalar; + typedef vcg::Point3 VectorType; + typedef vcg::Box3 AxisAlignedBoxType; + + typedef HeapMaxPriorityQueue PriorityQueue; + + struct Node { - public: - inline VectorConstDataWrapper(StdVectorType &vec): - ConstDataWrapper ( &(vec[0]), vec.size(), sizeof(typename StdVectorType::value_type)) - {} - }; - - template - class VertexConstDataWrapper :public ConstDataWrapper - { - public: - inline VertexConstDataWrapper(MeshType &m): - ConstDataWrapper ( &(m.vert[0].P()), m.vert.size(), sizeof(typename MeshType::VertexType)) - {} - }; - - /** - * This class allows to create a Kd-Tree thought to perform the neighbour query (radius search, knn-nearest serach and closest search). - * The class implemetantion is thread-safe. - */ - template - class KdTree - { - public: - - typedef _Scalar Scalar; - typedef vcg::Point3 VectorType; - typedef vcg::Box3 AxisAlignedBoxType; - - typedef HeapMaxPriorityQueue PriorityQueue; - - struct Node - { - union { - //standard node - struct { - Scalar splitValue; - unsigned int firstChildId:24; - unsigned int dim:2; - unsigned int leaf:1; - }; - //leaf - struct { - unsigned int start; - unsigned short size; - }; - }; + union { + //standard node + struct { + Scalar splitValue; + unsigned int firstChildId : 24; + unsigned int dim : 2; + unsigned int leaf : 1; }; - typedef std::vector NodeList; - - // return the protected members which store the nodes and the points list - inline const NodeList& _getNodes(void) { return mNodes; } - inline const std::vector& _getPoints(void) { return mPoints; } - - public: - - KdTree(const ConstDataWrapper& points, unsigned int nofPointsPerCell = 16, unsigned int maxDepth = 64); - - ~KdTree(); - - void doQueryK(const VectorType& queryPoint, int k, PriorityQueue& mNeighborQueue); - - void doQueryDist(const VectorType& queryPoint, float dist, std::vector& points, std::vector& sqrareDists); - - void doQueryClosest(const VectorType& queryPoint, unsigned int& index, Scalar& dist); - - protected: - - // element of the stack - struct QueryNode - { - QueryNode() {} - QueryNode(unsigned int id) : nodeId(id) {} - unsigned int nodeId; // id of the next node - Scalar sq; // squared distance to the next node + //leaf + struct { + unsigned int start; + unsigned short size; }; + }; + }; + typedef std::vector NodeList; - // used to build the tree: split the subset [start..end[ according to dim and splitValue, - // and returns the index of the first element of the second subset - unsigned int split(int start, int end, unsigned int dim, float splitValue); + // return the protected members which store the nodes and the points list + inline const NodeList& _getNodes(void) { return mNodes; } + inline const std::vector& _getPoints(void) { return mPoints; } + inline unsigned int _getNumLevel(void) { return numLevel; } + inline const AxisAlignedBoxType& _getAABBox(void) { return mAABB; } - int createTree(unsigned int nodeId, unsigned int start, unsigned int end, unsigned int level, unsigned int targetCellsize, unsigned int targetMaxDepth); + public: - protected: + KdTree(const ConstDataWrapper& points, unsigned int nofPointsPerCell = 16, unsigned int maxDepth = 64, bool balanced = false); - AxisAlignedBoxType mAABB; //BoundingBox - NodeList mNodes; //kd-tree nodes - std::vector mPoints; //points read from the input DataWrapper - std::vector mIndices; //points indices + ~KdTree(); + + void doQueryK(const VectorType& queryPoint, int k, PriorityQueue& mNeighborQueue); + + void doQueryDist(const VectorType& queryPoint, float dist, std::vector& points, std::vector& sqrareDists); + + void doQueryClosest(const VectorType& queryPoint, unsigned int& index, Scalar& dist); + + protected: + + // element of the stack + struct QueryNode + { + QueryNode() {} + QueryNode(unsigned int id) : nodeId(id) {} + unsigned int nodeId; // id of the next node + Scalar sq; // squared distance to the next node }; - template - KdTree::KdTree(const ConstDataWrapper& points, unsigned int nofPointsPerCell, unsigned int maxDepth) - : mPoints(points.size()), mIndices(points.size()) - { - // compute the AABB of the input - mPoints[0] = points[0]; - mAABB.Set(mPoints[0]); - for (unsigned int i=1 ; i mPoints; //points read from the input DataWrapper + std::vector mIndices; //points indices + unsigned int targetCellSize; //min number of point in a leaf + unsigned int targetMaxDepth; //max tree depth + unsigned int numLevel; //actual tree depth + bool isBalanced; //true if the tree is balanced + }; + + + template + KdTree::KdTree(const ConstDataWrapper& points, unsigned int nofPointsPerCell, unsigned int maxDepth, bool balanced) + : mPoints(points.size()), mIndices(points.size()) + { + // compute the AABB of the input + mPoints[0] = points[0]; + mAABB.Set(mPoints[0]); + for (unsigned int i = 1; i < mPoints.size(); ++i) + { + mPoints[i] = points[i]; + mIndices[i] = i; + mAABB.Add(mPoints[i]); + } + + targetMaxDepth = maxDepth; + targetCellSize = nofPointsPerCell; + isBalanced = balanced; + //mNodes.reserve(4 * mPoints.size() / nofPointsPerCell); //first node inserted (no leaf). The others are made by the createTree function (recursively) - mNodes.resize(1); - mNodes.back().leaf = 0; - /*int numLevel = */ - createTree(0, 0, mPoints.size(), 1, nofPointsPerCell, maxDepth); - } + mNodes.resize(1); + mNodes.back().leaf = 0; + numLevel = createTree(0, 0, mPoints.size(), 1); + } - template - KdTree::~KdTree() + template + KdTree::~KdTree() + { + } + + + /** Performs the kNN query. + * + * This algorithm uses the simple distance to the split plane to prune nodes. + * A more elaborated approach consists to track the closest corner of the cell + * relatively to the current query point. This strategy allows to save about 5% + * of the leaves. However, in practice the slight overhead due to this tracking + * reduces the overall performance. + * + * This algorithm also use a simple stack while a priority queue using the squared + * distances to the cells as a priority values allows to save about 10% of the leaves. + * But, again, priority queue insertions and deletions are quite involved, and therefore + * a simple stack is by far much faster. + * + * The result of the query, the k-nearest neighbors, are stored into the stack mNeighborQueue, where the + * topmost element [0] is NOT the nearest but the farthest!! (they are not sorted but arranged into a heap). + */ + template + void KdTree::doQueryK(const VectorType& queryPoint, int k, PriorityQueue& mNeighborQueue) + { + mNeighborQueue.setMaxSize(k); + mNeighborQueue.init(); + + std::vector mNodeStack(numLevel + 1); + mNodeStack[0].nodeId = 0; + mNodeStack[0].sq = 0.f; + unsigned int count = 1; + + while (count) { - } + //we select the last node (AABB) inserted in the stack + QueryNode& qnode = mNodeStack[count - 1]; + //while going down the tree qnode.nodeId is the nearest sub-tree, otherwise, + //in backtracking, qnode.nodeId is the other sub-tree that will be visited iff + //the actual nearest node is further than the split distance. + Node& node = mNodes[qnode.nodeId]; - /** Performs the kNN query. - * - * This algorithm uses the simple distance to the split plane to prune nodes. - * A more elaborated approach consists to track the closest corner of the cell - * relatively to the current query point. This strategy allows to save about 5% - * of the leaves. However, in practice the slight overhead due to this tracking - * reduces the overall performance. - * - * This algorithm also use a simple stack while a priority queue using the squared - * distances to the cells as a priority values allows to save about 10% of the leaves. - * But, again, priority queue insertions and deletions are quite involved, and therefore - * a simple stack is by far much faster. - * - * The result of the query, the k-nearest neighbors, are stored into the stack mNeighborQueue, where the - * topmost element [0] is NOT the nearest but the farthest!! (they are not sorted but arranged into a heap). - */ - template - void KdTree::doQueryK(const VectorType& queryPoint, int k, PriorityQueue& mNeighborQueue) - { - mNeighborQueue.setMaxSize(k); - mNeighborQueue.init(); - - QueryNode mNodeStack[64]; - mNodeStack[0].nodeId = 0; - mNodeStack[0].sq = 0.f; - unsigned int count = 1; - - while (count) + //if the distance is less than the top of the max-heap, it could be one of the k-nearest neighbours + if (mNeighborQueue.getNofElements() < k || qnode.sq < mNeighborQueue.getTopWeight()) + { + //when we arrive to a leaf + if (node.leaf) { - //we select the last node (AABB) inserted in the stack - QueryNode& qnode = mNodeStack[count-1]; + --count; //pop of the leaf - //while going down the tree qnode.nodeId is the nearest sub-tree, otherwise, - //in backtracking, qnode.nodeId is the other sub-tree that will be visited iff - //the actual nearest node is further than the split distance. - Node& node = mNodes[qnode.nodeId]; - - //if the distance is less than the top of the max-heap, it could be one of the k-nearest neighbours - if (mNeighborQueue.getNofElements() < k || qnode.sq < mNeighborQueue.getTopWeight()) - { - //when we arrive to a leaf - if (node.leaf) - { - --count; //pop of the leaf - - //end is the index of the last element of the leaf in mPoints - unsigned int end = node.start+node.size; - //adding the element of the leaf to the heap - for (unsigned int i=node.start ; i - void KdTree::doQueryDist(const VectorType& queryPoint, float dist, std::vector& points, std::vector& sqrareDists) - { - QueryNode mNodeStack[64]; - mNodeStack[0].nodeId = 0; - mNodeStack[0].sq = 0.f; - unsigned int count = 1; - - float sqrareDist = dist*dist; - while (count) - { - QueryNode& qnode = mNodeStack[count-1]; - Node & node = mNodes[qnode.nodeId]; - - if (qnode.sq < sqrareDist) - { - if (node.leaf) - { - --count; // pop - unsigned int end = node.start+node.size; - for (unsigned int i=node.start ; i - void KdTree::doQueryClosest(const VectorType& queryPoint, unsigned int& index, Scalar& dist) - { - QueryNode mNodeStack[64]; - mNodeStack[0].nodeId = 0; - mNodeStack[0].sq = 0.f; - unsigned int count = 1; - - int minIndex = mIndices.size() / 2; - Scalar minDist = vcg::SquaredNorm(queryPoint - mPoints[minIndex]); - minIndex = mIndices[minIndex]; - - while (count) - { - QueryNode& qnode = mNodeStack[count-1]; - Node & node = mNodes[qnode.nodeId]; - - if (qnode.sq < minDist) - { - if (node.leaf) - { - --count; // pop - unsigned int end = node.start+node.size; - for (unsigned int i=node.start ; i - unsigned int KdTree::split(int start, int end, unsigned int dim, float splitValue) - { - int l(start), r(end-1); - for ( ; l= start && mPoints[r][dim] >= splitValue) - r--; - if (l > r) - break; - std::swap(mPoints[l],mPoints[r]); - std::swap(mIndices[l],mIndices[r]); - } - //returns the index of the first element on the second part - return (mPoints[l][dim] < splitValue ? l+1 : l); - } - - /** recursively builds the kdtree - * - * The heuristic is the following: - * - if the number of points in the node is lower than targetCellsize then make a leaf - * - else compute the AABB of the points of the node and split it at the middle of - * the largest AABB dimension. - * - * This strategy might look not optimal because it does not explicitly prune empty space, - * unlike more advanced SAH-like techniques used for RT. On the other hand it leads to a shorter tree, - * faster to traverse and our experience shown that in the special case of kNN queries, - * this strategy is indeed more efficient (and much faster to build). Moreover, for volume data - * (e.g., fluid simulation) pruning the empty space is useless. - * - * Actually, storing at each node the exact AABB (we therefore have a binary BVH) allows - * to prune only about 10% of the leaves, but the overhead of this pruning (ball/ABBB intersection) - * is more expensive than the gain it provides and the memory consumption is x4 higher ! - */ - template - int KdTree::createTree(unsigned int nodeId, unsigned int start, unsigned int end, unsigned int level, unsigned int targetCellSize, unsigned int targetMaxDepth) - { - //select the first node - Node& node = mNodes[nodeId]; - AxisAlignedBoxType aabb; - - //putting all the points in the bounding box - aabb.Set(mPoints[start]); - for (unsigned int i=start+1 ; i diag.Y()) - dim = diag.X() > diag.Z() ? 0 : 2; + //otherwise, if we're not on a leaf else - dim = diag.Y() > diag.Z() ? 1 : 2; + { + // the new offset is the distance between the searched point and the actual split coordinate + float new_off = queryPoint[node.dim] - node.splitValue; - node.dim = dim; - //we divide the bounding box in 2 partitions, considering the average of the "dim" dimension - node.splitValue = Scalar(0.5*(aabb.max[dim] + aabb.min[dim])); - - //midId is the index of the first element in the second partition - unsigned int midId = split(start, end, dim, node.splitValue); + //left sub-tree + if (new_off < 0.) + { + mNodeStack[count].nodeId = node.firstChildId; + //in the father's nodeId we save the index of the other sub-tree (for backtracking) + qnode.nodeId = node.firstChildId + 1; + } + //right sub-tree (same as above) + else + { + mNodeStack[count].nodeId = node.firstChildId + 1; + qnode.nodeId = node.firstChildId; + } + //distance is inherited from the father (while descending the tree it's equal to 0) + mNodeStack[count].sq = qnode.sq; + //distance of the father is the squared distance from the split plane + qnode.sq = new_off*new_off; + ++count; + } + } + else + { + // pop + --count; + } + } + } - node.firstChildId = mNodes.size(); - mNodes.resize(mNodes.size()+2); + /** Performs the distance query. + * + * The result of the query, all the points within the distance dist form the query point, is the vector of the indeces + * and the vector of the squared distances from the query point. + */ + template + void KdTree::doQueryDist(const VectorType& queryPoint, float dist, std::vector& points, std::vector& sqrareDists) + { + std::vector mNodeStack(numLevel + 1); + mNodeStack[0].nodeId = 0; + mNodeStack[0].sq = 0.f; + unsigned int count = 1; + + float sqrareDist = dist*dist; + while (count) + { + QueryNode& qnode = mNodeStack[count - 1]; + Node & node = mNodes[qnode.nodeId]; + + if (qnode.sq < sqrareDist) + { + if (node.leaf) + { + --count; // pop + unsigned int end = node.start + node.size; + for (unsigned int i = node.start; i < end; ++i) + { + float pointSquareDist = vcg::SquaredNorm(queryPoint - mPoints[i]); + if (pointSquareDist < sqrareDist) + { + points.push_back(mIndices[i]); + sqrareDists.push_back(pointSquareDist); + } + } + } + else + { + // replace the stack top by the farthest and push the closest + float new_off = queryPoint[node.dim] - node.splitValue; + if (new_off < 0.) + { + mNodeStack[count].nodeId = node.firstChildId; + qnode.nodeId = node.firstChildId + 1; + } + else + { + mNodeStack[count].nodeId = node.firstChildId + 1; + qnode.nodeId = node.firstChildId; + } + mNodeStack[count].sq = qnode.sq; + qnode.sq = new_off*new_off; + ++count; + } + } + else + { + // pop + --count; + } + } + } + + + /** Searchs the closest point. + * + * The result of the query, the closest point to the query point, is the index of the point and + * and the squared distance from the query point. + */ + template + void KdTree::doQueryClosest(const VectorType& queryPoint, unsigned int& index, Scalar& dist) + { + std::vector mNodeStack(numLevel + 1); + mNodeStack[0].nodeId = 0; + mNodeStack[0].sq = 0.f; + unsigned int count = 1; + + int minIndex = mIndices.size() / 2; + Scalar minDist = vcg::SquaredNorm(queryPoint - mPoints[minIndex]); + minIndex = mIndices[minIndex]; + + while (count) + { + QueryNode& qnode = mNodeStack[count - 1]; + Node & node = mNodes[qnode.nodeId]; + + if (qnode.sq < minDist) + { + if (node.leaf) + { + --count; // pop + unsigned int end = node.start + node.size; + for (unsigned int i = node.start; i < end; ++i) + { + float pointSquareDist = vcg::SquaredNorm(queryPoint - mPoints[i]); + if (pointSquareDist < minDist) + { + minDist = pointSquareDist; + minIndex = mIndices[i]; + } + } + } + else + { + // replace the stack top by the farthest and push the closest + float new_off = queryPoint[node.dim] - node.splitValue; + if (new_off < 0.) + { + mNodeStack[count].nodeId = node.firstChildId; + qnode.nodeId = node.firstChildId + 1; + } + else + { + mNodeStack[count].nodeId = node.firstChildId + 1; + qnode.nodeId = node.firstChildId; + } + mNodeStack[count].sq = qnode.sq; + qnode.sq = new_off*new_off; + ++count; + } + } + else + { + // pop + --count; + } + } + index = minIndex; + dist = minDist; + } + + + + /** + * Split the subarray between start and end in two part, one with the elements less than splitValue, + * the other with the elements greater or equal than splitValue. The elements are compared + * using the "dim" coordinate [0 = x, 1 = y, 2 = z]. + */ + template + unsigned int KdTree::split(int start, int end, unsigned int dim, float splitValue) + { + int l(start), r(end - 1); + for (; l < r; ++l, --r) + { + while (l < end && mPoints[l][dim] < splitValue) + l++; + while (r >= start && mPoints[r][dim] >= splitValue) + r--; + if (l > r) + break; + std::swap(mPoints[l], mPoints[r]); + std::swap(mIndices[l], mIndices[r]); + } + //returns the index of the first element on the second part + return (mPoints[l][dim] < splitValue ? l + 1 : l); + } + + /** recursively builds the kdtree + * + * The heuristic is the following: + * - if the number of points in the node is lower than targetCellsize then make a leaf + * - else compute the AABB of the points of the node and split it at the middle of + * the largest AABB dimension. + * + * This strategy might look not optimal because it does not explicitly prune empty space, + * unlike more advanced SAH-like techniques used for RT. On the other hand it leads to a shorter tree, + * faster to traverse and our experience shown that in the special case of kNN queries, + * this strategy is indeed more efficient (and much faster to build). Moreover, for volume data + * (e.g., fluid simulation) pruning the empty space is useless. + * + * Actually, storing at each node the exact AABB (we therefore have a binary BVH) allows + * to prune only about 10% of the leaves, but the overhead of this pruning (ball/ABBB intersection) + * is more expensive than the gain it provides and the memory consumption is x4 higher ! + */ + template + int KdTree::createTree(unsigned int nodeId, unsigned int start, unsigned int end, unsigned int level) + { + //select the first node + Node& node = mNodes[nodeId]; + AxisAlignedBoxType aabb; + + //putting all the points in the bounding box + aabb.Set(mPoints[start]); + for (unsigned int i = start + 1; i < end; ++i) + aabb.Add(mPoints[i]); + + //bounding box diagonal + VectorType diag = aabb.max - aabb.min; + + //the split "dim" is the dimension of the box with the biggest value + unsigned int dim; + if (diag.X() > diag.Y()) + dim = diag.X() > diag.Z() ? 0 : 2; + else + dim = diag.Y() > diag.Z() ? 1 : 2; + + node.dim = dim; + if (isBalanced) //we divide the points using the median value along the "dim" dimension + { + std::vector tempVector; + for (unsigned int i = start + 1; i < end; ++i) + tempVector.push_back(mPoints[i][dim]); + std::sort(tempVector.begin(), tempVector.end()); + node.splitValue = (tempVector[tempVector.size() / 2.0] + tempVector[tempVector.size() / 2.0 + 1]) / 2.0; + } + else //we divide the bounding box in 2 partitions, considering the average of the "dim" dimension + node.splitValue = Scalar(0.5*(aabb.max[dim] + aabb.min[dim])); + + //midId is the index of the first element in the second partition + unsigned int midId = split(start, end, dim, node.splitValue); + + node.firstChildId = mNodes.size(); + mNodes.resize(mNodes.size() + 2); + bool flag = (midId == start) || (midId == end); int leftLevel, rightLevel; - - { - // left child - unsigned int childId = mNodes[nodeId].firstChildId; - Node& child = mNodes[childId]; - if (midId - start <= targetCellSize || level>=targetMaxDepth) - { - child.leaf = 1; - child.start = start; - child.size = midId - start; + { + // left child + unsigned int childId = mNodes[nodeId].firstChildId; + Node& child = mNodes[childId]; + if (flag || (midId - start) <= targetCellSize || level >= targetMaxDepth) + { + child.leaf = 1; + child.start = start; + child.size = midId - start; leftLevel = level; - } - else - { - child.leaf = 0; - leftLevel = createTree(childId, start, midId, level+1, targetCellSize, targetMaxDepth); - } - } + } + else + { + child.leaf = 0; + leftLevel = createTree(childId, start, midId, level + 1); + } + } - { - // right child - unsigned int childId = mNodes[nodeId].firstChildId+1; - Node& child = mNodes[childId]; - if (end - midId <= targetCellSize || level>=targetMaxDepth) - { - child.leaf = 1; - child.start = midId; - child.size = end - midId; + { + // right child + unsigned int childId = mNodes[nodeId].firstChildId + 1; + Node& child = mNodes[childId]; + if (flag || (end - midId) <= targetCellSize || level >= targetMaxDepth) + { + child.leaf = 1; + child.start = midId; + child.size = end - midId; rightLevel = level; - } - else - { - child.leaf = 0; - rightLevel = createTree(childId, midId, end, level+1, targetCellSize, targetMaxDepth); - } - } + } + else + { + child.leaf = 0; + rightLevel = createTree(childId, midId, end, level + 1); + } + } if (leftLevel > rightLevel) return leftLevel; return rightLevel; - } + } + } #endif From 82300062f81a3a97c1c67e75fd0972c9b101d858 Mon Sep 17 00:00:00 2001 From: gianpaolopalma Date: Wed, 16 Nov 2016 11:24:12 +0100 Subject: [PATCH 56/91] Added a new implementation of the kdtree for faces --- vcg/space/index/kdtree/kdtree_face.h | 300 +++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 vcg/space/index/kdtree/kdtree_face.h diff --git a/vcg/space/index/kdtree/kdtree_face.h b/vcg/space/index/kdtree/kdtree_face.h new file mode 100644 index 00000000..3fc373ee --- /dev/null +++ b/vcg/space/index/kdtree/kdtree_face.h @@ -0,0 +1,300 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004-2016 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +#ifndef KDTREE_FACE_H +#define KDTREE_FACE_H + +#include +#include + +namespace vcg { + + /** + * This class allows to create a Kd-Tree thought to perform the neighbour query using the mesh faces (closest search). + * The class implemetantion is thread-safe. + */ + template + class KdTreeFace + { + public: + + typedef typename MeshType::ScalarType Scalar; + typedef typename MeshType::CoordType VectorType; + typedef typename MeshType::BoxType AxisAlignedBoxType; + typedef typename MeshType::FacePointer FacePointer; + + class Node + { + public: + Scalar splitValue; + unsigned int firstChildId : 24; + unsigned int dim : 2; + unsigned int leaf : 1; + AxisAlignedBoxType aabb; + std::vector list; + }; + typedef std::vector NodeListPointer; + + public: + + KdTreeFace(MeshType& mesh, unsigned int maxObjPerCell = 64, unsigned int maxDepth = 64) : epsilon(std::numeric_limits::epsilon()) + { + targetCellSize = maxObjPerCell; + targetMaxDepth = maxDepth; + mNodes.resize(1); + Node& node = mNodes.back(); + node.leaf = 0; + node.aabb = mesh.bbox; + node.aabb.Offset(VectorType(epsilon, epsilon, epsilon)); + for (int i = 0; i < mesh.face.size(); i++) + node.list.push_back(&mesh.face[i]); + numLevel = createTree(0, 1); + }; + + ~KdTreeFace() + { + + }; + + + template FacePointer doQueryClosest(const VectorType& queryPoint, VectorType& narestPoint, Scalar& dist, ObjectMarker& marker, Scalar maxDist = std::numeric_limits::max()) + { + if (maxDist < std::numeric_limits::max() && !mNodes[0].aabb.IsIn(queryPoint) && vcg::PointFilledBoxDistance(queryPoint, mNodes[0].aabb) >= maxDist) + { + dist = maxDist; + return NULL; + } + std::vector mNodeStack(numLevel + 1); + mNodeStack[0].nodeId = 0; + mNodeStack[0].sq = 0.f; + unsigned int count = 1; + + Scalar minDist = maxDist; + VectorType p; + FacePointer face = NULL; + while (count) + { + QueryNode& qnode = mNodeStack[count - 1]; + Node& node = mNodes[qnode.nodeId]; + + if (qnode.sq < minDist) + { + if (node.leaf) + { + --count; // pop + for (int i = 0; i < node.list.size(); i++) + { + if (!marker.IsMarked(node.list[i])) + { + marker.Mark(node.list[i]); + Scalar tempDist = minDist; + VectorType tempP; + if (vcg::face::PointDistanceBase(*node.list[i], queryPoint, tempDist, tempP)) + { + if (tempDist < minDist) + { + minDist = tempDist; + p = tempP; + face = node.list[i]; + } + } + } + } + } + else + { + // replace the stack top by the farthest and push the closest + float new_off = queryPoint[node.dim] - node.splitValue; + float abs_off = abs(new_off); + if (abs_off < minDist) + { + if (new_off < 0.) + { + mNodeStack[count].nodeId = node.firstChildId; + qnode.nodeId = node.firstChildId + 1; + new_off = vcg::PointFilledBoxDistance(queryPoint, mNodes[node.firstChildId + 1].aabb); + } + else + { + mNodeStack[count].nodeId = node.firstChildId + 1; + qnode.nodeId = node.firstChildId; + new_off = vcg::PointFilledBoxDistance(queryPoint, mNodes[node.firstChildId].aabb); + } + mNodeStack[count].sq = qnode.sq; + qnode.sq = new_off; + ++count; + } + else + { + if (new_off < 0.) + qnode.nodeId = node.firstChildId; + else + qnode.nodeId = node.firstChildId + 1; + } + } + } + else + { + // pop + --count; + } + } + dist = minDist; + narestPoint = p; + return face; + } + + protected: + + // element of the stack + struct QueryNode + { + QueryNode() {} + QueryNode(unsigned int id) : nodeId(id) {} + unsigned int nodeId; // id of the next node + Scalar sq; // distance to the next node + }; + + + int createTree(unsigned int nodeId, unsigned int level) + { + Node& node = mNodes[nodeId]; + VectorType diag = node.aabb.max - node.aabb.min; + unsigned int dim; + if (diag.X() > diag.Y()) + dim = diag.X() > diag.Z() ? 0 : 2; + else + dim = diag.Y() > diag.Z() ? 1 : 2; + + node.splitValue = Scalar(0.5*(node.aabb.max[dim] + node.aabb.min[dim])); + node.dim = dim; + + AxisAlignedBoxType leftBox, rightBox; + leftBox.Add(node.aabb.min); + rightBox.Add(node.aabb.max); + if (node.dim == 0) + { + leftBox.Add(VectorType(node.splitValue, node.aabb.max[1], node.aabb.max[2])); + rightBox.Add(VectorType(node.splitValue, node.aabb.min[1], node.aabb.min[2])); + } + else if (node.dim == 1) + { + leftBox.Add(VectorType(node.aabb.max[0], node.splitValue, node.aabb.max[2])); + rightBox.Add(VectorType(node.aabb.min[0], node.splitValue, node.aabb.min[2])); + } + else if (node.dim == 2) + { + leftBox.Add(VectorType(node.aabb.max[0], node.aabb.max[1], node.splitValue)); + rightBox.Add(VectorType(node.aabb.min[0], node.aabb.min[1], node.splitValue)); + } + leftBox.Offset(VectorType(epsilon, epsilon, epsilon)); + rightBox.Offset(VectorType(epsilon, epsilon, epsilon)); + + node.firstChildId = mNodes.size(); + int firstChildId = node.firstChildId; + mNodes.resize(mNodes.size() + 2); + Node& parent = mNodes[nodeId]; + Node& leftChild = mNodes[firstChildId]; + Node& rightChild = mNodes[firstChildId + 1]; + leftChild.aabb.SetNull(); + rightChild.aabb.SetNull(); + + for (int i = 0; i < parent.list.size(); i++) + { + unsigned int state = 0; + FacePointer fp = parent.list[i]; + for (int j = 0; j < 3; j++) + { + if (fp->P(j)[dim] < parent.splitValue) + state |= (1 << 0); + else if (fp->P(j)[dim] > parent.splitValue) + state |= (1 << 1); + else + { + state |= (1 << 0); + state |= (1 << 1); + } + } + if (state & (1 << 0)) + { + leftChild.list.push_back(fp); + leftChild.aabb.Add(fp->P(0)); + leftChild.aabb.Add(fp->P(1)); + leftChild.aabb.Add(fp->P(2)); + } + if (state & (1 << 1)) + { + rightChild.list.push_back(fp); + rightChild.aabb.Add(fp->P(0)); + rightChild.aabb.Add(fp->P(1)); + rightChild.aabb.Add(fp->P(2)); + } + } + parent.list.clear(); + leftChild.aabb.Intersect(leftBox); + rightChild.aabb.Intersect(rightBox); + + int leftLevel, rightLevel; + { + if (leftChild.list.size() <= targetCellSize || level >= targetMaxDepth) + { + leftChild.leaf = 1; + leftLevel = level; + } + else + { + leftChild.leaf = 0; + leftLevel = createTree(firstChildId, level + 1); + } + } + + { + Node& rightChild = mNodes[firstChildId + 1]; + if (rightChild.list.size() <= targetCellSize || level >= targetMaxDepth) + { + rightChild.leaf = 1; + rightLevel = level; + } + else + { + rightChild.leaf = 0; + rightLevel = createTree(firstChildId + 1, level + 1); + } + } + if (leftLevel > rightLevel) + return leftLevel; + return rightLevel; + }; + + + protected: + + NodeListPointer mNodes; //kd-tree nodes + unsigned int numLevel; + const Scalar epsilon; + unsigned int targetCellSize; + unsigned int targetMaxDepth; + }; + +} +#endif From f4feeb5d5b583b38902deeaea168c80abd873009 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Fri, 18 Nov 2016 09:16:52 +0100 Subject: [PATCH 57/91] Added support of backslash terminated lines in OBJ --- wrap/io_trimesh/import_obj.h | 176 ++++++----------------------------- 1 file changed, 28 insertions(+), 148 deletions(-) diff --git a/wrap/io_trimesh/import_obj.h b/wrap/io_trimesh/import_obj.h index 3c3001eb..84c06cba 100644 --- a/wrap/io_trimesh/import_obj.h +++ b/wrap/io_trimesh/import_obj.h @@ -524,7 +524,6 @@ namespace vcg { locInd[iii]=indexTriangulatedVect[pi+iii]; ff.v[iii]=indexVVect[ locInd[iii] ]; ff.n[iii]=indexNVect[ locInd[iii] ]; -// qDebug("ff.n[iii]=indexNVect[ locInd[iii] ]; %i", ff.n[iii]); ff.t[iii]=indexTVect[ locInd[iii] ]; } @@ -644,14 +643,11 @@ namespace vcg { for(int i=0; i= 0 && size_t(e.v0) < m.vert.size() && e.v1 >= 0 && size_t(e.v1) < m.vert.size()); // TODO add proper handling of bad indices - - edge.V(0) = &(m.vert[e.v0]); - edge.V(1) = &(m.vert[e.v1]); + m.edge[i].V(0) = &(m.vert[e.v0]); + m.edge[i].V(1) = &(m.vert[e.v1]); } } //------------------------------------------------------------------------------- @@ -664,7 +660,9 @@ namespace vcg { m.face[i].Alloc(indexedFaces[i].v.size()); // it does not do anything if it is a trimesh for(unsigned int j=0;j=0 && vertInd < m.vn); m.face[i].V(j) = &(m.vert[indexedFaces[i].v[j]]); if (((oi.mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) != 0) && (HasPerWedgeTexCoord(m))) @@ -687,7 +685,6 @@ namespace vcg { if ( oi.mask & vcg::tri::io::Mask::IOM_VERTNORMAL ) { -// qDebug("XXXXXX %i",indexedFaces[i].n[j]); m.face[i].V(j)->N().Import(normals[indexedFaces[i].n[j]]); } @@ -734,10 +731,10 @@ namespace vcg { /*! - * Read the next valid line and parses it into "tokens", allowing - * the tokens to be read one at a time. - * \param stream The object providing the input stream - * \param tokens The "tokens" in the next line + * Read the next valid line and parses it into "tokens" (e.g. groups like 234/234/234), allowing + * the tokens to be read one at a time. It read multiple lines concatenating them if they end with '\' + * \param stream The object providing the input stream + * \param tokens The "tokens" in the next line */ inline static void TokenizeNextLine(std::ifstream &stream, std::vector< std::string > &tokens, std::vector *colVec) { @@ -746,6 +743,16 @@ namespace vcg { do { std::getline(stream, line); + // We have to manage backspace terminated lines, + // joining them together before parsing them + if(line.back()==13) line.pop_back(); + while(line.back()=='\\') { + std::string tmpLine; + std::getline(stream, tmpLine); + if(tmpLine.back()==13) line.pop_back(); + line.pop_back(); + line.append(tmpLine); + } const size_t len = line.length(); if((len > 0) && colVec && line[0] == '#') { @@ -798,6 +805,12 @@ namespace vcg { while (from %i %i %i",token.c_str(),vId,nId,tId); - /* - const std::string vStr = (hasPosition) ? (token.substr(0, firstSep)) : ("0"); - const std::string tStr = (hasTexcoord) ? (token.substr(firstSep + 1, secondSep - firstSep - 1)) : ("0"); - const std::string nStr = (hasNormal) ? (token.substr(secondSep + 1)) : ("0"); - - if (!vStr.empty()) vId = atoi(vStr.c_str()) - 1; - if (!tStr.empty()) tId = atoi(tStr.c_str()) - 1; - if (!nStr.empty()) nId = atoi(nStr.c_str()) - 1; - */ } -#if 0 - // This function takes a token and, according to the mask, it returns the indexes of the involved vertex, normal and texcoord indexes. - // Example. if the obj file has vertex texcoord (e.g. lines 'vt 0.444 0.5555') - // when parsing a line like - // f 46/303 619/325 624/326 623/327 - // if in the mask you have specified to read wedge tex coord - // for the first token it will return inside vId and tId the corresponding indexes 46 and 303 ) - inline static void SplitToken(std::string token, int &vId, int &nId, int &tId, int mask) - { - std::string vertex; - std::string texcoord; - std::string normal; - - if( ( mask & Mask::IOM_WEDGTEXCOORD ) && (mask & Mask::IOM_WEDGNORMAL) ) SplitVVTVNToken(token, vertex, texcoord, normal); - if(!( mask & Mask::IOM_WEDGTEXCOORD ) && (mask & Mask::IOM_WEDGNORMAL) ) SplitVVNToken(token, vertex, normal); - if( ( mask & Mask::IOM_WEDGTEXCOORD ) &&!(mask & Mask::IOM_WEDGNORMAL) ) SplitVVTToken(token, vertex, texcoord); - if(!( mask & Mask::IOM_WEDGTEXCOORD ) &&!(mask & Mask::IOM_WEDGNORMAL) ) SplitVToken(token, vertex); - - vId = atoi(vertex.c_str()) - 1; - if(mask & Mask::IOM_WEDGTEXCOORD) tId = atoi(texcoord.c_str()) - 1; - if(mask & Mask::IOM_WEDGNORMAL) nId = atoi(normal.c_str()) - 1; - } - - inline static void SplitVToken(std::string token, std::string &vertex) - { - vertex = token; - } - - inline static void SplitVVTToken(std::string token, std::string &vertex, std::string &texcoord) - { - vertex.clear(); - texcoord.clear(); - - size_t from = 0; - size_t to = 0; - size_t length = token.size(); - - if(from!=length) - { - char c = token[from]; - vertex.push_back(c); - - to = from+1; - while (to Date: Mon, 21 Nov 2016 12:00:56 +0100 Subject: [PATCH 58/91] - fixed crash derived from changing mesh topology without updating internal data structures --- wrap/gl/pick.h | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/wrap/gl/pick.h b/wrap/gl/pick.h index c8878491..d4ea2e8d 100644 --- a/wrap/gl/pick.h +++ b/wrap/gl/pick.h @@ -155,7 +155,7 @@ public: Box3 reg =ComputeDCBox(x,y,width,height); - if(M!=lastM || &m != lastm) + if ((M != lastM) || (&m != lastm) || (pVec.size() != m.VN())) { FillProjectedVector(m,pVec,M,viewportF); lastM = M; @@ -184,21 +184,24 @@ public: reg.Add(CoordType(x-width/ScalarType(2.0),y-height/ScalarType(2.0),ScalarType(-1.0))); reg.Add(CoordType(x+width/ScalarType(2.0),y+height/ScalarType(2.0),ScalarType(1.0))); - if(M!=lastM || &m != lastm) + if((M!=lastM) || (&m != lastm) || (pVec.size() != m.VN())) { FillProjectedVector(m,pVec,M,viewportF); lastM = M; lastm = &m; } - for(size_t i=0;i-1.0f) && (p1[2]>-1.0f) && (p2[2]>-1.0f) && IntersectionTriangleBox(reg,p0,p1,p2)) - result.push_back(&m.face[i]); - } + for (size_t i = 0; i < m.face.size(); ++i) + { + if (!m.face[i].IsD()) + { + const CoordType &p0 = pVec[tri::Index(m, m.face[i].V(0))]; + const CoordType &p1 = pVec[tri::Index(m, m.face[i].V(1))]; + const CoordType &p2 = pVec[tri::Index(m, m.face[i].V(2))]; + if ((p0[2] > -1.0f) && (p1[2] > -1.0f) && (p2[2] > -1.0f) && IntersectionTriangleBox(reg, p0, p1, p2)) + result.push_back(&m.face[i]); + } + } return result.size(); } From 84c99ef92023b0d0116ec81f7d0f1da2b4fbe0db Mon Sep 17 00:00:00 2001 From: Marco Callieri Date: Mon, 21 Nov 2016 17:07:40 +0100 Subject: [PATCH 59/91] added axis display on trackball pan When the trackball is panned, axes are rendered in the trackball sphere --- wrap/gui/trackmode.cpp | 3 +- wrap/gui/trackutils.h | 66 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/wrap/gui/trackmode.cpp b/wrap/gui/trackmode.cpp index c2688cd4..f8157f62 100644 --- a/wrap/gui/trackmode.cpp +++ b/wrap/gui/trackmode.cpp @@ -95,7 +95,8 @@ void PanMode::Apply (Trackball * tb, Point3f new_point) } void PanMode::Draw(Trackball * tb){ - DrawSphereIcon(tb,true ); + DrawSphereIcon(tb,true); + DrawSphereAxis(tb); DrawUglyPanMode(tb); } diff --git a/wrap/gui/trackutils.h b/wrap/gui/trackutils.h index b9438dc1..4e3d1ede 100644 --- a/wrap/gui/trackutils.h +++ b/wrap/gui/trackutils.h @@ -707,15 +707,15 @@ void DrawSphereIcon (Trackball * tb, bool active, bool planeshandle=false) glRotatef (90, 1, 0, 0); col[0] = .40f; col[1] = .85f; col[2] = .40f; glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col); - DrawCircle(planeshandle); + DrawCircle(planeshandle); glRotatef (90, 0, 1, 0); col[0] = .85f; col[1] = .40f; col[2] = .40f; glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col); DrawCircle(planeshandle); - glPopMatrix (); - glPopAttrib (); + glPopMatrix(); + glPopAttrib(); } // TEMPORARY drawing section @@ -832,6 +832,66 @@ void DrawUglyScaleMode(Trackball * tb) DrawUglyLetter(tb,ugly_s); } +/*! +@brief function to draw X,Y and Z axis in the trackball sphere. + +Draws the three colored axis inside the trackball sphere. added to better see the trackball center when panning + +@param tb the manipulator. +*/ +void DrawSphereAxis(Trackball * tb) +{ + glPushAttrib(GL_TRANSFORM_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glDepthMask(GL_FALSE); + + Point3f center = tb->center + tb->track.InverseMatrix()*Point3f(0, 0, 0); + glTranslate(center); + glScale(tb->radius / tb->track.sca); + + float amb[4] = { .35f, .35f, .35f, 1.0f }; + float col[4] = { .5f, .5f, .8f, 1.0f }; + glEnable(GL_LINE_SMOOTH); + glLineWidth(DH.LineWidthMoving); + glDisable(GL_COLOR_MATERIAL); // has to be disabled, it is used by wrapper to draw meshes, and prevent direct material setting, used here + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor(DH.color); + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, amb); + + col[0] = 1.0f; col[1] = 0.0f; col[2] = 0.0f; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col); + glBegin(GL_LINES); + glNormal3d(-1.0, 0.0, 0.0); + glVertex3d(-1.2, 0.0, 0.0); + glNormal3d( 1.0, 0.0, 0.0); + glVertex3d( 1.2, 0.0, 0.0); + glEnd(); + col[0] = 0.0f; col[1] = 1.0f; col[2] = 0.0f; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col); + glBegin(GL_LINES); + glNormal3d(0.0,-1.0, 0.0); + glVertex3d(0.0,-1.2, 0.0); + glNormal3d(0.0, 1.0, 0.0); + glVertex3d(0.0, 1.2, 0.0); + glEnd(); + col[0] = 0.0f; col[1] = 0.0f; col[2] = 1.0f; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col); + glBegin(GL_LINES); + glNormal3d(0.0, 0.0,-1.0); + glVertex3d(0.0, 0.0,-1.2); + glNormal3d(0.0, 0.0, 1.0); + glVertex3d(0.0, 0.0, 1.2); + glEnd(); + + glPopMatrix(); + glPopAttrib(); +} + /*! @brief AxisMode drawing function, member of the \e DrawUgly series. From a52d3149b10e8844f82f45617c57cf9d349a5ca5 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 24 Nov 2016 11:59:50 +0100 Subject: [PATCH 60/91] Added an enum for opening success (E_NOERROR) common to all the imported --- wrap/io_trimesh/import.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wrap/io_trimesh/import.h b/wrap/io_trimesh/import.h index 39ef6555..96d161bb 100644 --- a/wrap/io_trimesh/import.h +++ b/wrap/io_trimesh/import.h @@ -93,6 +93,9 @@ return lastType; } public: +enum ImporterError { + E_NOERROR =0 // No error =0 is the standard for ALL the imported files. +}; // simple aux function that returns true if a given file has a given extesnion static bool FileExtension(std::string filename, std::string extension) { From 62f9ecf60233b49dab00b67ae72c06c61a9ee357 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 24 Nov 2016 12:00:03 +0100 Subject: [PATCH 61/91] Harmless warning --- wrap/io_trimesh/export_ply.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/io_trimesh/export_ply.h b/wrap/io_trimesh/export_ply.h index 5ac018ad..73ed0622 100644 --- a/wrap/io_trimesh/export_ply.h +++ b/wrap/io_trimesh/export_ply.h @@ -405,7 +405,7 @@ namespace vcg { fprintf(fpout,"%.*g %.*g %.*g " ,DGT,vp->P()[0],DGT,vp->P()[1],DGT,vp->P()[2]); if( HasPerVertexNormal(m) && (pi.mask & Mask::IOM_VERTNORMAL) ) - fprintf(fpout,"%.*g %.*g %.*g " ,DGT,vp->N()[0],DGT,vp->N()[1],DGT,vp->N()[2]); + fprintf(fpout,"%.*g %.*g %.*g " ,DGT,double(vp->N()[0]),DGT,double(vp->N()[1]),DGT,double(vp->N()[2])); if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS)) fprintf(fpout,"%d ",vp->Flags()); From 22b633c9c27ebdee2e8f33a99dafab66bb4c30e2 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 24 Nov 2016 13:29:26 +0100 Subject: [PATCH 62/91] Corrected bug of trivial walker when used on a sub volume --- .../algorithms/create/mc_trivial_walker.h | 53 ++++++++----------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/vcg/complex/algorithms/create/mc_trivial_walker.h b/vcg/complex/algorithms/create/mc_trivial_walker.h index b7fc9df1..8a745560 100644 --- a/vcg/complex/algorithms/create/mc_trivial_walker.h +++ b/vcg/complex/algorithms/create/mc_trivial_walker.h @@ -108,10 +108,8 @@ public: Vol.resize(this->siz[0]*this->siz[1]*this->siz[2]); this->ComputeDimAndVoxel(); } - - - }; + template class SimpleVoxel { @@ -163,18 +161,10 @@ private: typedef typename MeshType::VertexPointer VertexPointer; public: - // subbox is the portion of the volume to be computed - // resolution determine the sampling step: - // should be a divisor of bbox size (e.g. if bbox size is 256^3 resolution could be 128,64, etc) - - void Init(VolumeType &volume) - { - Init(volume,Box3i(Point3i(0,0,0),volume.ISize())); - } - - void Init(VolumeType &/*volume*/, Box3i subbox) + // SetExtractionBox set the portion of the volume to be traversed + void SetExtractionBox(Box3i subbox) { - _bbox = subbox; + _bbox = subbox; _slice_dimension = _bbox.DimX()*_bbox.DimZ(); _x_cs = new VertexIndex[ _slice_dimension ]; @@ -182,40 +172,39 @@ private: _z_cs = new VertexIndex[ _slice_dimension ]; _x_ns = new VertexIndex[ _slice_dimension ]; _z_ns = new VertexIndex[ _slice_dimension ]; - } - - ~TrivialWalker() - {_thr=0;} + + TrivialWalker() + { + _bbox.SetNull(); + _slice_dimension=0; + } template void BuildMesh(MeshType &mesh, VolumeType &volume, EXTRACTOR_TYPE &extractor, const float threshold, vcg::CallBackPos * cb=0) { - Init(volume); + if(_bbox.IsNull() || _slice_dimension==0) + SetExtractionBox(Box3i(Point3i(0,0,0),volume.ISize())); _volume = &volume; _mesh = &mesh; _mesh->Clear(); _thr=threshold; - vcg::Point3i p1, p2; - Begin(); extractor.Initialize(); for (int j=_bbox.min.Y(); j<(_bbox.max.Y()-1)-1; j+=1) { - if(cb && ((j%10)==0) ) cb(j*_bbox.DimY()/100.0,"Marching volume"); - for (int i=_bbox.min.X(); i<(_bbox.max.X()-1)-1; i+=1) { for (int k=_bbox.min.Z(); k<(_bbox.max.Z()-1)-1; k+=1) { - p1.X()=i; p1.Y()=j; p1.Z()=k; - p2.X()=i+1; p2.Y()=j+1; p2.Z()=k+1; + Point3i p1(i,j,k); + Point3i p2(i+1,j+1,k+1); if(volume.ValidCell(p1,p2)) extractor.ProcessCell(p1, p2); } } - NextSlice(); + NextYSlice(); } extractor.Finalize(); _volume = NULL; @@ -229,7 +218,7 @@ private: bool Exist(const vcg::Point3i &p0, const vcg::Point3i &p1, VertexPointer &v) { - int pos = p0.X()+p0.Z()*_bbox.max.X(); + int pos = p0.X()+p0.Z()*_bbox.DimX(); int vidx; if (p0.X()!=p1.X()) // punti allineati lungo l'asse X @@ -249,8 +238,8 @@ private: { int i = p1.X() - _bbox.min.X(); int z = p1.Z() - _bbox.min.Z(); - VertexIndex index = i+z*_bbox.max.X(); - VertexIndex pos; + VertexIndex index = i+z*_bbox.DimX(); + VertexIndex pos=-1; if (p1.Y()==_current_slice) { if ((pos=_x_cs[index])==-1) @@ -282,7 +271,7 @@ private: { int i = p1.X() - _bbox.min.X(); int z = p1.Z() - _bbox.min.Z(); - VertexIndex index = i+z*_bbox.max.X(); + VertexIndex index = i+z*_bbox.DimX(); VertexIndex pos; if ((pos=_y_cs[index])==-1) { @@ -298,7 +287,7 @@ private: { int i = p1.X() - _bbox.min.X(); int z = p1.Z() - _bbox.min.Z(); - VertexIndex index = i+z*_bbox.max.X(); + VertexIndex index = i+z*_bbox.DimX(); VertexIndex pos; if (p1.Y()==_current_slice) { @@ -343,7 +332,7 @@ protected: VolumeType *_volume; float _thr; - void NextSlice() + void NextYSlice() { memset(_x_cs, -1, _slice_dimension*sizeof(VertexIndex)); memset(_y_cs, -1, _slice_dimension*sizeof(VertexIndex)); From cff044ca387e725c1f0bb47bb23fba4b30e6ec17 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 24 Nov 2016 15:26:20 +0100 Subject: [PATCH 63/91] Header and namespace cleaning --- .../create/plymc/tri_edge_collapse_mc.h | 5 +- vcg/complex/algorithms/local_optimization.h | 72 ------------------- 2 files changed, 4 insertions(+), 73 deletions(-) diff --git a/vcg/complex/algorithms/create/plymc/tri_edge_collapse_mc.h b/vcg/complex/algorithms/create/plymc/tri_edge_collapse_mc.h index 733b4b96..72a391be 100644 --- a/vcg/complex/algorithms/create/plymc/tri_edge_collapse_mc.h +++ b/vcg/complex/algorithms/create/plymc/tri_edge_collapse_mc.h @@ -22,7 +22,8 @@ ****************************************************************************/ #ifndef __TRI_EDGE_COLLAPSE_MC__ #define __TRI_EDGE_COLLAPSE_MC__ -#include +namespace vcg{ +namespace tri{ class TriEdgeCollapseMCParameter : public BaseParameterClass { @@ -125,5 +126,7 @@ class MCTriEdgeCollapse: public tri::TriEdgeCollapse< MCTriMesh, VertexPair, MYT }; +} +} #endif diff --git a/vcg/complex/algorithms/local_optimization.h b/vcg/complex/algorithms/local_optimization.h index e80a8bbb..e72f3420 100644 --- a/vcg/complex/algorithms/local_optimization.h +++ b/vcg/complex/algorithms/local_optimization.h @@ -20,81 +20,9 @@ * for more details. * * * ****************************************************************************/ -/**************************************************************************** - $Log: not supported by cvs2svn $ - Revision 1.20 2007/01/19 09:13:09 cignoni - Added Finalize() method to the interface - - Revision 1.19 2007/01/11 11:48:33 ganovelli - currMetric inizialied to heap.front() (it was heap.back()- wrong) - - Revision 1.18 2006/12/11 14:09:44 ganovelli - added missing initialization of currMetric - - Revision 1.17 2006/06/09 07:28:43 m_di_benedetto - Corrected ClearHeap(): iterator "hi" not decrementable if it was the first of the container. - - Revision 1.16 2005/11/10 15:38:46 cignoni - Added casts to remove warnings - - Revision 1.15 2005/10/02 23:23:52 cignoni - Changed the sense of the < operator for heap: it is reversed according to the stl where highest score elements must float in the heap - Completed TimeBudget Termination condition. - Parametrized the ClearHeap procedure now there is a HeapSimplexRatio param. Removed dirty printf. - - Revision 1.14 2005/04/14 11:34:33 ponchio - *** empty log message *** - - Revision 1.13 2005/01/19 10:33:50 cignoni - Improved ClearHeap management - - Revision 1.12 2004/12/10 01:02:48 cignoni - added an inline and removed loggng - - Revision 1.11 2004/12/03 21:14:39 ponchio - Fixed memory leak... - - Revision 1.10 2004/11/23 10:37:17 cignoni - Added a member with a cached copy of the floating Priority() value inside the HeapElem to optimize operator< in heap updating operator - - Revision 1.9 2004/11/05 10:03:47 fiorin - Added ModifierType::TriEdgeFlipOp - - Revision 1.8 2004/10/25 07:02:56 ganovelli - some inline function, logs on file (precompiler directive) - - Revision 1.7 2004/09/29 17:08:39 ganovelli - changed > to < in heapelem comparison - - Revision 1.6 2004/09/28 09:57:08 cignoni - Better Doxygen docs - - Revision 1.5 2004/09/15 10:40:20 ponchio - typedef LocalOptimization HeapType -> public: - - Revision 1.4 2004/09/08 15:10:59 ganovelli - *** empty log message *** - - Revision 1.3 2004/07/27 09:46:15 cignoni - First working version of the LocalOptimization/Simplification Framework - - Revision 1.1 2004/07/15 12:04:14 ganovelli - minor changes - - Revision 1.2 2004/07/09 10:22:56 ganovelli - working draft - - Revision 1.1 2004/07/08 08:25:15 ganovelli - first draft - -****************************************************************************/ #ifndef __VCGLIB_LOCALOPTIMIZATION #define __VCGLIB_LOCALOPTIMIZATION -#include -#include -#include -#include #include namespace vcg{ From 831639d819f18499a987023b2efd190ba342c660 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 24 Nov 2016 17:13:29 +0100 Subject: [PATCH 64/91] Refactoring and cleaning of the plymc surface reconstruction algorithm --- vcg/complex/algorithms/create/plymc/plymc.h | 74 +++-- .../create/plymc/simplemeshprovider.h | 233 +++++++++++++++ vcg/complex/algorithms/create/plymc/volume.h | 34 +-- vcg/complex/algorithms/create/plymc/voxel.h | 281 +++++++++--------- 4 files changed, 431 insertions(+), 191 deletions(-) create mode 100644 vcg/complex/algorithms/create/plymc/simplemeshprovider.h diff --git a/vcg/complex/algorithms/create/plymc/plymc.h b/vcg/complex/algorithms/create/plymc/plymc.h index ed43bfe7..2f3315d3 100644 --- a/vcg/complex/algorithms/create/plymc/plymc.h +++ b/vcg/complex/algorithms/create/plymc/plymc.h @@ -35,23 +35,13 @@ #include #include -#include -#include - -#include -#include #include -#include -#include -#include -#include #include -#include #include #include #include -#include +//#include #include #include @@ -61,7 +51,6 @@ #include #include -//#include #include #include "volume.h" #include "tri_edge_collapse_mc.h" @@ -73,6 +62,15 @@ template void MCSimplify( MeshType &m, float perc, bool preserveBB=true, vcg::CallBackPos *cb=0); +/** Surface Reconstruction + * + * To allow the managment of a very large set of meshes to be merged, + * it is templated on a MeshProvider class that is able to provide the meshes to be merged. + * IT is the surface reconstrction algorithm that have been used for a long time inside the ISTI-Visual Computer Lab. + * It is mostly a variant of the Curless et al. e.g. a volumetric approach with some original weighting schemes," + * a different expansion rule, and another approach to hole filling through volume dilation/relaxations. + */ + template < class SMesh, class MeshProvider> class PlyMC { @@ -175,6 +173,7 @@ public: MeshProvider MP; Parameter p; Volume VV; + char errorMessage[1024]; /// PLYMC Methods @@ -192,21 +191,36 @@ public: { if(!(loadmask & tri::io::Mask::IOM_VERTNORMAL)) { - printf("Error, pointset MUST have normals"); - return false; + if(m.FN()==0) + { + sprintf(errorMessage,"%sError: mesh has not per vertex normals\n",errorMessage); + return false; + } + else + { + tri::Clean::RemoveUnreferencedVertex(m); + tri::Allocator::CompactEveryVector(m); + tri::UpdateNormal::PerVertexNormalizedPerFaceNormalized(m); + } } + tri::UpdateNormal::NormalizePerVertex(m); + int badNormalCnt=0; for(SVertexIterator vi=m.vert.begin(); vi!=m.vert.end();++vi) if(math::Abs(SquaredNorm((*vi).N())-1.0)>0.0001) { - printf("Error: mesh has not per vertex normalized normals\n"); + badNormalCnt++; + tri::Allocator::DeleteVertex(m,*vi); + } + tri::Allocator::CompactEveryVector(m); + if(badNormalCnt > m.VN()/10) + { + sprintf(errorMessage,"%sError: mesh has null normals\n",errorMessage); return false; } - + if(!(loadmask & tri::io::Mask::IOM_VERTQUALITY)) tri::UpdateQuality::VertexConstant(m,0); tri::UpdateNormal::PerVertexMatrix(m,Tr); - //if(!(loadmask & tri::io::Mask::IOM_VERTCOLOR)) - // saveMask &= ~tri::io::Mask::IOM_VERTCOLOR; } else // processing for triangle meshes { @@ -223,7 +237,6 @@ public: tri::UpdateTopology::VertexFace(m); tri::UpdateFlags::FaceBorderFromVF(m); tri::Geodesic::DistanceFromBorder(m); - // tri::UpdateQuality::VertexGeodesicFromBorder(m); } } @@ -325,8 +338,9 @@ public: return true; } -void Process(vcg::CallBackPos *cb=0) +bool Process(vcg::CallBackPos *cb=0) { + sprintf(errorMessage,""); printf("bbox scanning...\n"); fflush(stdout); Matrix44f Id; Id.SetIdentity(); MP.InitBBox(); @@ -344,7 +358,6 @@ void Process(vcg::CallBackPos *cb=0) voxdim = fullb.max - fullb.min; - int TotAdd=0,TotMC=0,TotSav=0; // if kcell==0 the number of cells is computed starting from required voxel size; __int64 cells; if(p.NCell>0) cells = (__int64)(p.NCell)*(__int64)(1000); @@ -364,6 +377,7 @@ void Process(vcg::CallBackPos *cb=0) } + int TotAdd=0,TotMC=0,TotSav=0; // partial timings counter for(p.IPos[0]=p.IPosS[0];p.IPos[0]<=p.IPosE[0];++p.IPos[0]) for(p.IPos[1]=p.IPosS[1];p.IPos[1]<=p.IPosE[1];++p.IPos[1]) @@ -405,8 +419,8 @@ void Process(vcg::CallBackPos *cb=0) res = InitMesh(*sm,MP.MeshName(i).c_str(),MP.Tr(i)); if(!res) { - printf("Failed Init of mesh %s",MP.MeshName(i).c_str()); - return; + sprintf(errorMessage,"%sFailed Init of mesh %s\n",errorMessage,MP.MeshName(i).c_str()); + return false ; } } res |= AddMeshToVolumeM(*sm, MP.MeshName(i),MP.W(i)); @@ -452,26 +466,20 @@ void Process(vcg::CallBackPos *cb=0) VV.SlicedPPM("final","__",p.SliceNum); VV.SlicedPPMQ("final","__",p.SliceNum); } - //MCMesh me; - // MCMesh me; if(res) { - typedef vcg::tri::TrivialWalker > Walker; + typedef vcg::tri::TrivialWalker > Walker; typedef vcg::tri::MarchingCubes MarchingCubes; - //typedef vcg::tri::ExtendedMarchingCubes ExtendedMarchingCubes; Walker walker; MarchingCubes mc(me, walker); - Box3i currentSubBox=VV.SubPartSafe; - Point3i currentSubBoxRes=VV.ssz; /**********************/ if(cb) cb(50,"Step 2: Marching Cube..."); else printf("Step 2: Marching Cube...\n"); /**********************/ - walker.Init(VV,currentSubBox); + walker.SetExtractionBox(VV.SubPartSafe); walker.BuildMesh(me,VV,mc,0); - // walker.BuildMesh(me,VV,mc,currentSubBox,currentSubBoxRes); typename MCMesh::VertexIterator vi; Box3f bbb; bbb.Import(VV.SubPart); @@ -481,8 +489,7 @@ void Process(vcg::CallBackPos *cb=0) vcg::tri::Allocator< MCMesh >::DeleteVertex(me,*vi); VV.DeInterize((*vi).P()); } - typename MCMesh::FaceIterator fi; - for (fi = me.face.begin(); fi != me.face.end(); ++fi) + for (typename MCMesh::FaceIterator fi = me.face.begin(); fi != me.face.end(); ++fi) { if((*fi).V(0)->IsD() || (*fi).V(1)->IsD() || (*fi).V(2)->IsD() ) vcg::tri::Allocator< MCMesh >::DeleteFace(me,*fi); @@ -526,6 +533,7 @@ void Process(vcg::CallBackPos *cb=0) { printf("----------- skipping SubBlock %2i %2i %2i ----------\n",p.IPos[0],p.IPos[1],p.IPos[2]); } + return true; } diff --git a/vcg/complex/algorithms/create/plymc/simplemeshprovider.h b/vcg/complex/algorithms/create/plymc/simplemeshprovider.h new file mode 100644 index 00000000..1ce3be53 --- /dev/null +++ b/vcg/complex/algorithms/create/plymc/simplemeshprovider.h @@ -0,0 +1,233 @@ +#ifndef SIMPLEMESHPROVIDER_H +#define SIMPLEMESHPROVIDER_H +#include "../../meshlab/alnParser.h" +#include +#include +#include +#include +#include + +/* + * A mesh provider class has the simpler role of passing the set of meshes to be merged to the surface reconstrcution algorithm. + * The only reason for this abstraction is that, plymc can work in a out-of-core way and the loading of the needed range maps can be optimized with a high level caching system. + */ +template +class MinimalMeshProvider +{ +private: + + std::vector< std::string > nameVec; + std::vector< TriMeshType * > meshVec; + std::vector trVec; + std::vector weightVec; // weight tot be applied to each mesh. + vcg::Box3f fullBBox; + +public: + bool Find(const std::string &name, TriMeshType * &sm) + { + for(int i=0;i +class MeshCache +{ + class Pair + { + public: + Pair(){used=0;} + TriMeshType *M; + std::string Name; + int used; // 'data' dell'ultimo accesso. si butta fuori quello lru + }; + + std::list MV; + +public: + void clear(); + + MeshCache() {MeshCacheSize=6;} + ~MeshCache() { + typename std::list::iterator mi; + for(mi=MV.begin();mi!=MV.end();++mi) + delete (*mi).M; + } + + + /** + * @brief Find load a mesh form the cache if it is in or from the disk otherwise + * @param name what mesh to find + * @param sm the pointer loaded mesh + * @return true if the mesh was already in cache + * + */ + bool Find(const std::string &name, TriMeshType * &sm) + { + typename std::list::iterator mi; + typename std::list::iterator oldest; // quello che e' piu' tempo che non viene acceduto. + int last; + + last = std::numeric_limits::max(); + oldest = MV.begin(); + + for(mi=MV.begin();mi!=MV.end();++mi) + { + if((*mi).usedMeshCacheSize) { + sm=(*oldest).M; + (*oldest).used=0; + (*oldest).Name=name; + } else { + MV.push_back(Pair()); + MV.back().Name=name; + MV.back().M=new TriMeshType(); + sm=MV.back().M; + } + return false; + } + + + size_t MeshCacheSize; + size_t size() const {return MV.size();} +}; + +template +class SimpleMeshProvider +{ +private: + std::vector< std::string > meshnames; + std::vector TrV; + std::vector WV; // weight tot be applied to each mesh. + std::vector BBV; // bbox of the transformed meshes.. + vcg::Box3f fullBBox; + MeshCache MC; + +public: + + int size() {return meshnames.size();} + + int getCacheSize() {return MC.MeshCacheSize;} + int setCacheSize(size_t newsize) + { + if(newsize == MC.MeshCacheSize) + return MC.MeshCacheSize; + if(newsize <= 0) + return MC.MeshCacheSize; + + MC.MeshCacheSize = newsize; + return newsize; + } + + bool openALN (const char* alnName) + { + vector rmaps; + ALNParser::ParseALN(rmaps, alnName); + + for(size_t i=0; i::FileExtension(meshnames[i],"PLY") || tri::io::Importer::FileExtension(meshnames[i],"ply")) + { + ret=ply::ScanBBox(meshnames[i].c_str(),BBV[i],TrV[i],true,0); + } + else + { + printf("Trying to import a non-ply file %s\n",meshnames[i].c_str());fflush(stdout); + TriMeshType m; + ret = (tri::io::Importer::Open(m,meshnames[i].c_str()) == tri::io::Importer::E_NOERROR); + tri::UpdatePosition::Matrix(m,TrV[i]); + tri::UpdateBounding::Box(m); + BBV[i].Import(m.bbox); + } + if( ! ret) + { + printf("\n\nwarning:\n file '%s' not found\n",meshnames[i].c_str());fflush(stdout); + continue; + } + fullBBox.Add(BBV[i]); + } + return true; + } + +}; + +class SVertex; +class SFace; +class SUsedTypes: public vcg::UsedTypes < vcg::Use::AsVertexType, + vcg::Use::AsFaceType >{}; + +class SVertex : public Vertex< SUsedTypes, vertex::Coord3f, vertex::Normal3f,vertex::VFAdj, vertex::BitFlags, vertex::Color4b, vertex::Qualityf>{}; +class SFace : public Face< SUsedTypes, face::VertexRef, face::Normal3f,face::Qualityf, face::VFAdj, face::BitFlags> {}; +class SMesh : public tri::TriMesh< std::vector< SVertex>, std::vector< SFace > > {}; + +} + +#endif // SIMPLEMESHPROVIDER_H diff --git a/vcg/complex/algorithms/create/plymc/volume.h b/vcg/complex/algorithms/create/plymc/volume.h index d543c32e..0a9ba7fc 100644 --- a/vcg/complex/algorithms/create/plymc/volume.h +++ b/vcg/complex/algorithms/create/plymc/volume.h @@ -24,26 +24,10 @@ #ifndef __VOLUME_H__ #define __VOLUME_H__ -#ifdef __MINGW32__ -#define _int64 __int64 -#endif - #include "voxel.h" -#include "svoxel.h" -#include #include -//#define BLOCKSIDE() 8 - -// Stato di un voxel - -// B() dice se ci sono dati in uno stadio usabile. -// Cnt() dice quanti ce ne sono stati sommati (per la normalizzazione) - -// b==false cnt==0 totalmente non inzializzato (Zero) -// b==false cnt >0 da normalizzare -// b==true cnt==0 gia' normalizzato -// b==true cnt >0 Errore!!! +namespace vcg { // forward definition template < class VOL > @@ -67,7 +51,7 @@ const char *SFormat( const char * f, ... ) template class Volume { public: - typedef SCALAR_TYPE scalar; + typedef SCALAR_TYPE scalar; typedef Point3 Point3x; typedef Box3 Box3x; @@ -172,7 +156,7 @@ bool Verbose; // se true stampa un sacco di info in piu su logfp; for(size_t i=0;i inside the subblock of voxel (x,y,z). + * return true if the subblock is allocated. + */ bool Pos(const int &_x,const int &_y,const int &_z, int & rpos,int &lpos) const { int x=_x-SubPartSafe.min[0]; int y=_y-SubPartSafe.min[1]; int z=_z-SubPartSafe.min[2]; assert(_x>=SubPartSafe.min[0] && _x=SubPartSafe.min[1] && _y=SubPartSafe.min[2] && _z=SubPartSafe.min[1] && _y=SubPartSafe.min[2] && _z=0 && x=0 && y=0 && z0 da normalizzare +// b==true cnt==0 gia' normalizzato +// b==true cnt >0 Errore!!! + + +/** + * + */ + template class Voxel { - public: - typedef SCALAR_TYPE scalar; +public: + typedef SCALAR_TYPE scalar; - Voxel(SCALAR_TYPE vv, bool bb, Point3 nn, short _cnt) {v=vv;b=bb;n=nn;cnt=_cnt;} - Voxel(SCALAR_TYPE vv, Point3 nn, scalar qq) {v=vv;b=true;n=nn;cnt=0;q=qq;} + Voxel(SCALAR_TYPE vv, bool bb, Point3 nn, short _cnt) {v=vv;b=bb;n=nn;cnt=_cnt;} + Voxel(SCALAR_TYPE vv, Point3 nn, scalar qq) {v=vv;b=true;n=nn;cnt=0;q=qq;} - const scalar &N(const int i) const { return n[i]; } + const Point3 &N() const { return n; } - const Point3 &N() const { return n; } + void SetN(const Point3 &nn) { n=nn; } + const scalar &V() const { return v; } - void SetN(const Point3 &nn) { n=nn; } - const scalar &V() const { return v; } + void SetV(const scalar &vv) { v=vv; } - void SetV(const scalar &vv) { v=vv; } + const scalar &Q() const { return q; } - const scalar &Q() const { return q; } - - void SetQ(const scalar &qq) { q=qq; } + void SetQ(const scalar &qq) { q=qq; } - bool B() const {return b;}; - void SetB(bool val) {b=val;} - int Cnt() const {return cnt;} - void SetCnt(int val) {cnt=val;} - inline void Blend( Voxel const & vx, scalar w) + bool B() const {return b;}; + void SetB(bool val) {b=val;} + int Cnt() const {return cnt;} + void SetCnt(int val) {cnt=val;} + inline void Blend( Voxel const & vx, scalar w) + { + float w1=1.0-w; + v=v*w1+vx.v*w; + q=q*w1+vx.q*w; + n=n*w1+vx.n*w; + //return *this; + } + + inline Voxel & operator += ( Voxel const & vx) + { + assert(!b); + if(cnt==0) { - float w1=1.0-w; - v=v*w1+vx.v*w; - q=q*w1+vx.q*w; - n=n*w1+vx.n*w; - //return *this; + v=vx.v; + q=vx.q; + n=vx.n; + cnt=1; + b=false; } - - inline Voxel & operator += ( Voxel const & vx) + else { - if(cnt==0) - { - assert(!b); - v=vx.v; - q=vx.q; - n=vx.n; - cnt=1; - b=false; - } - else - { - assert(!b); - v+=vx.v; - q+=vx.q; - n+=vx.n; - ++cnt; - } - return *this; + v+=vx.v; + q+=vx.q; + n+=vx.n; + ++cnt; } + return *this; + } - inline bool Normalize(int thr) + inline bool Normalize(int thr) + { + assert(cnt>0); + assert(!B()); + if(cnt0); - assert(!B()); - if(cnt n; +protected: + bool b; + short cnt; + scalar v; + scalar q; + Point3 n; }; @@ -129,67 +144,67 @@ class Voxelfc :public Voxel { public: - Voxelfc(float vv, bool bb, Point3f nn, short _cnt) :Voxel(vv,bb,nn,_cnt){} - Voxelfc(float vv, Point3f nn, scalar qq) :Voxel(vv,nn,qq) {} - Voxelfc(float vv, Point3f nn, scalar qq,Color4b cc) :Voxel(vv,nn,qq) - { - c[0]=cc[0]; - c[1]=cc[1]; - c[2]=cc[2]; - } + Voxelfc(float vv, bool bb, Point3f nn, short _cnt) :Voxel(vv,bb,nn,_cnt){} + Voxelfc(float vv, Point3f nn, scalar qq) :Voxel(vv,nn,qq) {} + Voxelfc(float vv, Point3f nn, scalar qq,Color4b cc) :Voxel(vv,nn,qq) + { + c[0]=cc[0]; + c[1]=cc[1]; + c[2]=cc[2]; + } - inline bool Normalize(int thr) - { - if(cnt>=thr) c/=cnt; - return Voxel::Normalize(thr); - } + inline bool Normalize(int thr) + { + if(cnt>=thr) c/=cnt; + return Voxel::Normalize(thr); + } - static const Voxelfc &Zero() { - static Voxelfc tt(0,false,Point3f(0,0,0),0); - return tt; - } + static const Voxelfc &Zero() { + static Voxelfc tt(0,false,Point3f(0,0,0),0); + return tt; + } - void Merge(const Voxelfc &VOX) - { - c=( c*q + VOX.C()*VOX.Q() )/(q+VOX.Q()); - Voxel::Merge(VOX); - } + void Merge(const Voxelfc &VOX) + { + c=( c*q + VOX.C()*VOX.Q() )/(q+VOX.Q()); + Voxel::Merge(VOX); + } - void Set(const Voxelfc &VOX) - { - Voxel::Set(VOX); - c=VOX.c; - } + void Set(const Voxelfc &VOX) + { + Voxel::Set(VOX); + c=VOX.c; + } - const float &C(const int i) const { return c[i]; } - const Point3f &C() const { return c; } - void SetC(const Point3f &cc) { c=cc; } - Color4b C4b() const - { - static Color4b cc; - cc=Color4b(c[0],c[1],c[2],255); - return cc; - } - inline void Blend( Voxelfc const & vx, scalar w) - { - float w1=1.0-w; - v=v*w1+vx.v*w; - q=q*w1+vx.q*w; - n=n*w1+vx.n*w; - c=c*w1+vx.c*w; - //return *this; - } + const float &C(const int i) const { return c[i]; } + const Point3f &C() const { return c; } + void SetC(const Point3f &cc) { c=cc; } + Color4b C4b() const + { + static Color4b cc; + cc=Color4b(c[0],c[1],c[2],255); + return cc; + } + inline void Blend( Voxelfc const & vx, scalar w) + { + float w1=1.0-w; + v=v*w1+vx.v*w; + q=q*w1+vx.q*w; + n=n*w1+vx.n*w; + c=c*w1+vx.c*w; + //return *this; + } - inline Voxelfc & operator += ( Voxelfc const & vx) - { - Voxel::operator +=(vx); - if(cnt==1) c =vx.c; - else c+=vx.c; - return *this; - } + inline Voxelfc & operator += ( Voxelfc const & vx) + { + Voxel::operator +=(vx); + if(cnt==1) c =vx.c; + else c+=vx.c; + return *this; + } private: - Point3f c; + Point3f c; }; - +} #endif From 095a69753592934fb2964bbdb6b2c8fe34e14074 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Thu, 24 Nov 2016 18:02:07 +0100 Subject: [PATCH 65/91] added a check for empty lines in obj (to avoid out of bound accesses) --- wrap/io_trimesh/import_obj.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wrap/io_trimesh/import_obj.h b/wrap/io_trimesh/import_obj.h index 84c06cba..cdedc588 100644 --- a/wrap/io_trimesh/import_obj.h +++ b/wrap/io_trimesh/import_obj.h @@ -745,8 +745,8 @@ namespace vcg { std::getline(stream, line); // We have to manage backspace terminated lines, // joining them together before parsing them - if(line.back()==13) line.pop_back(); - while(line.back()=='\\') { + if(!line.empty() && line.back()==13) line.pop_back(); + while(!line.empty() && line.back()=='\\') { std::string tmpLine; std::getline(stream, tmpLine); if(tmpLine.back()==13) line.pop_back(); From 77b144b796dd6b85591eb70e6f374f6f1ee26f3c Mon Sep 17 00:00:00 2001 From: Guido Ranzuglia Date: Thu, 24 Nov 2016 18:14:02 +0100 Subject: [PATCH 66/91] - added missing return value --- wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h | 1 + 1 file changed, 1 insertion(+) diff --git a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h index 05bb98d2..d4371596 100644 --- a/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h +++ b/wrap/gl/gl_mesh_attributes_multi_viewer_bo_manager.h @@ -895,6 +895,7 @@ namespace vcg bool isthereaquadview = false; for(typename ViewsMap::const_iterator it = _perviewreqatts.begin();it != _perviewreqatts.end();++it) isthereaquadview = (it->second._intatts[size_t(PR_WIREFRAME_EDGES)][INT_ATT_NAMES::ATT_VERTPOSITION]) || isthereaquadview; + return isthereaquadview; } From e977c746bd9a447eead08a74c6113f250852f86b Mon Sep 17 00:00:00 2001 From: Matteo Dellepiane Date: Tue, 29 Nov 2016 11:37:19 +0100 Subject: [PATCH 67/91] PackInt function made public In order to make the new Ponchio's nexus work properly --- vcg/space/rect_packer.h | 284 ++++++++++++++++++++-------------------- 1 file changed, 142 insertions(+), 142 deletions(-) diff --git a/vcg/space/rect_packer.h b/vcg/space/rect_packer.h index d5033a3a..d56bc144 100644 --- a/vcg/space/rect_packer.h +++ b/vcg/space/rect_packer.h @@ -240,6 +240,148 @@ static bool PackOccupancyMulti(const std::vector & rectVec, /// the se return true; } +/* This is the low level function that packs a set of int rects onto a grid. + +Based on the criptic code written by Claudio Rocchini + +Greedy algorithm. +Sort the rect according their height (larger first) +and then place them in the position that minimize the area of the bbox of all the placed rectangles + +To efficiently skip occupied areas it fills the grid with the id of the already placed rectangles. +*/ +static bool PackInt(const std::vector & sizes, // the sizes of the rect to be packed + const vcg::Point2i & max_size, // the size of the container + std::vector & posiz, // the found positionsof each rect + vcg::Point2i & global_size) // the size of smallest rect covering all the packed rect +{ + int n = (int)(sizes.size()); + assert(n>0 && max_size[0]>0 && max_size[1]>0); + + int gridSize = max_size[0] * max_size[1]; // Size dell griglia + int i, j, x, y; + + posiz.resize(n, Point2i(-1, -1)); + std::vector grid(gridSize, 0); // Creazione griglia + +#define Grid(q,w) (grid[(q)+(w)*max_size[0]]) + + // Build a permutation that keeps the reordiering of the sizes vector according to their width + std::vector perm(n); + for (i = 0; imax_size[0] || sizes[perm[0]][1]>max_size[1]) + return false; + + // Posiziono il primo + j = perm[0]; + global_size = sizes[j]; + posiz[j] = Point2i(0, 0); + + // Fill the grid with the id(+1) of the first + for (y = 0; y= 0 && x= 0 && y= 0 && j0 && sy>0); + + // Calcolo la posizione limite + int lx = std::min(global_size[0], max_size[0] - sx); + int ly = std::min(global_size[1], max_size[1] - sy); + + assert(lx>0 && ly>0); + + int finterior = 0; + + for (y = 0; y <= ly; y++) + { + for (x = 0; x <= lx;) + { + int px; + int c = Grid(x, y + sy - 1); + // Intersection check + if (!c) c = Grid(x + sx - 1, y + sy - 1); + if (!c) + { + for (px = x; px= 0 && carea) + { + bestx = x; + besty = y; + bestsx = nsx; + bestsy = nsy; + bestArea = area; + if (bestsx == global_size[0] && bestsy == global_size[1]) + finterior = 1; + } + break; + } + if (finterior) break; + } + if (finterior) break; + } + + if (bestArea == -1) + { + return false; + } + + posiz[j][0] = bestx; + posiz[j][1] = besty; + global_size[0] = bestsx; + global_size[1] = bestsy; + for (y = posiz[j][1]; y= 0 && x= 0 && y & sizes, // the sizes of the rect to be packed - const vcg::Point2i & max_size, // the size of the container - std::vector & posiz, // the found positionsof each rect - vcg::Point2i & global_size) // the size of smallest rect covering all the packed rect -{ - int n = (int)(sizes.size()); - assert(n>0 && max_size[0]>0 && max_size[1]>0); - - int gridSize = max_size[0]*max_size[1]; // Size dell griglia - int i,j,x,y; - - posiz.resize(n,Point2i(-1,-1)); - std::vector grid(gridSize,0); // Creazione griglia - - #define Grid(q,w) (grid[(q)+(w)*max_size[0]]) - - // Build a permutation that keeps the reordiering of the sizes vector according to their width - std::vector perm(n); - for(i=0;imax_size[0] || sizes[perm[0]][1]>max_size[1] ) - return false; - - // Posiziono il primo - j = perm[0]; - global_size = sizes[j]; - posiz[j] = Point2i(0,0); - - // Fill the grid with the id(+1) of the first - for(y=0;y=0 && x=0 && y=0 && j0 && sy>0); - - // Calcolo la posizione limite - int lx = std::min(global_size[0],max_size[0]-sx); - int ly = std::min(global_size[1],max_size[1]-sy); - - assert(lx>0 && ly>0); - - int finterior = 0; - - for(y=0;y<=ly;y++) - { - for(x=0;x<=lx;) - { - int px; - int c = Grid(x,y+sy-1); - // Intersection check - if(!c) c = Grid(x+sx-1,y+sy-1); - if(!c) - { - for(px=x;px=0 && carea) - { - bestx = x; - besty = y; - bestsx = nsx; - bestsy = nsy; - bestArea = area; - if( bestsx==global_size[0] && bestsy==global_size[1] ) - finterior = 1; - } - break; - } - if(finterior) break; - } - if( finterior ) break; - } - - if(bestArea==-1) - { - return false; - } - - posiz[j][0] = bestx; - posiz[j][1] = besty; - global_size[0] = bestsx; - global_size[1] = bestsy; - for(y=posiz[j][1];y=0 && x=0 && y & sizes, const int ntexture, From 4f34f2d78ef4f91eea880da0241382c7ff890bf0 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Fri, 2 Dec 2016 15:36:33 +0100 Subject: [PATCH 68/91] harmless clang warning format specifies type 'unsigned long' but the argument has type 'size_t' (aka 'unsigned int') --- vcg/complex/algorithms/local_optimization/tri_edge_flip.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcg/complex/algorithms/local_optimization/tri_edge_flip.h b/vcg/complex/algorithms/local_optimization/tri_edge_flip.h index 53d3c5ed..29f26b5f 100644 --- a/vcg/complex/algorithms/local_optimization/tri_edge_flip.h +++ b/vcg/complex/algorithms/local_optimization/tri_edge_flip.h @@ -284,7 +284,7 @@ public: const char* Info(TRIMESH_TYPE &m) { static char dump[60]; - sprintf(dump,"%lu -> %lu %g\n", tri::Index(m,_pos.F()->V(0)), tri::Index(m,_pos.F()->V(1)),-_priority); + sprintf(dump,"%zu -> %zu %g\n", tri::Index(m,_pos.F()->V(0)), tri::Index(m,_pos.F()->V(1)),-_priority); return dump; } From 2a31fb82018d47f251b0ade6e84c70ffa008a62f Mon Sep 17 00:00:00 2001 From: Paolo Cignoni Date: Sun, 4 Dec 2016 12:07:19 +0100 Subject: [PATCH 69/91] added include