diff --git a/Apps/Unsupported/IvViewer/ACGMakefile b/Apps/Unsupported/IvViewer/ACGMakefile new file mode 100644 index 0000000000000000000000000000000000000000..0b7543d8d5191c7f537726e5d939d438340a22bb --- /dev/null +++ b/Apps/Unsupported/IvViewer/ACGMakefile @@ -0,0 +1,37 @@ +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Config +#============================================================================== + + +SUBDIRS := $(call find-subdirs) + +USE_COIN := no +USE_SOQT := no + +ifeq ($(USE_COIN),yes) + USE_SOQT := yes +endif + +ifeq ($(USE_SOQT),yes) + + CXX_DEFS += -DUSE_SOQT=1 + +ifeq ($(USE_COIN),yes) + PACKAGES := coin soqt_coin glut opengl qt +else + PACKAGES := Inventor soqt_inventor glut opengl qt +endif + +else + PACKAGES := inventor opengl x11 +endif + + +PROJ_LIBS = OpenMesh/Core + +MODULES := cxx + + +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Rules +#============================================================================== diff --git a/Apps/Unsupported/IvViewer/SoOpenMeshNodeT.cc b/Apps/Unsupported/IvViewer/SoOpenMeshNodeT.cc new file mode 100644 index 0000000000000000000000000000000000000000..00986e535d704345482a6ed248629874494a811b --- /dev/null +++ b/Apps/Unsupported/IvViewer/SoOpenMeshNodeT.cc @@ -0,0 +1,370 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mo, 19. Mai 2008) $ +// +//============================================================================= + +//============================================================================= +// +// Class SoOpenMeshNodeT - implementation +// +//============================================================================= + + +#define OPENMESH_SOOPENMESHNODE_CC + +//== INCLUDES ================================================================= + +#include +#include +#include +#include +#include +#include +#include + +#include "SoOpenMeshNodeT.hh" +// Attention must be included after SoOpenMeshNodeT.hh +// as it redefines several macros! +#include "SoOpenMeshSupport.hh" + +#include + + +//== NAMESPACES ============================================================== + + +namespace OpenMesh { + + +//== IMPLEMENTATION ========================================================== + + +// Helper functions: draw vertices +inline void glVertex(const OpenMesh::Vec3f& _v) { glVertex3fv(_v); } +inline void glVertex(const OpenMesh::Vec3d& _v) { glVertex3dv(_v); } + +// Helper functions: draw normal +inline void glNormal(const OpenMesh::Vec3f& _n) { glNormal3fv(_n); } +inline void glNormal(const OpenMesh::Vec3d& _n) { glNormal3dv(_n); } + +// Helper function: convert Vec to SbVec3f +template inline SbVec3f sbvec3f(const Vec& _v) { + return SbVec3f(_v[0], _v[1], _v[2]); +} + + +//----------------------------------------------------------------------------- + + +template +void +SoOpenMeshNodeT::initClass() +{ + SO_NODE_INIT_CLASS(SoOpenMeshNodeT, SoShape, "Shape"); +} + + +//----------------------------------------------------------------------------- + + +template +SoOpenMeshNodeT::SoOpenMeshNodeT(const Mesh* _mesh) : + mesh_(_mesh) +{ + SO_NODE_CONSTRUCTOR(SoOpenMeshNodeT); +} + + +//----------------------------------------------------------------------------- + + +template +void +SoOpenMeshNodeT::GLRender(SoGLRenderAction *action) +{ + if (mesh_ && shouldGLRender(action)) + { + SoState* state = action->getState(); + SbBool send_normals = (SoLightModelElement::get(state) != + SoLightModelElement::BASE_COLOR); + + SoMaterialBundle mb(action); + mb.sendFirst(); + + drawFaces(send_normals); + } +} + + +//---------------------------------------------------------------------------- + + +template +void +SoOpenMeshNodeT:: +drawFaces(bool _send_normals, OpenMesh::GenProg::Bool2Type) +{ + typename Mesh::ConstFaceIter f_it(mesh_->faces_begin()), + f_end(mesh_->faces_end()); + + typename Mesh::ConstFaceVertexIter fv_it; + + + if (_send_normals) + { + glBegin(GL_TRIANGLES); + for (; f_it!=f_end; ++f_it) + { + glNormal(mesh_->normal(f_it)); + fv_it = mesh_->cfv_iter(f_it.handle()); + glVertex(mesh_->point(fv_it)); + ++fv_it; + glVertex(mesh_->point(fv_it)); + ++fv_it; + glVertex(mesh_->point(fv_it)); + } + glEnd(); + } + else + { + glBegin(GL_TRIANGLES); + for (; f_it!=f_end; ++f_it) + { + fv_it = mesh_->cfv_iter(f_it.handle()); + glVertex(mesh_->point(fv_it)); + ++fv_it; + glVertex(mesh_->point(fv_it)); + ++fv_it; + glVertex(mesh_->point(fv_it)); + } + glEnd(); + } +} + + +//---------------------------------------------------------------------------- + + +template +void +SoOpenMeshNodeT:: +drawFaces(bool _send_normals, OpenMesh::GenProg::Bool2Type) +{ + typename Mesh::ConstFaceIter f_it(mesh_->faces_begin()), + f_end(mesh_->faces_end()); + + typename Mesh::ConstFaceVertexIter fv_it; + + + if (_send_normals) + { + for (; f_it!=f_end; ++f_it) + { + glBegin(GL_POLYGON); + glNormal(mesh_->normal(f_it)); + for (fv_it=mesh_->cfv_iter(f_it.handle()); fv_it; ++fv_it) + glVertex(mesh_->point(fv_it)); + glEnd(); + } + } + else + { + for (; f_it!=f_end; ++f_it) + { + glBegin(GL_POLYGON); + for (fv_it=mesh_->cfv_iter(f_it.handle()); fv_it; ++fv_it) + glVertex(mesh_->point(fv_it)); + glEnd(); + } + } +} + + +//----------------------------------------------------------------------------- + + +template +void +SoOpenMeshNodeT::generatePrimitives(SoAction* _action) +{ + if (mesh_) + genPrimitives(_action); +} + + +//---------------------------------------------------------------------------- + + +template +void +SoOpenMeshNodeT:: +genPrimitives(SoAction* _action, OpenMesh::GenProg::Bool2Type) +{ + typename Mesh::ConstFaceIter f_it(mesh_->faces_begin()), + f_end(mesh_->faces_end()); + + typename Mesh::ConstFaceVertexIter fv_it; + + + SoPrimitiveVertex pv; + + beginShape(_action, TRIANGLES); + + for (; f_it!=f_end; ++f_it) + { + pv.setNormal(sbvec3f(mesh_->normal(f_it))); + + fv_it = mesh_->cfv_iter(f_it.handle()); + + pv.setPoint(sbvec3f(mesh_->point(fv_it))); + shapeVertex(&pv); + ++fv_it; + + pv.setPoint(sbvec3f(mesh_->point(fv_it))); + shapeVertex(&pv); + ++fv_it; + + pv.setPoint(sbvec3f(mesh_->point(fv_it))); + shapeVertex(&pv); + } + + endShape(); +} + + +//---------------------------------------------------------------------------- + + +template +void +SoOpenMeshNodeT:: +genPrimitives(SoAction* _action, OpenMesh::GenProg::Bool2Type) +{ + typename Mesh::ConstFaceIter f_it(mesh_->faces_begin()), + f_end(mesh_->faces_end()); + + typename Mesh::ConstFaceVertexIter fv_it; + + SoPrimitiveVertex pv; + + + for (; f_it!=f_end; ++f_it) + { + beginShape(_action, POLYGON); + + pv.setNormal(sbvec3f(mesh_->normal(f_it))); + + for (fv_it=mesh_->cfv_iter(f_it.handle()); fv_it; ++fv_it) + { + pv.setPoint(sbvec3f(mesh_->point(fv_it))); + shapeVertex(&pv); + } + + endShape(); + } +} + + +//----------------------------------------------------------------------------- + + +template +void +SoOpenMeshNodeT::computeBBox(SoAction *action, + SbBox3f &box, + SbVec3f ¢er) +{ + if (mesh_ && mesh_->n_vertices()) + { + typename Mesh::ConstVertexIter vIt(mesh_->vertices_begin()); + typename Mesh::ConstVertexIter vEnd(mesh_->vertices_end()); + + typename Mesh::Point min(mesh_->point(vIt)); + typename Mesh::Point max(mesh_->point(vIt)); + + + for (++vIt; vIt != vEnd; ++vIt) + { + max.maximize(mesh_->point(vIt)); + min.minimize(mesh_->point(vIt)); + } + + box.setBounds(SbVec3f(min[0],min[1],min[2]), + SbVec3f(max[0],max[1],max[2])); + } + + else box.setBounds(SbVec3f(0,0,0), SbVec3f(0,0,0)); +} + + +//----------------------------------------------------------------------------- + +#if 0 +/* As we are using templates, we cannot use the predefined macro + SO_NODE_SOURCE to automatically generate the following piece of + code. Ugly, but necessary. +*/ + +template +SoType SoOpenMeshNodeT::classTypeId; + +template +SoFieldData *SoOpenMeshNodeT::fieldData; + +template +const SoFieldData **SoOpenMeshNodeT::parentFieldData; + +template +SbBool SoOpenMeshNodeT::firstInstance = TRUE; + +template +SoType SoOpenMeshNodeT::getTypeId() const { + return classTypeId; +} + +template +const SoFieldData* +SoOpenMeshNodeT::getFieldData() const { + SO__NODE_CHECK_CONSTRUCT("SoOpenMeshNodeT"); + return fieldData; +} + +template +void* SoOpenMeshNodeT::createInstance() { + return (void *)(new SoOpenMeshNodeT); +} + +#else + +SO_NODE_SOURCE(SoOpenMeshNodeT); + +#endif + +//============================================================================= +} // namespace OpenMesh +//============================================================================= diff --git a/Apps/Unsupported/IvViewer/SoOpenMeshNodeT.hh b/Apps/Unsupported/IvViewer/SoOpenMeshNodeT.hh new file mode 100644 index 0000000000000000000000000000000000000000..53940b27675cdba590168f7fa2612c6a7238d7c6 --- /dev/null +++ b/Apps/Unsupported/IvViewer/SoOpenMeshNodeT.hh @@ -0,0 +1,117 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mo, 19. Mai 2008) $ +// +//============================================================================= + +//============================================================================= +// +// Class SoOpenMeshNode +// +// This class defines an basic inventor node to display an OpenMesh +// +//============================================================================= + + +#ifndef OPENMESH_SOOPENMESHNODE_HH +#define OPENMESH_SOOPENMESHNODE_HH + + +//== INCLUDES ================================================================= + + +#include +#include +#include + +//== NAMESPACES =============================================================== + + +namespace OpenMesh { + + +//== CLASS DEFINITION ========================================================= + + +template +class SoOpenMeshNodeT : public SoShape +{ + + SO_NODE_HEADER(SoOpenMeshNodeT); + + +public: + + static void initClass(); + SoOpenMeshNodeT(const Mesh* _mesh=0); + void setMesh(const Mesh* mesh) { d_mesh = mesh; } + + +protected: + + virtual void GLRender(SoGLRenderAction *action); + virtual void computeBBox(SoAction *action, SbBox3f &box, SbVec3f ¢er); + virtual void generatePrimitives(SoAction *action); + + +private: + + virtual ~SoOpenMeshNodeT() {}; + + + // Draw faces as triangles / polygons + void drawFaces(bool _send_normals) { + typedef typename Mesh::Face Face; + drawFaces(_send_normals, typename Face::IsTriangle()); + } + void drawFaces(bool _send_normals, OpenMesh::GenProg::Bool2Type); + void drawFaces(bool _send_normals, OpenMesh::GenProg::Bool2Type); + + + // Generate primitives + void genPrimitives(SoAction* _action) { + typedef typename Mesh::Face Face; + genPrimitives(_action, typename Face::IsTriangle()); + } + void genPrimitives(SoAction* _action, OpenMesh::GenProg::Bool2Type); + void genPrimitives(SoAction* _action, OpenMesh::GenProg::Bool2Type); + + + const Mesh* mesh_; +}; + + +//============================================================================= +} // namespace OpenMesh +//============================================================================= +#if defined(INCLUDE_TEMPLATES) && !defined(OPENMESH_SOOPENMESHNODE_CC) +# define OPENMESH_SOOPENMESHMODE_TEMPLATES +# include "SoOpenMeshNodeT.cc" +#endif +//============================================================================= +#endif // OPENMESH_SOOPENMESHNODE_HH +//============================================================================= diff --git a/Apps/Unsupported/IvViewer/SoOpenMeshSupport.hh b/Apps/Unsupported/IvViewer/SoOpenMeshSupport.hh new file mode 100644 index 0000000000000000000000000000000000000000..3f51d1ec4332ee15130565c82b1ada621f84c154 --- /dev/null +++ b/Apps/Unsupported/IvViewer/SoOpenMeshSupport.hh @@ -0,0 +1,111 @@ +#ifndef SOOPENMESHSUPPORT_H +#define SOOPENMESHSUPPORT_H + +//== REDEFINE DEFINES SO THEY WORK WITH TEMPLATES ============================ + +#define SO_NODE_SOURCE_TEMPLATE template + +// ----------------------------------------------------------------- COIN ---- +// +// define __COIN__ is set by coin headers +#ifdef __COIN__ + +#ifdef PRIVATE_NODE_TYPESYSTEM_SOURCE +# undef PRIVATE_NODE_TYPESYSTEM_SOURCE +#endif + +#define PRIVATE_NODE_TYPESYSTEM_SOURCE(_class_) \ +SO_NODE_SOURCE_TEMPLATE \ +SoType _class_::getClassTypeId(void) { return _class_::classTypeId; } \ +SO_NODE_SOURCE_TEMPLATE \ +SoType _class_::getTypeId(void) const { return _class_::classTypeId; } \ +/* Don't set value explicitly to SoType::badType(), to avoid a bug in */ \ +/* Sun CC v4.0. (Bitpattern 0x0000 equals SoType::badType()). */ \ +SO_NODE_SOURCE_TEMPLATE \ +SoType _class_::classTypeId + +// FIXME: document. 20000103 mortene. +#ifdef SO_NODE_ABSTRACT_SOURCE +# undef SO_NODE_ABSTRACT_SOURCE +#endif + +#define SO_NODE_ABSTRACT_SOURCE(_class_) \ +PRIVATE_NODE_TYPESYSTEM_SOURCE(_class_); \ + \ +SO_NODE_SOURCE_TEMPLATE \ +unsigned int _class_::classinstances = 0; \ +SO_NODE_SOURCE_TEMPLATE \ +const SoFieldData ** _class_::parentFieldData = NULL; \ +SO_NODE_SOURCE_TEMPLATE \ +SoFieldData * _class_::fieldData = NULL; \ + \ +SO_NODE_SOURCE_TEMPLATE \ +const SoFieldData ** \ +_class_::getFieldDataPtr(void) \ +{ \ + return (const SoFieldData **)(&_class_::fieldData); \ +} \ + \ +SO_NODE_SOURCE_TEMPLATE \ +const SoFieldData * \ +_class_::getFieldData(void) const \ +{ \ + return _class_::fieldData; \ +} + + + +// FIXME: document. 20000103 mortene. +#ifdef SO_NODE_SOURCE +# undef SO_NODE_SOURCE +#endif +#define SO_NODE_SOURCE(_class_) \ +SO_NODE_ABSTRACT_SOURCE(_class_); \ + \ +SO_NODE_SOURCE_TEMPLATE \ +void * \ +_class_::createInstance(void) \ +{ \ + return new _class_; \ +} + +// ------------------------------------------------------------------ SGI ---- +#else + +#ifdef SO_NODE_SOURCE +# undef SO_NODE_SOURCE +#endif + +#define SO_NODE_SOURCE(_class_) \ + SO_NODE_SOURCE_TEMPLATE \ + SoType _class_::classTypeId; \ + \ + SO_NODE_SOURCE_TEMPLATE \ + SoFieldData *_class_::fieldData; \ + \ + SO_NODE_SOURCE_TEMPLATE \ + const SoFieldData **_class_::parentFieldData; \ + \ + SO_NODE_SOURCE_TEMPLATE \ + SbBool _class_::firstInstance = TRUE; \ + \ + SO_NODE_SOURCE_TEMPLATE \ + SoType _class_::getTypeId() const { \ + return classTypeId; \ + } \ + \ + SO_NODE_SOURCE_TEMPLATE \ + const SoFieldData* \ + _class_::getFieldData() const { \ + SO__NODE_CHECK_CONSTRUCT("SoOpenMeshNodeT"); \ + return fieldData; \ + } \ + \ + SO_NODE_SOURCE_TEMPLATE \ + void* _class_::createInstance() { \ + return (void *)(new _class_); \ + } \ + +#endif + +#endif diff --git a/Apps/Unsupported/IvViewer/ivviewer.cc b/Apps/Unsupported/IvViewer/ivviewer.cc new file mode 100644 index 0000000000000000000000000000000000000000..d08640c57d9551f8a0d721b48c435069658d7fe8 --- /dev/null +++ b/Apps/Unsupported/IvViewer/ivviewer.cc @@ -0,0 +1,140 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 4483 $ +// $Date: 2009-01-28 11:41:31 +0100 (Mi, 28. Jan 2009) $ +// +//============================================================================= + +// + +#if !defined(USE_SOQT) +# define USE_SOQT 0 +#endif + +//== INCLUDES ================================================================= + + +#include +// +// Attention! must include this before including inventor files! +// There some dependencies not solved yet! +#include +#include +// +#include +#if USE_SOQT +# include +# include +# include +#else +# include +# include +#endif +#include +// +#include + + +//== CLASS DEFINITION ========================================================= + + +struct MyTraits : public OpenMesh::DefaultTraits +{ + VertexAttributes(OpenMesh::Attributes::Normal); + HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge); + FaceAttributes(OpenMesh::Attributes::Normal); +}; + + +typedef OpenMesh::TriMesh_ArrayKernelT MyMesh; +typedef OpenMesh::SoOpenMeshNodeT MyNode; + + + +//== IMPLEMENTATION =========================================================== + + + +int main(int argc, char **argv) +{ + OpenMesh::IO::Options opt; + +#if USE_SOQT + QApplication app(argc,argv); + + SoQt::init( argv[0] ); + + MyNode::initClass(); + SoQtExaminerViewer *myViewer = new SoQtExaminerViewer(); + + + // Read a mesh + MyMesh mesh; + if (argc > 1 && OpenMesh::IO::read_mesh(mesh, argv[1], opt)) + { + if (!opt.check( OpenMesh::IO::Options::FaceNormal)) + mesh.update_face_normals(); + + SoSeparator* root = new SoSeparator(); + root->addChild(new MyNode(&mesh)); + + myViewer->setSceneGraph(root); + } + + QObject::connect(qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit())); + + myViewer->show(); + SoQt::mainLoop(); +#else + // Inventor stuff + Widget myWindow = SoXt::init(argv[0]); + MyNode::initClass(); + SoXtExaminerViewer *myViewer = + new SoXtExaminerViewer(myWindow); + + + + // Read a mesh + MyMesh mesh; + if (argc > 1 && OpenMesh::IO::read_mesh(mesh, argv[1], opt)) + { + if (!opt.check( OpenMesh::IO::Options::FaceNormal)) + mesh.update_face_normals(); + + SoSeparator* root = new SoSeparator(); + root->addChild(new MyNode(&mesh)); + + myViewer->setSceneGraph(root); + } + + myViewer->show(); + SoXt::show(myWindow); + SoXt::mainLoop(); +#endif +} + + +//============================================================================= diff --git a/Apps/Unsupported/OsgViewer/ACGMakefile b/Apps/Unsupported/OsgViewer/ACGMakefile new file mode 100644 index 0000000000000000000000000000000000000000..8c47783ae1439ddeae9c810b38e2513a09901b2d --- /dev/null +++ b/Apps/Unsupported/OsgViewer/ACGMakefile @@ -0,0 +1,21 @@ +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Config +#============================================================================== + +#CXX_SRC_EXT := .cc +#CXX_HDR_EXT := .h + +CXX_CFLAGS += -DOM_USE_OSG=1 + +SUBDIRS = + +PACKAGES := osg qt glut opengl x11 math + +PROJ_LIBS = OpenMesh/Apps/QtViewer OpenMesh/Tools OpenMesh/Core + +MODULES := moc cxx + + +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Rules +#============================================================================== diff --git a/Apps/Unsupported/OsgViewer/README b/Apps/Unsupported/OsgViewer/README new file mode 100644 index 0000000000000000000000000000000000000000..34dfe021a37a8f4b8e7e52f8bf8ece3b7b55f660 --- /dev/null +++ b/Apps/Unsupported/OsgViewer/README @@ -0,0 +1,11 @@ +Usage: + + 1. osgviewer + + Load a model via I/O routines of OpenMesh and save as a OpenSG + binary file in file opensg.bin. + + 2. osgviewer + + Load model previously stored in opensg.bin via OpenSG BINLoader. + diff --git a/Apps/Unsupported/OsgViewer/meshviewer.cc b/Apps/Unsupported/OsgViewer/meshviewer.cc new file mode 100644 index 0000000000000000000000000000000000000000..0f60038f513d7a1cbc573b0d7c3335dfdd11cc7f --- /dev/null +++ b/Apps/Unsupported/OsgViewer/meshviewer.cc @@ -0,0 +1,134 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mo, 19. Mai 2008) $ +// +//============================================================================= +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311) +#endif + +#include +#include +#include +#include +#include +#include +#include + + +struct MyTraits : public OpenMesh::Kernel_OSG::Traits +{ + VertexAttributes(OpenMesh::Attributes::Normal | + OpenMesh::Attributes::TexCoord ); + HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge); + FaceAttributes(OpenMesh::Attributes::Normal); +}; + + +typedef OpenMesh::Kernel_OSG::TriMesh_OSGArrayKernelT MyMesh; +typedef MeshViewerWidgetT MeshViewerWidget; + +void usage_and_exit(int xcode); + +int main(int argc, char **argv) +{ + osg::osgInit(argc, argv); + + // OpenGL check + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication app(argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + QString msg = "System has no OpenGL support!"; + QMessageBox::critical( NULL, "OpenGL", msg + argv[1], 0 ); + return -1; + } + + + int c; + OpenMesh::IO::Options opt; + + while ( (c=getopt(argc,argv,"s"))!=-1 ) + { + switch(c) + { + case 's': opt += OpenMesh::IO::Options::Swap; break; + case 'h': + usage_and_exit(0); + default: + usage_and_exit(1); + } + } + // create widget + MeshViewerWidget* w = new MeshViewerWidget(0, "Viewer"); + app.setMainWidget(w); + + // static mesh, hence use strips + w->enable_strips(); + + w->resize(400, 400); + w->show(); + + // load scene + if ( optind < argc ) + { + if ( ! w->open_mesh(argv[optind], opt) ) + { + QString msg = "Cannot read mesh from file:\n '"; + msg += argv[optind]; + msg += "'"; + QMessageBox::critical( NULL, w->caption(), msg, 0 ); + return 1; + } + } + + if ( ++optind < argc ) + { + if ( ! w->open_texture( argv[optind] ) ) + { + QString msg = "Cannot load texture image from file:\n '"; + msg += argv[optind]; + msg += "'\n\nPossible reasons:\n"; + msg += "- Mesh file didn't provide texture coordinates\n"; + msg += "- Texture file does not exist\n"; + msg += "- Texture file is not accessible.\n"; + QMessageBox::warning( NULL, w->caption(), msg, 0 ); + } + } + + return app.exec(); +} + +void usage_and_exit(int xcode) +{ + std::cout << "Usage: meshviewer [-s] [mesh] [texture]\n" << std::endl; + std::cout << "Options:\n" + << " -s\n" + << " Reverse byte order, when reading binary files.\n" + << std::endl; + exit(xcode); +} diff --git a/Apps/Unsupported/OsgViewer/osgviewer.cc b/Apps/Unsupported/OsgViewer/osgviewer.cc new file mode 100644 index 0000000000000000000000000000000000000000..d4dfafcba35d7cf944cd8c8dc690e5dab9479700 --- /dev/null +++ b/Apps/Unsupported/OsgViewer/osgviewer.cc @@ -0,0 +1,481 @@ +// -------------------- STL +#include +#include +#include +#include +// -------------------- OpenSG +#include +#include +#include +#include +#include +#include +#include +// -------------------- OpenMesh +#include // always before kernel type + +#include +#include + +#include +#include + +// -------------------- +#include + + +// ----------------------------------------------------------- namespace ----- + +OSG_USING_NAMESPACE + + +// ------------------------------------------------------------- OpenMesh ---- + +struct MeshTraits : public OpenMesh::Kernel_OSG::Traits +{ + HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge); + VertexAttributes ( OpenMesh::Attributes::Normal | + OpenMesh::Attributes::Color ); + FaceAttributes ( OpenMesh::Attributes::Normal ); +}; + +typedef OpenMesh::Kernel_OSG::TriMesh_OSGArrayKernelT mesh_t; +typedef OpenMesh::Subdivider::Uniform::LoopT< mesh_t > loop_t; +typedef OpenMesh::Smoother::JacobiLaplaceSmootherT< mesh_t > smoother_t; + +// --------------------------------------------------------------- globals ---- + +class MeshContainer +{ +public: + + typedef std::vector meshbag_t; + + const size_t InvalidIndex; + +public: + + MeshContainer() : InvalidIndex(size_t(-1)) + { } + + ~MeshContainer() + { + meshbag_t::iterator it = meshes_.begin(); + for(;it != meshes_.end(); ++it) + delete *it; + } + + size_t size() const { return meshes_.size(); } + + mesh_t& operator [] ( size_t idx ) + { + if (idx < meshes_.size()) + return *(meshes_[idx]); + throw std::range_error("Invalid index"); + } + + const mesh_t& operator [] ( size_t idx ) const + { + if (idx < meshes_.size()) + return *(meshes_[idx]); + throw std::range_error("Invalid index"); + } + + bool bind( osg::GeometryPtr geo ) + { + std::auto_ptr obj(new mesh_t); + + return (OpenMesh::Kernel_OSG::bind< mesh_t >( *obj, geo)) + ? (meshes_.push_back(obj.release()), true) + : false; + } + + + +private: + + meshbag_t meshes_; + +private: // non-copyable + + MeshContainer( const MeshContainer& ); + MeshContainer& operator = ( const MeshContainer& ); +}; + + +struct Globals +{ + // OpenSG specific entities + SimpleSceneManager* mgr; + GLUTWindowPtr gwin; + NodePtr root; + std::vector geos; + size_t sel; + bool statistics; + + // OpenMesh specific entities + MeshContainer meshes; + +} g; + + +// -------------------------------------------------------------- forwards ---- + +void display(void); +void reshape(int width, int height); +void mouse(int button, int state, int x, int y); +void keyboard(unsigned char key, int x, int y); +void motion(int x, int y); + + +// ---------------------------------------------------------------- helper ---- + +// setup the GLUT library which handles the windows for us +int setupGLUT(int *argc, char *argv[]) +{ + glutInit(argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); + + int winid = glutCreateWindow("OpenMesh within OpenSG"); + + glutReshapeFunc(reshape); + glutDisplayFunc(display); + glutMouseFunc(mouse); + glutMotionFunc(motion); + glutKeyboardFunc(keyboard); + + return winid; +} + + +// -------------------------------------------------- locate geometry node ---- +/* + This function uses the fact that ::dcast() acts like dynamic_cast. It tries + to dcast the core to a GeometryPtr, and tests the result to see if it + actually was derived from Geometry. +*/ + +Action::ResultE bindGeo(NodePtr& node) +{ + GeometryPtr geo = GeometryPtr::dcast(node->getCore()); + + if (geo!=NullFC) + { + if ( g.meshes.bind( geo ) ) + { + std::cout << " Geometry connected to OpenMesh object\n"; + g.geos.push_back(geo); + g.sel = g.meshes.size()-1; + assert( g.geos.size() == g.meshes.size() ); + } + else + std::cerr << " Warning! Could not bind the OpenMesh" + << " object to the geometry!\n"; + } + return Action::Continue; +} + +// ------------------------------------------------------------------ main ---- + + +int main(int argc, char **argv) +{ + // OSG init + osgInit(argc,argv); + + int winid = setupGLUT(&argc, argv); + + // the connection between GLUT and OpenSG + g.gwin = GLUTWindow::create(); + g.gwin->setId(winid); + g.gwin->init(); + + // -------------------- create root node with core + std::cout << "Create root node with core\n"; + + g.root = Node::create(); + NodeCorePtr core = Group::create(); + + osg::beginEditCP(g.root); + { + g.root->setCore(core); + } + osg::endEditCP(g.root); + + // -------------------- load the scene + std::cout << "Load a scene from '" << argv[1] << "'\n"; + + NodePtr node = SceneFileHandler::the().read( argv[1] ); + + if ( node != NullFC ) + { + osg::beginEditCP(g.root); + { + g.root->addChild(node); + } + osg::endEditCP(g.root); + } + else + return 1; + + // -------------------- bind all geometry nodes to an OpenMesh + std::cout << "Bind all geometry nodes\n"; + + traverse(g.root, + osgTypedFunctionFunctor1CPtrRef(bindGeo)); + + if (!g.meshes.size()) + { + std::cerr << " No geometry found. Nothing to do!\n"; + return 1; + } + else + std::cout << " Number of bound geometry: " << g.meshes.size() << std::endl; + + // -------------------- create the SimpleSceneManager helper + std::cout << "Create simple scene manager\n"; + + g.mgr = new SimpleSceneManager; + + // tell the manager what to manage + g.mgr->setWindow(g.gwin); + g.mgr->setRoot (g.root); + + // + g.mgr->useOpenSGLogo(); + g.mgr->setStatistics(false); + + // -------------------- show the whole scene + std::cout << "Display everything\n"; + + g.mgr->showAll(); + + glutMainLoop(); + return 0; +} + +// --------------------------------------------------------------- display ---- + +void display(void) +{ + g.mgr->redraw(); +} + +// --------------------------------------------------------------- reshape ---- + +void reshape(int w, int h) +{ + g.mgr->resize(w, h); + glutPostRedisplay(); +} + +// ----------------------------------------------------------------- mouse ---- + +void mouse(int button, int state, int x, int y) +{ + if (state) + { + g.mgr->mouseButtonRelease(button, x, y); +// if ( g.mode & FLYMODE ) +// glutIdleFunc(NULL); + } + else + { + g.mgr->mouseButtonPress(button, x, y); +// if ( g.mode & FLYMODE ) +// glutIdleFunc(idle); + } + glutPostRedisplay(); +} + +// -------------------------------------------------------------- keyboard ---- + +void keyboard(unsigned char key, int x, int y) +{ +#define MESH g.meshes[g.sel] +#define GEO g.geos[g.sel] +#define YN(b) (b?"yes":"no") + OpenMesh::Utils::Timer t; + + using namespace std; + + switch(key) + { + case 27: // escape + exit(0); + break; + + case 'i': + { + cout << "OpenMesh information for obj #" << g.sel << ":\n"; + cout << " #Vertices: " << MESH.n_vertices() << endl; + cout << " #Faces: " << MESH.n_faces() << endl; + cout << " #Edges: " << MESH.n_edges() << endl; + cout << " v. normal: " << YN(MESH.has_vertex_normals()) << endl; + cout << " v. color: " << YN(MESH.has_vertex_colors()) << endl; + cout << "v. texcoord: " << YN(MESH.has_vertex_texcoords()) << endl; + cout << " f. normal: " << YN(MESH.has_face_normals()) << endl; + cout << " f. color: " << YN(MESH.has_face_colors()) << endl; + break; + } + case 'I': + cout << "Geometry information for obj #" << g.sel << ":\n"; + cout << " #Types: " << GEO->getTypes()->size() << endl; + cout << " #Lengths: " << GEO->getLengths()->size() << endl; + cout << " #Indices: " << GEO->getIndices()->size() << endl; + cout << "#Positions: " << GEO->getPositions()->size() << endl; + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if ((size_t(key)-size_t('0')) < g.meshes.size()) + { + g.sel = (size_t(key)-size_t('0')); + cout << "Selected geometry #" << g.sel << endl; + } + break; + + case '+': + g.sel = ++g.sel % g.meshes.size(); + cout << "Selected geometry #" << g.sel << endl; + break; + + case '-': + g.sel = (g.sel + g.meshes.size()-1) % g.meshes.size(); + cout << "Selected geometry #" << g.sel << endl; + break; + + case 'S': + g.mgr->setStatistics( g.statistics=!g.statistics ); + g.statistics + ? cout << "Statistics enabled.\n" + : cout << "Statistics disabled.\n"; + glutPostRedisplay(); + break; + + case 'w': + { + OpenMesh::IO::Options opt; + + if (MESH.has_vertex_colors()) + opt += OpenMesh::IO::Options::VertexColor; + if (MESH.has_face_colors()) + opt += OpenMesh::IO::Options::FaceColor; + if (MESH.has_vertex_normals()) + opt += OpenMesh::IO::Options::VertexNormal; + + std::string ofname; + { + std::stringstream ostr; + ostr << "object-" << g.sel << ".om"; + ofname = ostr.str(); + } + + cout << "Writing OpenMesh of geometry #" << g.sel + << " to " << ofname << std::endl; + t.start(); + bool rc = OpenMesh::IO::write_mesh( MESH, ofname, opt); + t.stop(); + rc + ? cout << " Done (" << t.as_string() << ")\n" + : cout << " Failed to store OpenMesh\n"; + + break; + } + + case 's': + { + cout << "Appyling two smoothing steps on selected geometry.."; + t.start(); + smoother_t smoother( g.meshes[g.sel] ); + smoother.initialize( smoother_t::Tangential, smoother_t::C1 ); + beginEditCP(g.geos[g.sel]); + smoother.smooth(2); + endEditCP(g.geos[g.sel]); + t.stop(); + cout << "done. " << t.as_string() << endl; + glutPostRedisplay(); + break; + } + + case 't': + { + cout << "Applying two smoothing steps on all bound geometry.."; + t.start(); + for(size_t i = 0; i < g.meshes.size(); ++i) + { + smoother_t smoother( g.meshes[i] ); + smoother.initialize( smoother_t::Tangential, smoother_t::C1 ); + beginEditCP(g.geos[i]); + smoother.smooth(2); + endEditCP(g.geos[i]); + } + t.stop(); + cout << "done. " << t.as_string() << endl; + glutPostRedisplay(); + break; + } + + case 'c': + { + OpenMesh::IO::Options opt; + + if (MESH.has_vertex_colors()) + opt += OpenMesh::IO::Options::VertexColor; + if (MESH.has_face_colors()) + opt += OpenMesh::IO::Options::FaceColor; + if (MESH.has_vertex_normals()) + opt += OpenMesh::IO::Options::VertexNormal; + + mesh_t m(MESH); + + std::string ofname; + { + std::stringstream ostr; + ostr << "copy-" << g.sel << ".om"; + ofname = ostr.str(); + } + + cout << "Writing copy of geometry #" << g.sel + << " to " << ofname << std::endl; + t.start(); + bool rc = OpenMesh::IO::write_mesh( MESH, ofname, opt); + t.stop(); + rc + ? cout << " Done (" << t.as_string() << ")\n" + : cout << " Failed to store OpenMesh\n"; + + OpenMesh::IO::write_mesh( m, ofname ); + + break; + } + + case 'u': + { + cout << "Applying one step of loop subdivision.."; + t.start(); + loop_t loop; + beginEditCP( GEO ); + loop( MESH, 1 ); + MESH.update_normals(); + endEditCP( GEO ); + t.stop(); + cout << "done. " << t.as_string() << endl; + glutPostRedisplay(); + break; + } + + default: + cout << "key [0x" << setw(4) << hex << key << dec << "]\n"; + } +#undef YN +#undef MESH +} + +//----------------------------------------------------------------- motion ---- + +void motion(int x, int y) +{ + g.mgr->mouseMove(x, y); + glutPostRedisplay(); +} diff --git a/Apps/Unsupported/ProgViewer/ACGMakefile b/Apps/Unsupported/ProgViewer/ACGMakefile new file mode 100644 index 0000000000000000000000000000000000000000..dd5b34d08b158d9cd99f65d308471e2aaed8e71f --- /dev/null +++ b/Apps/Unsupported/ProgViewer/ACGMakefile @@ -0,0 +1,18 @@ +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Config +#============================================================================== + +CXX_CFLAGS += -DQT_THREAD_SUPPORT + +SUBDIRS = $(call find-subdirs) + +PACKAGES := qt4 glut opengl x11 math + +PROJ_LIBS = OpenMesh/Apps/QtViewer OpenMesh/Tools OpenMesh/Core + +MODULES := moc4 cxx + + +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Rules +#============================================================================== diff --git a/Apps/Unsupported/ProgViewer/OpenMesh_Apps_ProgViewer.vcproj b/Apps/Unsupported/ProgViewer/OpenMesh_Apps_ProgViewer.vcproj new file mode 100644 index 0000000000000000000000000000000000000000..0ae89add9c43d2fc85f71a4f9a5c42006a9b1255 --- /dev/null +++ b/Apps/Unsupported/ProgViewer/OpenMesh_Apps_ProgViewer.vcproj @@ -0,0 +1,274 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Apps/Unsupported/ProgViewer/ProgViewerWidget.cc b/Apps/Unsupported/ProgViewer/ProgViewerWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..f4b8b6cff5dcf12da5e853b4d09e2fcc363b0dce --- /dev/null +++ b/Apps/Unsupported/ProgViewer/ProgViewerWidget.cc @@ -0,0 +1,321 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mo, 19. Mai 2008) $ +// +//============================================================================= + + +//== INCLUDES ================================================================= + +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311) +#endif + +#include +#include +// -------------------- +#include +#include +#include +// -------------------- +#include +#include +#include +#include +#include +// -------------------- +#ifdef ARCH_DARWIN +# include +#else +# include +#endif + +using namespace Qt; +//== IMPLEMENTATION ========================================================== + + +void +ProgViewerWidget::open_prog_mesh(const char* _filename) +{ + MyMesh::Point p; + unsigned int i, i0, i1, i2; + unsigned int v1, vl, vr; + char c[10]; + + std::ifstream ifs(_filename, std::ios::binary); + if (!ifs) + { + std::cerr << "read error\n"; + exit(1); + } + + // + bool swap = OpenMesh::Endian::local() != OpenMesh::Endian::LSB; + + // read header + ifs.read(c, 8); c[8] = '\0'; + if (std::string(c) != std::string("ProgMesh")) + { + std::cerr << "Wrong file format.\n"; + exit(1); + } + OpenMesh::IO::binary::restore( ifs, n_base_vertices_, swap ); + OpenMesh::IO::binary::restore( ifs, n_base_faces_, swap ); + OpenMesh::IO::binary::restore( ifs, n_detail_vertices_, swap ); + + n_max_vertices_ = n_base_vertices_ + n_detail_vertices_; + + // load base mesh + mesh_.clear(); + + for (i=0; i::restore( ifs, p, swap ); + mesh_.add_vertex(p); + } + + for (i=0; i::restore( ifs, i0, swap); + OpenMesh::IO::binary::restore( ifs, i1, swap); + OpenMesh::IO::binary::restore( ifs, i2, swap); + mesh_.add_face(mesh_.vertex_handle(i0), + mesh_.vertex_handle(i1), + mesh_.vertex_handle(i2)); + } + + + // load progressive detail + for (i=0; i::restore( ifs, p, swap ); + OpenMesh::IO::binary::restore( ifs, v1, swap ); + OpenMesh::IO::binary::restore( ifs, vl, swap ); + OpenMesh::IO::binary::restore( ifs, vr, swap ); + + PMInfo pminfo; + pminfo.p0 = p; + pminfo.v1 = MyMesh::VertexHandle(v1); + pminfo.vl = MyMesh::VertexHandle(vl); + pminfo.vr = MyMesh::VertexHandle(vr); + pminfos_.push_back(pminfo); + } + pmiter_ = pminfos_.begin(); + + + // update face and vertex normals + mesh_.update_face_normals(); + mesh_.update_vertex_normals(); + + // bounding box + MyMesh::ConstVertexIter + vIt(mesh_.vertices_begin()), + vEnd(mesh_.vertices_end()); + + MyMesh::Point bbMin, bbMax; + + bbMin = bbMax = mesh_.point(vIt); + for (; vIt!=vEnd; ++vIt) + { + bbMin.minimize(mesh_.point(vIt)); + bbMax.maximize(mesh_.point(vIt)); + } + + // set center and radius + set_scene_pos(0.5f*(bbMin + bbMax), 0.5*(bbMin - bbMax).norm()); + + // info + std::cerr << mesh_.n_vertices() << " vertices, " + << mesh_.n_edges() << " edge, " + << mesh_.n_faces() << " faces, " + << n_detail_vertices_ << " detail vertices\n"; + + setWindowTitle( QFileInfo(_filename).fileName() ); +} + + +//----------------------------------------------------------------------------- + + +void ProgViewerWidget::refine(unsigned int _n) +{ + size_t n_vertices = mesh_.n_vertices(); + + while (n_vertices < _n && pmiter_ != pminfos_.end()) + { + pmiter_->v0 = mesh_.add_vertex(pmiter_->p0); + mesh_.vertex_split(pmiter_->v0, + pmiter_->v1, + pmiter_->vl, + pmiter_->vr); + ++pmiter_; + ++n_vertices; + } + + mesh_.update_face_normals(); + mesh_.update_vertex_normals(); + + std::cerr << n_vertices << " vertices\n"; +} + + +//----------------------------------------------------------------------------- + + +void ProgViewerWidget::coarsen(unsigned int _n) +{ + size_t n_vertices = mesh_.n_vertices(); + + while (n_vertices > _n && pmiter_ != pminfos_.begin()) + { + --pmiter_; + + MyMesh::HalfedgeHandle hh = + mesh_.find_halfedge(pmiter_->v0, pmiter_->v1); + + mesh_.collapse(hh); + + --n_vertices; + } + + mesh_.garbage_collection(); + mesh_.update_face_normals(); + mesh_.update_vertex_normals(); + + std::cerr << n_vertices << " vertices\n"; +} + + +//----------------------------------------------------------------------------- + +void ProgViewerWidget::keyPressEvent(QKeyEvent* _event) +{ + switch (_event->key()) + { + case Key_Minus: + if ( _event->modifiers() & ShiftModifier) + coarsen(mesh_.n_vertices()-1); + else + coarsen((unsigned int)(0.9*mesh_.n_vertices())); + updateGL(); + break; + + case Key_Plus: + if (_event->modifiers() & ShiftModifier) + refine(mesh_.n_vertices()+1); + else + refine((unsigned int)(std::max( 1.1*mesh_.n_vertices(), + mesh_.n_vertices()+1.0) )); + updateGL(); + break; + + case Key_Home: + coarsen(n_base_vertices_); + updateGL(); + break; + + case Key_A: + if (timer_->isActive()) + { + timer_->stop(); + std::cout << "animation stopped!" << std::endl; + } + else + { + timer_->setSingleShot(true); + timer_->start(0); + std::cout << "animation started!" << std::endl; + } + break; + + case Key_End: + refine(n_base_vertices_ + n_detail_vertices_); + updateGL(); + break; + + case Key_P: + { + const size_t refine_max = 100000; + const size_t n_loop = 5; + + OpenMesh::Utils::Timer t; + size_t count; + + coarsen(0); count = mesh_.n_vertices(); + refine(refine_max); count = mesh_.n_vertices() - count; + + t.start(); + for (size_t i=0; iBase::keyPressEvent(_event); + } +} + +void ProgViewerWidget::animate( void ) +{ + if (animateRefinement_) + { + refine((unsigned int)( 1.1*(mesh_.n_vertices()+1) )); + if ( mesh_.n_vertices() > n_base_vertices_+(0.5*n_detail_vertices_)) + animateRefinement_ = false; + } + else + { + coarsen((unsigned int)(0.9*(mesh_.n_vertices()-1))); + if ( mesh_.n_vertices() == n_base_vertices_ ) + animateRefinement_ = true; + } + updateGL(); + timer_->setSingleShot(true); + timer_->start(300); +} + +//============================================================================= diff --git a/Apps/Unsupported/ProgViewer/ProgViewerWidget.hh b/Apps/Unsupported/ProgViewer/ProgViewerWidget.hh new file mode 100644 index 0000000000000000000000000000000000000000..8f451d4f876b7f8a5567957c9d2be47a9fd9be2d --- /dev/null +++ b/Apps/Unsupported/ProgViewer/ProgViewerWidget.hh @@ -0,0 +1,137 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mo, 19. Mai 2008) $ +// +//============================================================================= + + +#ifndef OPENMESHAPPS_PROGVIEWERWIDGET_HH +#define OPENMESHAPPS_PROGVIEWERWIDGET_HH + + +//== INCLUDES ================================================================= + +#include +#include +#include +#include +#include + + + +//== CLASS DEFINITION ========================================================= + + +using namespace OpenMesh; +using namespace OpenMesh::Attributes; + + +struct MyTraits : public OpenMesh::DefaultTraits +{ + VertexAttributes ( OpenMesh::Attributes::Normal | + OpenMesh::Attributes::Status ); + EdgeAttributes ( OpenMesh::Attributes::Status ); + HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge ); + FaceAttributes ( OpenMesh::Attributes::Normal | + OpenMesh::Attributes::Status ); +}; + + +typedef OpenMesh::TriMesh_ArrayKernelT MyMesh; +typedef MeshViewerWidgetT MeshViewerWidget; + + +//== CLASS DEFINITION ========================================================= + + + +class ProgViewerWidget : public MeshViewerWidget +{ + Q_OBJECT + +public: + + typedef MeshViewerWidget Base; + typedef ProgViewerWidget This; + + +public: + /// default constructor + ProgViewerWidget(QWidget* _parent=0) + : MeshViewerWidget(_parent) + { + timer_ = new QTimer(this); + + connect( timer_, SIGNAL(timeout()), SLOT(animate()) ); + } + + /// destructor + ~ProgViewerWidget() + { + delete timer_; + } + + /// open progressive mesh + void open_prog_mesh(const char* _filename); + +protected slots: + +void animate( void ); + +private: + + QTimer *timer_; + + struct PMInfo + { + MyMesh::Point p0; + MyMesh::VertexHandle v0, v1, vl, vr; + }; + typedef std::vector PMInfoContainer; + typedef PMInfoContainer::iterator PMInfoIter; + + /// refine mesh up to _n vertices + void refine(unsigned int _n); + + /// coarsen mesh down to _n vertices + void coarsen(unsigned int _n); + + virtual void keyPressEvent(QKeyEvent* _event); + + // mesh data + bool animateRefinement_; + PMInfoContainer pminfos_; + PMInfoIter pmiter_; + size_t n_base_vertices_, n_base_faces_, n_detail_vertices_; + size_t n_max_vertices_; +}; + + +//============================================================================= +#endif // OPENMESHAPPS_PROGVIEWERWIDGET_HH defined +//============================================================================= + diff --git a/Apps/Unsupported/ProgViewer/progviewer.cc b/Apps/Unsupported/ProgViewer/progviewer.cc new file mode 100644 index 0000000000000000000000000000000000000000..d19f61e1748d32a6bb0083adfbe2ab7d660b431c --- /dev/null +++ b/Apps/Unsupported/ProgViewer/progviewer.cc @@ -0,0 +1,78 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 2096 $ +// $Date: 2008-06-26 13:16:48 +0200 (Do, 26. Jun 2008) $ +// +//============================================================================= + +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311) +#endif + +#include +#include + +#include +#include +#include +#include + +#include + +int main(int argc, char **argv) +{ + // OpenGL check + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication app(argc,argv); + + glutInit(&argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + std::cerr << "This system has no OpenGL support.\n"; + return -1; + } + + + // create widget + ProgViewerWidget w(0); + w.resize(400, 400); + w.show(); + + // load scene + if (argc > 1) w.open_prog_mesh(argv[1]); + + + // print usage info + std::cout << "\n\n" + << "Press Minus : Coarsen mesh\n" + << " Plus : Refine mesh\n" + << " Home : Coarsen down to base mesh\n" + << " End : Refine up to finest mesh\n" + << "\n"; + + + return app.exec(); +} diff --git a/Apps/Unsupported/Streaming-qt4/ACGMakefile b/Apps/Unsupported/Streaming-qt4/ACGMakefile new file mode 100644 index 0000000000000000000000000000000000000000..3e506776a47e28c0580696621f715b629f5f3ac9 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/ACGMakefile @@ -0,0 +1,16 @@ +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Config +#============================================================================== + + +SUBDIRS = $(call find-subdirs) + +PACKAGES := + +PROJ_LIBS := + +MODULES := + +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Rules +#============================================================================== diff --git a/Apps/Unsupported/Streaming-qt4/Client/ACGMakefile b/Apps/Unsupported/Streaming-qt4/Client/ACGMakefile new file mode 100644 index 0000000000000000000000000000000000000000..7be8556985ed8134646c1e088fa6c41f8fc4832a --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Client/ACGMakefile @@ -0,0 +1,19 @@ +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Config +#============================================================================== + +CXX_CFLAGS += -DQT_THREAD_SUPPORT + +SUBDIRS = $(call find-subdirs) + +PACKAGES := qt4 glut opengl + +PROJ_LIBS := OpenMesh/Apps/QtViewer \ + OpenMesh/Core OpenMesh/Tools + +MODULES := moc4 cxx + + +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Rules +#============================================================================== diff --git a/Apps/Unsupported/Streaming-qt4/Client/MeshViewerWidgetT.cc b/Apps/Unsupported/Streaming-qt4/Client/MeshViewerWidgetT.cc new file mode 100644 index 0000000000000000000000000000000000000000..b25f11da23a5baef10d9ce1dea90b3b9ae43837a --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Client/MeshViewerWidgetT.cc @@ -0,0 +1,603 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mon, 19 May 2008) $ +// +//============================================================================= +#define OPENMESHAPPS_MESHVIEWERWIDGET_CC + +//== INCLUDES ================================================================= + +#ifdef _MSC_VER +//# pragma warning(disable: 4267 4311) +#endif + +// +#include +#include +#include +#include +#include +#include +#include + +using namespace OpenMesh; + + +//== IMPLEMENTATION ========================================================== + + +template +bool +MeshViewerWidgetT::open_mesh(const char* _filename, + IO::Options _opt) +{ + // load mesh + // calculate normals + // set scene center and radius + + mesh_.request_face_normals(); + mesh_.request_face_colors(); + mesh_.request_vertex_normals(); + mesh_.request_vertex_texcoords2D(); + + if ( IO::read_mesh(mesh_, _filename, _opt )) + { + opt_ = _opt; + + // update face and vertex normals + if ( ! opt_.check( IO::Options::FaceNormal ) ) + mesh_.update_face_normals(); + + if ( ! opt_.check( IO::Options::VertexNormal ) ) + mesh_.update_vertex_normals(); + + if ( mesh_.has_vertex_colors() ) + add_draw_mode("Colored"); + + if ( _opt.check( IO::Options::FaceColor ) ) + add_draw_mode("Colored Faces"); + else + mesh_.release_face_colors(); + + // bounding box + typename Mesh::ConstVertexIter vIt(mesh_.vertices_begin()); + typename Mesh::ConstVertexIter vEnd(mesh_.vertices_end()); + + typedef typename Mesh::Point Point; + using OpenMesh::Vec3f; + + Vec3f bbMin, bbMax; + + bbMin = bbMax = OpenMesh::vector_cast(mesh_.point(vIt)); + + for (size_t count=0; vIt!=vEnd; ++vIt, ++count) + { + bbMin.minimize( OpenMesh::vector_cast(mesh_.point(vIt))); + bbMax.maximize( OpenMesh::vector_cast(mesh_.point(vIt))); + + if ( ! opt_.check( IO::Options::VertexColor ) && + mesh_.has_vertex_colors() ) + { + typename Mesh::Color + c( 54, + (unsigned char)(54.5+200.0*count/mesh_.n_vertices()), + 54 ); + mesh_.set_color( vIt, c ); + } + } + + + // set center and radius + set_scene_pos( (bbMin+bbMax)*0.5, (bbMin-bbMax).norm()*0.5 ); + + // info + std::clog << mesh_.n_vertices() << " vertices, " + << mesh_.n_edges() << " edge, " + << mesh_.n_faces() << " faces\n"; + + // + { + std::clog << "Computing strips.." << std::flush; + OpenMesh::Utils::Timer t; + t.start(); + compute_strips(); + t.stop(); + std::clog << "done [" << strips_.n_strips() + << " strips created in " << t.as_string() << "]\n"; + } + +#if defined(OM_CC_MSVC) + updateGL(); +#endif + + return true; + } + return false; +} + + +//----------------------------------------------------------------------------- + +template +bool MeshViewerWidgetT::open_texture( const char *_filename ) +{ + QImage texsrc; + QString fname = _filename; + + if (texsrc.load( fname )) + { + return set_texture( texsrc ); + } + return false; +} + + +//----------------------------------------------------------------------------- + +template +bool MeshViewerWidgetT::set_texture( QImage& _texsrc ) +{ + std::clog << "set_texture\n"; + + if ( !opt_.vertex_has_texcoord() ) + return false; + + { + // adjust texture size: 2^k * 2^l + int tex_w, w( _texsrc.width() ); + int tex_h, h( _texsrc.height() ); + + for (tex_w=1; tex_w <= w; tex_w <<= 1) ; + for (tex_h=1; tex_h <= h; tex_h <<= 1) ; + tex_w >>= 1; + tex_h >>= 1; + _texsrc = _texsrc.scaled( tex_w, tex_h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); + } + + QImage texture( QGLWidget::convertToGLFormat ( _texsrc ) ); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + if ( tex_id_ > 0 ) + { + glDeleteTextures(1, &tex_id_); + } + glGenTextures(1, &tex_id_); + glBindTexture(GL_TEXTURE_2D, tex_id_); + + // glTexGenfv( GL_S, GL_SPHERE_MAP, 0 ); + // glTexGenfv( GL_T, GL_SPHERE_MAP, 0 ); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, // target + 0, // level + GL_RGBA, // internal format + texture.width(), // width (2^n) + texture.height(), // height (2^m) + 0, // border + GL_RGBA, // format + GL_UNSIGNED_BYTE, // type + texture.bits() ); // pointer to pixels + + return true; +} + + +//----------------------------------------------------------------------------- + +template +void +MeshViewerWidgetT::draw_openmesh(const std::string& _draw_mode) +{ + typename Mesh::ConstFaceIter fIt(mesh_.faces_begin()), + fEnd(mesh_.faces_end()); + + typename Mesh::ConstFaceVertexIter fvIt; + +#if defined(OM_USE_OSG) && OM_USE_OSG + if (_draw_mode == "OpenSG Indices") // -------------------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, mesh_.vertex_normals()); + + if ( tex_id_ && mesh_.has_vertex_texcoords2D() ) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, mesh_.texcoords2D()); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tex_id_); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_mode_); + } + + glDrawElements(GL_TRIANGLES, + mesh_.osg_indices()->size(), + GL_UNSIGNED_INT, + &mesh_.osg_indices()->getField()[0] ); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + else +#endif + + if (_draw_mode == "Wireframe") // -------------------------------------------- + { + glBegin(GL_TRIANGLES); + for (; fIt!=fEnd; ++fIt) + { + fvIt = mesh_.cfv_iter(fIt.handle()); + glVertex3fv( &mesh_.point(fvIt)[0] ); + ++fvIt; + glVertex3fv( &mesh_.point(fvIt)[0] ); + ++fvIt; + glVertex3fv( &mesh_.point(fvIt)[0] ); + } + glEnd(); + } + + else if (_draw_mode == "Solid Flat") // ------------------------------------- + { + glBegin(GL_TRIANGLES); + for (; fIt!=fEnd; ++fIt) + { + glNormal3fv( &mesh_.normal(fIt)[0] ); + + fvIt = mesh_.cfv_iter(fIt.handle()); + glVertex3fv( &mesh_.point(fvIt)[0] ); + ++fvIt; + glVertex3fv( &mesh_.point(fvIt)[0] ); + ++fvIt; + glVertex3fv( &mesh_.point(fvIt)[0] ); + } + glEnd(); + + + } + + + else if (_draw_mode == "Solid Smooth") // ----------------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, mesh_.vertex_normals()); + + if ( tex_id_ && mesh_.has_vertex_texcoords2D() ) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, mesh_.texcoords2D()); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tex_id_); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_mode_); + } + + glBegin(GL_TRIANGLES); + for (; fIt!=fEnd; ++fIt) + { + fvIt = mesh_.cfv_iter(fIt.handle()); + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + } + glEnd(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + if ( tex_id_ && mesh_.has_vertex_texcoords2D() ) + { + glDisable(GL_TEXTURE_2D); + } + } + + else if (_draw_mode == "Colored") // ---------------------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, mesh_.vertex_normals()); + + if ( mesh_.has_vertex_colors() ) + { + glEnableClientState( GL_COLOR_ARRAY ); + glColorPointer(3, GL_UNSIGNED_BYTE, 0,mesh_.vertex_colors()); + } + + glBegin(GL_TRIANGLES); + for (; fIt!=fEnd; ++fIt) + { + fvIt = mesh_.cfv_iter(fIt.handle()); + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + } + glEnd(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } + + + else if (_draw_mode == "Colored Faces") // ---------------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, mesh_.vertex_normals()); + + glBegin(GL_TRIANGLES); + for (; fIt!=fEnd; ++fIt) + { + glColor( fIt.handle() ); + + fvIt = mesh_.cfv_iter(fIt.handle()); + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + } + glEnd(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + } + + + else if ( _draw_mode == "Strips'n VertexArrays" ) // ------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, mesh_.vertex_normals()); + + if ( tex_id_ && mesh_.has_vertex_texcoords2D() ) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, mesh_.texcoords2D()); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tex_id_); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_mode_); + } + + typename MyStripifier::StripsIterator strip_it = strips_.begin(); + typename MyStripifier::StripsIterator strip_last = strips_.end(); + + // Draw all strips + for (; strip_it!=strip_last; ++strip_it) + { + glDrawElements(GL_TRIANGLE_STRIP, + strip_it->size(), GL_UNSIGNED_INT, &(*strip_it)[0] ); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + + + else if (_draw_mode == "Show Strips" && strips_.is_valid() ) // ------------- + { + typename MyStripifier::StripsIterator strip_it = strips_.begin(); + typename MyStripifier::StripsIterator strip_last = strips_.end(); + + float cmax = 256.0f; + int range = 220; + int base = (int)cmax-range; + int drcol = 13; + int dgcol = 31; + int dbcol = 17; + + int rcol=0, gcol=dgcol, bcol=dbcol+dbcol; + + // Draw all strips + for (; strip_it!=strip_last; ++strip_it) + { + typename MyStripifier::IndexIterator idx_it = strip_it->begin(); + typename MyStripifier::IndexIterator idx_last = strip_it->end(); + + rcol = (rcol+drcol) % range; + gcol = (gcol+dgcol) % range; + bcol = (bcol+dbcol) % range; + + glBegin(GL_TRIANGLE_STRIP); + glColor3f((rcol+base)/cmax, (gcol+base)/cmax, (bcol+base)/cmax); + for ( ;idx_it != idx_last; ++idx_it ) + glVertex3fv( &mesh_.point( OM_TYPENAME Mesh::VertexHandle(*idx_it))[0] ); + glEnd(); + } + glColor3f(1.0, 1.0, 1.0); + } + + + else if( _draw_mode == "Points" ) // ----------------------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + glDrawArrays( GL_POINTS, 0, mesh_.n_vertices() ); + glDisableClientState(GL_VERTEX_ARRAY); + } + + +} + + +//----------------------------------------------------------------------------- + + +template +void +MeshViewerWidgetT::draw_scene(const std::string& _draw_mode) +{ + + if ( ! mesh_.n_vertices() ) + return; + +#if defined(OM_USE_OSG) && OM_USE_OSG + else if ( _draw_mode == "OpenSG Indices") + { + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); + draw_openmesh( _draw_mode ); + } + else +#endif + if ( _draw_mode == "Points" ) + { + glDisable(GL_LIGHTING); + draw_openmesh(_draw_mode); + } + else if (_draw_mode == "Wireframe") + { + glDisable(GL_LIGHTING); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + draw_openmesh(_draw_mode); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + + else if ( _draw_mode == "Hidden-Line" ) + { + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glDepthRange(0.01, 1.0); + draw_openmesh("Solid Smooth"); + + glDisable(GL_LIGHTING); + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE); + glColor4f( 0.4f, 0.4f, 0.4f, 1.0f ); + glDepthRange( 0.0, 1.0 ); + draw_openmesh( "Wireframe" ); + + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL); + } + + else if (_draw_mode == "Solid Flat") + { + glEnable(GL_LIGHTING); + glShadeModel(GL_FLAT); + draw_openmesh(_draw_mode); + } + + else if (_draw_mode == "Solid Smooth" || + _draw_mode == "Strips'n VertexArrays" ) + { + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); + draw_openmesh(_draw_mode); + } + + else if (_draw_mode == "Show Strips") + { + glDisable(GL_LIGHTING); + draw_openmesh(_draw_mode); + } + + else if (_draw_mode == "Colored" ) + { + glDisable(GL_LIGHTING); + draw_openmesh(_draw_mode); + } + + else if (_draw_mode == "Colored Faces" ) + { + glDisable(GL_LIGHTING); + draw_openmesh(_draw_mode); + } +} + + +//----------------------------------------------------------------------------- + +#define TEXMODE( Mode ) \ + tex_mode_ = Mode; std::cout << "Texture mode set to " << #Mode << std::endl + +template +void +MeshViewerWidgetT::keyPressEvent( QKeyEvent* _event) +{ + switch( _event->key() ) + { + case Qt::Key_I: + std::cout << "\n# Vertices : " << mesh_.n_vertices() << std::endl; + std::cout << "# Edges : " << mesh_.n_edges() << std::endl; + std::cout << "# Faces : " << mesh_.n_faces() << std::endl; + std::cout << "binary input : " << opt_.check(opt_.Binary) << std::endl; + std::cout << "swapped input : " << opt_.check(opt_.Swap) << std::endl; + std::cout << "vertex normal : " + << opt_.check(opt_.VertexNormal) << std::endl; + std::cout << "vertex texcoord: " + << opt_.check(opt_.VertexTexCoord) << std::endl; + std::cout << "vertex color : " + << opt_.check(opt_.VertexColor) << std::endl; + this->QGLViewerWidget::keyPressEvent( _event ); + break; + + case Qt::Key_T: + switch( tex_mode_ ) + { + case GL_MODULATE: TEXMODE(GL_DECAL); break; + case GL_DECAL: TEXMODE(GL_BLEND); break; + case GL_BLEND: TEXMODE(GL_REPLACE); break; + case GL_REPLACE: TEXMODE(GL_MODULATE); break; + } + updateGL(); + break; + + default: + this->QGLViewerWidget::keyPressEvent( _event ); + } +} + +#undef TEXMODE + +//============================================================================= diff --git a/Apps/Unsupported/Streaming-qt4/Client/MeshViewerWidgetT.hh b/Apps/Unsupported/Streaming-qt4/Client/MeshViewerWidgetT.hh new file mode 100644 index 0000000000000000000000000000000000000000..6ee8580806afa05c0c3756637fbd48ea5e4ba125 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Client/MeshViewerWidgetT.hh @@ -0,0 +1,163 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mon, 19 May 2008) $ +// +//============================================================================= + + +#ifndef OPENMESHAPPS_MESHVIEWERWIDGETT_HH +#define OPENMESHAPPS_MESHVIEWERWIDGETT_HH + + +//== INCLUDES ================================================================= + +#include +#include +#include +#include +#include +#include +#include +#include + + +//== FORWARDS ================================================================= + +class QImage; + + +//== CLASS DEFINITION ========================================================= + + +template +class MeshViewerWidgetT : public QGLViewerWidget +{ +public: + typedef M Mesh; + typedef OpenMesh::StripifierT MyStripifier; + + + /// default constructor + MeshViewerWidgetT(QWidget* _parent=0, const char* _name=0) + : QGLViewerWidget(_parent, _name), + f_strips_(false), + tex_id_(0), + tex_mode_(GL_MODULATE), + strips_(mesh_) + { + add_draw_mode("Points"); + add_draw_mode("Hidden-Line"); +#if defined(OM_USE_OSG) && OM_USE_OSG + add_draw_mode("OpenSG Indices"); +#endif + } + + void enable_strips() { + f_strips_ = true; + add_draw_mode("Strips'n VertexArrays"); + add_draw_mode("Show Strips"); + } + void disable_strips() { f_strips_ = false; } + + /// destructor + ~MeshViewerWidgetT() {} + + /// open mesh + virtual bool open_mesh(const char* _filename, OpenMesh::IO::Options _opt); + + /// load texture + virtual bool open_texture( const char *_filename ); + bool set_texture( QImage& _texsrc ); + + + Mesh& mesh() { return mesh_; } + const Mesh& mesh() const { return mesh_; } + + +protected: + + /// inherited drawing method + virtual void draw_scene(const std::string& _draw_mode); + +protected: + + /// draw the mesh + virtual void draw_openmesh(const std::string& _drawmode); + + void glVertex( const typename Mesh::VertexHandle vh ) + { glVertex3fv( &mesh_.point( vh )[0] ); } + + void glNormal( const typename Mesh::VertexHandle vh ) + { glNormal3fv( &mesh_.normal( vh )[0] ); } + + void glTexCoord( const typename Mesh::VertexHandle vh ) + { glTexCoord2fv( &mesh_.texcoord(vh)[0] ); } + + void glColor( const typename Mesh::VertexHandle vh ) + { glColor3ubv( &mesh_.color(vh)[0] ); } + + void glColor( const typename Mesh::FaceHandle fh ) + { glColor3ubv( &mesh_.color(fh)[0] ); } + + + +protected: // Strip support + + void compute_strips(void) + { + if (f_strips_) + { + strips_.clear(); + strips_.stripify(); + } + } + +protected: // inherited + + virtual void keyPressEvent( QKeyEvent* _event); + +protected: + + bool f_strips_; // enable/disable strip usage + GLuint tex_id_; + GLint tex_mode_; + OpenMesh::IO::Options opt_; // mesh file contained texcoords? + + Mesh mesh_; + MyStripifier strips_; +}; + + +//============================================================================= +#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESHAPPS_MESHVIEWERWIDGET_CC) +# define OPENMESH_MESHVIEWERWIDGET_TEMPLATES +# include "MeshViewerWidgetT.cc" +#endif +//============================================================================= +#endif // OPENMESHAPPS_MESHVIEWERWIDGETT_HH defined +//============================================================================= + diff --git a/Apps/Unsupported/Streaming-qt4/Client/MyMesh.hh b/Apps/Unsupported/Streaming-qt4/Client/MyMesh.hh new file mode 100644 index 0000000000000000000000000000000000000000..b6dfdb2e65168fc0b449a9ced184e49f4f51c479 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Client/MyMesh.hh @@ -0,0 +1,23 @@ +#ifndef OPENMESH_APPS_VDPMSTREAMING_CLIENT_MYMESH_HH +#define OPENMESH_APPS_VDPMSTREAMING_CLIENT_MYMESH_HH + +#include +#include +#include +#include + + +using OpenMesh::VDPM::MeshTraits; + + +//== CLASS DEFINITION ========================================================= + + +typedef OpenMesh::TriMesh_ArrayKernelT MyMesh; + +static QMutex mutex_; + + +//== CLASS DEFINITION ========================================================= + +#endif //OPENMESH_APPS_VDPMSTREAMING_CLIENT_MYMESH_HH defined diff --git a/Apps/Unsupported/Streaming-qt4/Client/QGLViewerWidget.cc b/Apps/Unsupported/Streaming-qt4/Client/QGLViewerWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..d729c4780182312330117722947c440159616b80 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Client/QGLViewerWidget.cc @@ -0,0 +1,621 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mon, 19 May 2008) $ +// +//============================================================================= + + +//== INCLUDES ================================================================= + +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311 4305) +#endif + +#include + +#include +// #include +#include +#include +#include +#include + +#include +#include + +#if !defined(M_PI) +# define M_PI 3.1415926535897931 +#endif + +using namespace OpenMesh; + + +//== IMPLEMENTATION ========================================================== + + +QGLViewerWidget::QGLViewerWidget( QWidget* _parent, const char* _name ) + : QGLWidget( _parent ) +{ + // qt stuff + setWindowTitle(_name); +// setBackgroundMode( NoBackground ); + setFocusPolicy(Qt::StrongFocus); + setAcceptDrops( true ); + setCursor(Qt::PointingHandCursor); + + + // popup menu + popup_menu_ = new QMenu("Draw Mode Menu", this); + + connect( popup_menu_, SIGNAL(activated(int)), + this, SLOT(slotPopupMenu(int))); + + + // init draw modes + n_draw_modes_ = 0; + add_draw_mode("Wireframe"); + add_draw_mode("Solid Flat"); + add_draw_mode("Solid Smooth"); + + // for example + add_draw_mode("Colored"); + + slotPopupMenu(2); +} + + +//---------------------------------------------------------------------------- + + +QGLViewerWidget::~QGLViewerWidget() +{ +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::initializeGL() +{ + // OpenGL state + glClearColor(1.0, 1.0, 1.0, 0.0); + glDisable( GL_DITHER ); + glEnable( GL_DEPTH_TEST ); + glEnable( GL_CULL_FACE ); + + + // material + GLfloat mat_a[] = {0.7, 0.6, 0.5, 1.0}; + GLfloat mat_d[] = {0.8, 0.7, 0.6, 1.0}; + GLfloat mat_s[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat shine[] = {120.0}; + +// GLfloat mat_a[] = {0.2, 0.2, 0.2, 1.0}; +// GLfloat mat_d[] = {0.4, 0.4, 0.4, 1.0}; +// GLfloat mat_s[] = {0.8, 0.8, 0.8, 1.0}; +// GLfloat shine[] = {128.0}; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_a); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_d); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_s); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shine); + + + // lighting + glLoadIdentity(); + + GLfloat pos1[] = { 0.1, 0.1, -0.02, 0.0}; + GLfloat pos2[] = {-0.1, 0.1, -0.02, 0.0}; + GLfloat pos3[] = { 0.0, 0.0, 0.1, 0.0}; + GLfloat col1[] = {.05, .05, .4, 1.0}; + GLfloat col2[] = {.4, .05, .05, 1.0}; + GLfloat col3[] = {1.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0,GL_POSITION, pos1); + glLightfv(GL_LIGHT0,GL_DIFFUSE, col1); + glLightfv(GL_LIGHT0,GL_SPECULAR, col1); + + glEnable(GL_LIGHT1); + glLightfv(GL_LIGHT1,GL_POSITION, pos2); + glLightfv(GL_LIGHT1,GL_DIFFUSE, col2); + glLightfv(GL_LIGHT1,GL_SPECULAR, col2); + + glEnable(GL_LIGHT2); + glLightfv(GL_LIGHT2,GL_POSITION, pos3); + glLightfv(GL_LIGHT2,GL_DIFFUSE, col3); + glLightfv(GL_LIGHT2,GL_SPECULAR, col3); + + + // Fog + GLfloat fogColor[4] = { 0.4, 0.4, 0.5, 1.0 }; + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogfv(GL_FOG_COLOR, fogColor); + glFogf(GL_FOG_DENSITY, 0.35); + glHint(GL_FOG_HINT, GL_DONT_CARE); + glFogf(GL_FOG_START, 5.0f); + glFogf(GL_FOG_END, 25.0f); + + // scene pos and size + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix_); + set_scene_pos(Vec3f(0.0, 0.0, 0.0), 1.0); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::resizeGL( int _w, int _h ) +{ + update_projection_matrix(); + glViewport(0, 0, _w, _h); + updateGL(); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::paintGL() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode( GL_PROJECTION ); + glLoadMatrixd( projection_matrix_ ); + glMatrixMode( GL_MODELVIEW ); + glLoadMatrixd( modelview_matrix_ ); + + if (draw_mode_) + { + assert(draw_mode_ <= n_draw_modes_); + draw_scene(draw_mode_names_[draw_mode_-1]); + } +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::draw_scene(const std::string& _draw_mode) +{ + if (_draw_mode == "Wireframe") + { + glDisable(GL_LIGHTING); + glutWireTeapot(0.5); + } + + else if (_draw_mode == "Solid Flat") + { + glEnable(GL_LIGHTING); + glShadeModel(GL_FLAT); + glutSolidTeapot(0.5); + } + + else if (_draw_mode == "Solid Smooth") + { + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); + glutSolidTeapot(0.5); + } + +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::mousePressEvent( QMouseEvent* _event ) +{ + // popup menu + if (_event->button() == Qt::RightButton) + { + popup_menu_->exec(QCursor::pos()); + } + + else + { + last_point_ok_ = map_to_sphere( last_point_2D_=_event->pos(), + last_point_3D_ ); + } +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::mouseMoveEvent( QMouseEvent* _event ) +{ + QPoint newPoint2D = _event->pos(); + + if ( (newPoint2D.x()<0) || (newPoint2D.x()>width()) || + (newPoint2D.y()<0) || (newPoint2D.y()>height()) ) return; + + + // Left button: rotate around center_ + // Middle button: translate object + // Left & middle button: zoom in/out + + + float value_y; + Vec3f newPoint3D; + bool newPoint_hitSphere = map_to_sphere( newPoint2D, newPoint3D ); + + float dx = newPoint2D.x() - last_point_2D_.x(); + float dy = newPoint2D.y() - last_point_2D_.y(); + + float w = width(); + float h = height(); + + + + // enable GL context + makeCurrent(); + + + // move in z direction + if ( (_event->button() == Qt::LeftButton) && (_event->button() == Qt::MidButton)) + { + value_y = radius_ * dy * 3.0 / h; + translate(Vec3f(0.0, 0.0, value_y)); + } + + + // move in x,y direction + else if (_event->button() == Qt::MidButton) + { + float z = - (modelview_matrix_[ 2]*center_[0] + + modelview_matrix_[ 6]*center_[1] + + modelview_matrix_[10]*center_[2] + + modelview_matrix_[14]) / + (modelview_matrix_[ 3]*center_[0] + + modelview_matrix_[ 7]*center_[1] + + modelview_matrix_[11]*center_[2] + + modelview_matrix_[15]); + + float aspect = w / h; + float near_plane = 0.01 * radius_; + float top = tan(fovy()/2.0f*M_PI/180.0f) * near_plane; + float right = aspect*top; + + translate(Vec3f( 2.0*dx/w*right/near_plane*z, + -2.0*dy/h*top/near_plane*z, + 0.0f)); + } + + + + // rotate + else if (_event->button() == Qt::LeftButton) + { + if (last_point_ok_) + { + if ( (newPoint_hitSphere = map_to_sphere(newPoint2D, newPoint3D)) ) + { + Vec3f axis = last_point_3D_ % newPoint3D; + float cos_angle = (last_point_3D_ | newPoint3D); + if ( fabs(cos_angle) < 1.0 ) + { + float angle = 2.0 * acos( cos_angle ) * 180.0 / M_PI; + rotate( axis, angle ); + } + } + } + } + + + // remember this point + last_point_2D_ = newPoint2D; + last_point_3D_ = newPoint3D; + last_point_ok_ = newPoint_hitSphere; + + // trigger redraw + updateGL(); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::mouseReleaseEvent( QMouseEvent* /* _event */ ) +{ + last_point_ok_ = false; +} + + +//----------------------------------------------------------------------------- + + +void QGLViewerWidget::wheelEvent(QWheelEvent* _event) +{ + // Use the mouse wheel to zoom in/out + + float d = -(float)_event->delta() / 120.0 * 0.2 * radius_; + translate(Vec3f(0.0, 0.0, d)); + updateGL(); + _event->accept(); +} + + +//---------------------------------------------------------------------------- + + +void QGLViewerWidget::keyPressEvent( QKeyEvent* _event) +{ + switch( _event->key() ) + { + case Qt::Key_C: + if ( glIsEnabled( GL_CULL_FACE ) ) + { + glDisable( GL_CULL_FACE ); + std::cout << "Back face culling: disabled\n"; + } + else + { + glEnable( GL_CULL_FACE ); + std::cout << "Back face culling: enabled\n"; + } + updateGL(); + break; + + case Qt::Key_I: + std::cout << "Radius: " << radius_ << std::endl; + std::cout << "Center: " << center_ << std::endl; + break; + + case Qt::Key_Space: + case Qt::Key_M: + { + double fps = performance(); + std::cout << "fps: " +#if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000) + << std::setiosflags (std::ios::fixed) +#else + << std::setiosflags (std::ios_base::fixed) +#endif + << fps << std::endl; + } + break; + + case Qt::Key_Q: + case Qt::Key_Escape: + qApp->quit(); + } + _event->ignore(); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::translate( const Vec3f& _trans ) +{ + // Translate the object by _trans + // Update modelview_matrix_ + makeCurrent(); + glLoadIdentity(); + glTranslated( _trans[0], _trans[1], _trans[2] ); + glMultMatrixd( modelview_matrix_ ); + glGetDoublev( GL_MODELVIEW_MATRIX, modelview_matrix_); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::rotate( const Vec3f& _axis, float _angle ) +{ + // Rotate around center center_, axis _axis, by angle _angle + // Update modelview_matrix_ + + Vec3f t( modelview_matrix_[0]*center_[0] + + modelview_matrix_[4]*center_[1] + + modelview_matrix_[8]*center_[2] + + modelview_matrix_[12], + modelview_matrix_[1]*center_[0] + + modelview_matrix_[5]*center_[1] + + modelview_matrix_[9]*center_[2] + + modelview_matrix_[13], + modelview_matrix_[2]*center_[0] + + modelview_matrix_[6]*center_[1] + + modelview_matrix_[10]*center_[2] + + modelview_matrix_[14] ); + + makeCurrent(); + glLoadIdentity(); + glTranslatef(t[0], t[1], t[2]); + glRotated( _angle, _axis[0], _axis[1], _axis[2]); + glTranslatef(-t[0], -t[1], -t[2]); + glMultMatrixd(modelview_matrix_); + glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix_); +} + + +//---------------------------------------------------------------------------- + + +bool +QGLViewerWidget::map_to_sphere( const QPoint& _v2D, Vec3f& _v3D ) +{ + if ( (_v2D.x() >= 0) && (_v2D.x() <= width()) && + (_v2D.y() >= 0) && (_v2D.y() <= height()) ) + { + double x = (double)(_v2D.x() - 0.5*width()) / (double)width(); + double y = (double)(0.5*height() - _v2D.y()) / (double)height(); + double sinx = sin(M_PI * x * 0.5); + double siny = sin(M_PI * y * 0.5); + double sinx2siny2 = sinx * sinx + siny * siny; + + _v3D[0] = sinx; + _v3D[1] = siny; + _v3D[2] = sinx2siny2 < 1.0 ? sqrt(1.0 - sinx2siny2) : 0.0; + + return true; + } + else return false; +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::update_projection_matrix() +{ + makeCurrent(); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + gluPerspective(45.0, (GLfloat) width() / (GLfloat) height(), + 0.01*radius_, 100.0*radius_); + glGetDoublev( GL_PROJECTION_MATRIX, projection_matrix_); + glMatrixMode( GL_MODELVIEW ); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::view_all() +{ + translate( Vec3f( -(modelview_matrix_[0]*center_[0] + + modelview_matrix_[4]*center_[1] + + modelview_matrix_[8]*center_[2] + + modelview_matrix_[12]), + -(modelview_matrix_[1]*center_[0] + + modelview_matrix_[5]*center_[1] + + modelview_matrix_[9]*center_[2] + + modelview_matrix_[13]), + -(modelview_matrix_[2]*center_[0] + + modelview_matrix_[6]*center_[1] + + modelview_matrix_[10]*center_[2] + + modelview_matrix_[14] + + 3.0*radius_) ) ); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::set_scene_pos( const Vec3f& _cog, float _radius ) +{ + center_ = _cog; + radius_ = _radius; + glFogf( GL_FOG_START, _radius ); + glFogf( GL_FOG_END, 4.0*_radius ); + + update_projection_matrix(); + view_all(); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::add_draw_mode(std::string _s) +{ + ++n_draw_modes_; + + // insert in popup menu + QString str( _s.c_str() ); + popup_menu_->addAction( str ); + + // store draw mode + draw_mode_names_.push_back(_s); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::slotPopupMenu(int _id) +{ + // set check status + for (int i=0; i < popup_menu_->actions().count(); ++i) + popup_menu_->actions()[i]->setChecked( i == _id ); + + // save draw mode + draw_mode_ = _id; +} + + +//---------------------------------------------------------------------------- + + +double +QGLViewerWidget::performance() +{ + setCursor( Qt::WaitCursor ); + + double fps(0.0); + + makeCurrent(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + OpenMesh::Utils::Timer timer; + + unsigned int frames = 60; + const float angle = 360.0/(float)frames; + unsigned int i; + Vec3f axis; + + glFinish(); + timer.start(); + + for (i=0, axis=Vec3f(1,0,0); i +#include +#include +#include +#include + + +//== FORWARD DECLARATIONS ===================================================== + + +class QPopupMenu; + + +//== CLASS DEFINITION ========================================================= + + +class QGLViewerWidget : public QGLWidget +{ + + Q_OBJECT + +public: + + // Default constructor. + QGLViewerWidget( QWidget* _parent=0, const char* _name=0 ); + + // Destructor. + virtual ~QGLViewerWidget(); + + /* Sets the center and size of the whole scene. + The _center is used as fixpoint for rotations and for adjusting + the camera/viewer (see view_all()). */ + void set_scene_pos( const OpenMesh::Vec3f& _center, float _radius ); + + /* view the whole scene: the eye point is moved far enough from the + center so that the whole scene is visible. */ + void view_all(); + + /// add draw mode to popup menu + void add_draw_mode(std::string _s); + + float radius() const { return radius_; } + const OpenMesh::Vec3f& center() const { return center_; } + + const GLdouble* modelview_matrix() const { return modelview_matrix_; } + const GLdouble* projection_matrix() const { return projection_matrix_; } + void set_modelview_matrix(const GLdouble _modelview_matrix[16]) + { memcpy(modelview_matrix_, _modelview_matrix, 16*sizeof(GLdouble)); } + void set_projection_matrix(const GLdouble _projection_matrix[16]) + { memcpy(projection_matrix_, _projection_matrix, 16*sizeof(GLdouble)); } + + float fovy() const { return 45.0f; } + +protected: + + // draw the scene: will be called by the painGL() method. + virtual void draw_scene(const std::string& _draw_mode); + + double performance(void); + +private slots: + + // popup menu clicked + void slotPopupMenu(int _id); + +private: // inherited + + // initialize OpenGL states (triggered by Qt) + void initializeGL(); + + // draw the scene (triggered by Qt) + void paintGL(); + + // handle resize events (triggered by Qt) + void resizeGL( int w, int h ); + +protected: + + // Qt mouse events + virtual void mousePressEvent( QMouseEvent* ); + virtual void mouseReleaseEvent( QMouseEvent* ); + virtual void mouseMoveEvent( QMouseEvent* ); + virtual void wheelEvent( QWheelEvent* ); + virtual void keyPressEvent( QKeyEvent* ); + +private: + + // updates projection matrix + void update_projection_matrix(); + +protected: + // translate the scene and update modelview matrix + void translate(const OpenMesh::Vec3f& _trans); + + // rotate the scene (around its center) and update modelview matrix + void rotate(const OpenMesh::Vec3f& _axis, float _angle); + + OpenMesh::Vec3f center_; + float radius_; + + GLdouble projection_matrix_[16], + modelview_matrix_[16]; + + + // popup menu for draw mode selection + QMenu* popup_menu_; + unsigned int draw_mode_; + unsigned int n_draw_modes_; + std::vector draw_mode_names_; + + + + // virtual trackball: map 2D screen point to unit sphere + bool map_to_sphere(const QPoint& _point, OpenMesh::Vec3f& _result); + + QPoint last_point_2D_; + OpenMesh::Vec3f last_point_3D_; + bool last_point_ok_; + +}; + + +//============================================================================= +#endif // OPENMESHAPPS_QGLVIEWERWIDGET_HH +//============================================================================= + diff --git a/Apps/Unsupported/Streaming-qt4/Client/VDPMClientViewerWidget.cc b/Apps/Unsupported/Streaming-qt4/Client/VDPMClientViewerWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..ff8ff068171d68cc720e076b63150d2244048d55 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Client/VDPMClientViewerWidget.cc @@ -0,0 +1,1351 @@ + +//== INCLUDES ================================================================= + +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311) +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +// #include "ImageData.h" + + +using OpenMesh::VDPM::debug_print; +using OpenMesh::VDPM::set_debug_print; + +using OpenMesh::VDPM::VHierarchyNode; +using OpenMesh::VDPM::VHierarchyNodeHandle; +using OpenMesh::VDPM::VHierarchyNodeHandleContainer; + + + +#ifdef EXAMPLE_CREATION + +static OpenMesh::Vec3uc myYellow = OpenMesh::Vec3uc(255, 255, 0); +static OpenMesh::Vec3uc myBlue = OpenMesh::Vec3uc(0, 0, 255); +std::map g_index2numdesc_map; + +void VDPMClientViewerWidget::increase_max_descendents(const VHierarchyNodeIndex &_node_index) +{ + g_index2numdesc_map[_node_index] = 2 + g_index2numdesc_map[_node_index]; + + unsigned char tree_id_bits = vhierarchy_.tree_id_bits(); + VHierarchyNodeIndex parent_index + = VHierarchyNodeIndex(_node_index.tree_id(tree_id_bits), _node_index.node_id(tree_id_bits) / 2, tree_id_bits); + + if (parent_index.is_valid(tree_id_bits) == true) + increase_max_descendents(parent_index); +} + +void VDPMClientViewerWidget::increase_cur_descendents(VHierarchyNodeHandle _node_handle) +{ + unsigned int cur_desc = vhierarchy_.node(_node_handle).cur_descendents(); + + vhierarchy_.node(_node_handle).set_cur_descendents(2 + cur_desc); + + VHierarchyNodeHandle parent_handle = vhierarchy_.parent_handle(_node_handle); + if (parent_handle.is_valid()) + increase_cur_descendents(parent_handle); +} + +void VDPMClientViewerWidget::__add_children(const VHierarchyNodeIndex &_node_index, bool update_current) +{ + if (update_current == true) + { + increase_cur_descendents(vhierarchy_.node_handle(_node_index)); + } + else + { + unsigned char tree_id_bits = vhierarchy_.tree_id_bits(); + + VHierarchyNodeIndex lchild_index + = VHierarchyNodeIndex(_node_index.tree_id(tree_id_bits), 2*_node_index.node_id(tree_id_bits), tree_id_bits); + VHierarchyNodeIndex rchild_index + = VHierarchyNodeIndex(_node_index.tree_id(tree_id_bits), 1+2*_node_index.node_id(tree_id_bits), tree_id_bits); + + g_index2numdesc_map[lchild_index] = 1; + g_index2numdesc_map[rchild_index] = 1; + + increase_max_descendents(_node_index); + } +} + +void VDPMClientViewerWidget::mesh_coloring() +{ + MyMesh::VertexIter vIt(mesh_.vertices_begin()), + vEnd(mesh_.vertices_end()); + + VHierarchyNodeHandle node_handle; + float ratio; + unsigned char r, g, b; + + for (; vIt!=vEnd; ++vIt) + { + node_handle = mesh_.data(vIt.handle()).vhierarchy_node_handle(); + ratio = vhierarchy_.node(node_handle).ratio(); + + r = (unsigned char) ((1.0f - ratio) * myYellow[0] + ratio * myBlue[0]); + g = (unsigned char) ((1.0f - ratio) * myYellow[1] + ratio * myBlue[1]); + b = (unsigned char) ((1.0f - ratio) * myYellow[2] + ratio * myBlue[2]); + + mesh_.set_color(vIt.handle(), OpenMesh::Vec3uc(r,g,b)); + } +} + +#endif + + + +void +VDPMClientViewerWidget:: +draw_scene(const std::string &_draw_mode) +{ + //std::cout << frame_ << "-th frame statistics" << std::endl; + + if (adaptive_mode_ == true) + { + + refinement_timer_.start(); + adaptive_refinement(); + refinement_timer_.stop(); + fprintf(refinement_file, "%d %d\n", frame_, (int) refinement_timer_.mseconds()); + +#ifdef EXAMPLE_CREATION + mesh_coloring(); +#endif + } + + render_timer_.start(); + MeshViewerWidget::draw_scene(_draw_mode); + render_timer_.stop(); + fprintf(render_file, "%d %d %d\n", frame_, (int) render_timer_.mseconds(), mesh_.n_faces()); + + ++frame_; +} + + +void +VDPMClientViewerWidget:: +adaptive_refinement() +{ + update_viewing_parameters(); + + MyMesh::HalfedgeHandle v0v1; + float fovy = viewing_parameters_.fovy(); + float tolerance_square = viewing_parameters_.tolerance_square(); + float tan_value = tanf(fovy / 2.0f); + kappa_square_ = 4.0f * tan_value * tan_value * tolerance_square; + + + for (vfront_.begin(); vfront_.end() != true;) + { + VHierarchyNodeHandle + node_handle = vfront_.node_handle(), + parent_handle = vhierarchy_.parent_handle(node_handle); + + if (qrefine(node_handle) == true) + { + if (vhierarchy_.is_leaf_node(node_handle) != true) + { + force_vsplit(node_handle); + } + else + { + //if (qSocket_->bytesAvailable() == 0) + if (session_running_ != true) + { + session_running_ = true; + send_viewing_information(); + } + vfront_.next(); + } + } + else if (vhierarchy_.is_root_node(node_handle) != true && + ecol_legal(parent_handle, v0v1) == true && + qrefine(parent_handle) != true) + { + ecol(parent_handle, v0v1); + } + else + { + vfront_.next(); + } + } + + // free memories taged as 'deleted' + mesh_.garbage_collection(false, true, true); + mesh_.update_face_normals(); +} + + +void +VDPMClientViewerWidget:: +current_max_resolution() +{ + for (vfront_.begin(); vfront_.end() != true;) + { + VHierarchyNodeHandle + node_handle = vfront_.node_handle(), + parent_handle = vhierarchy_.parent_handle(node_handle); + + if (vhierarchy_.is_leaf_node(node_handle) != true) + force_vsplit(node_handle); + else + vfront_.next(); + } + + // free memories taged as 'deleted' + mesh_.garbage_collection(false, true, true); + mesh_.update_face_normals(); +} + + +bool +VDPMClientViewerWidget:: +qrefine(VHierarchyNodeHandle _node_handle) +{ + VHierarchyNode &node = vhierarchy_.node(_node_handle); + OpenMesh::Vec3f p = mesh_.point(node.vertex_handle()); + OpenMesh::Vec3f eye_dir = p - viewing_parameters_.eye_pos(); + float distance = eye_dir.length(); + float distance2 = distance * distance; + float product_value = dot(eye_dir, node.normal()); + + if (outside_view_frustum(p, node.radius()) == true) + return false; + + if (oriented_away(node.sin_square(), distance2, product_value) == true) + return false; + + if (screen_space_error(node.mue_square(), + node.sigma_square(), distance2, product_value) == true) + return false; + + return true; +} + + +void +VDPMClientViewerWidget:: +force_vsplit(VHierarchyNodeHandle node_handle) +{ + MyMesh::VertexHandle vl, vr; + + get_active_cuts(node_handle, vl, vr); + + while (vl == vr) { + force_vsplit(mesh_.data(vl).vhierarchy_node_handle()); + get_active_cuts(node_handle, vl, vr); + } + + vsplit(node_handle, vl, vr); +} + + + +void +VDPMClientViewerWidget:: +vsplit(VHierarchyNodeHandle _node_handle, MyMesh::VertexHandle vl, MyMesh::VertexHandle vr) +{ + // refine + VHierarchyNodeHandle lchild_handle = vhierarchy_.lchild_handle(_node_handle); + VHierarchyNodeHandle rchild_handle = vhierarchy_.rchild_handle(_node_handle); + MyMesh::VertexHandle v0 = vhierarchy_.vertex_handle(lchild_handle); + MyMesh::VertexHandle v1 = vhierarchy_.vertex_handle(rchild_handle); + + mesh_.vertex_split(v0, v1, vl, vr); + mesh_.set_normal(v0, vhierarchy_.normal(lchild_handle)); + mesh_.set_normal(v1, vhierarchy_.normal(rchild_handle)); + mesh_.data(v0).set_vhierarchy_node_handle(lchild_handle); + mesh_.data(v1).set_vhierarchy_node_handle(rchild_handle); + mesh_.status(v0).set_deleted(false); + mesh_.status(v1).set_deleted(false); + + vfront_.remove(_node_handle); + vfront_.add(lchild_handle); + vfront_.add(rchild_handle); +} + + +void +VDPMClientViewerWidget:: +ecol(VHierarchyNodeHandle _node_handle, const MyMesh::HalfedgeHandle& v0v1) +{ + VHierarchyNodeHandle lchild_handle = vhierarchy_.lchild_handle(_node_handle); + VHierarchyNodeHandle rchild_handle = vhierarchy_.rchild_handle(_node_handle); + MyMesh::VertexHandle v0 = vhierarchy_.vertex_handle(lchild_handle); + MyMesh::VertexHandle v1 = vhierarchy_.vertex_handle(rchild_handle); + + // coarsen + mesh_.collapse(v0v1); + mesh_.set_normal(v1, vhierarchy_.normal(_node_handle)); + mesh_.data(v0).set_vhierarchy_node_handle(lchild_handle); + mesh_.data(v1).set_vhierarchy_node_handle(_node_handle); + mesh_.status(v0).set_deleted(false); + mesh_.status(v1).set_deleted(false); + + vfront_.add(_node_handle); + vfront_.remove(lchild_handle); + vfront_.remove(rchild_handle); +} + + +bool +VDPMClientViewerWidget:: +ecol_legal(VHierarchyNodeHandle _parent_handle, MyMesh::HalfedgeHandle& v0v1) +{ + VHierarchyNodeHandle lchild_handle = vhierarchy_.lchild_handle(_parent_handle); + VHierarchyNodeHandle rchild_handle = vhierarchy_.rchild_handle(_parent_handle); + + // test whether lchild & rchild present in the current vfront + if (vfront_.is_active(lchild_handle) != true || vfront_.is_active(rchild_handle) != true) + return false; + + MyMesh::VertexHandle v0, v1; + v0 = vhierarchy_.vertex_handle(lchild_handle); + v1 = vhierarchy_.vertex_handle(rchild_handle); + v0v1 = mesh_.find_halfedge(v0, v1); + + return mesh_.is_collapse_ok(v0v1); +} + +void +VDPMClientViewerWidget:: +get_active_cuts(const VHierarchyNodeHandle _node_handle, MyMesh::VertexHandle &vl, MyMesh::VertexHandle &vr) +{ + MyMesh::VertexVertexIter vv_it; + VHierarchyNodeHandle nnode_handle; + VHierarchyNodeIndex nnode_index; + VHierarchyNodeIndex fund_lcut_index = vhierarchy_.fund_lcut_index(_node_handle); + VHierarchyNodeIndex fund_rcut_index = vhierarchy_.fund_rcut_index(_node_handle); + + vl = MyMesh::InvalidVertexHandle; + vr = MyMesh::InvalidVertexHandle; + + for (vv_it=mesh_.vv_iter(vhierarchy_.vertex_handle(_node_handle)); vv_it; ++vv_it) + { + nnode_handle = mesh_.data(vv_it.handle()).vhierarchy_node_handle(); + nnode_index = vhierarchy_.node_index(nnode_handle); + + if (vl == MyMesh::InvalidVertexHandle && vhierarchy_.is_ancestor(nnode_index, fund_lcut_index) == true) + vl = vv_it.handle(); + if (vr == MyMesh::InvalidVertexHandle && vhierarchy_.is_ancestor(nnode_index, fund_rcut_index) == true) + vr = vv_it.handle(); + + /*if (vl == MyMesh::InvalidVertexHandle && nnode_index.is_ancestor_index(fund_lcut_index) == true) + vl = vv_it.handle(); + if (vr == MyMesh::InvalidVertexHandle && nnode_index.is_ancestor_index(fund_rcut_index) == true) + vr = vv_it.handle();*/ + + if (vl != MyMesh::InvalidVertexHandle && vr != MyMesh::InvalidVertexHandle) + break; + } +} + +bool +VDPMClientViewerWidget:: +outside_view_frustum(const OpenMesh::Vec3f &pos, float radius) +{ + Plane3d frustum_plane[4]; + + viewing_parameters_.frustum_planes(frustum_plane); + + for (int i = 0; i < 4; i++) { + if (frustum_plane[i].signed_distance(pos) < -radius) + return true; + } + + return false; +} + +bool +VDPMClientViewerWidget:: +oriented_away(float sin_square, float distance_square, float product_value) +{ + if (product_value > 0 && product_value*product_value > distance_square * sin_square) + return true; + else + return false; +} + +bool +VDPMClientViewerWidget:: +screen_space_error(float mue_square, float sigma_square, float distance_square, float product_value) +{ + if ((mue_square >= kappa_square_ * distance_square) || + (sigma_square * (distance_square - product_value * product_value) >= kappa_square_ * distance_square * distance_square)) + return false; + else + return true; +} + +void +VDPMClientViewerWidget:: +open_vd_prog_mesh(const char* _filename) +{ + unsigned int i; + unsigned int value; + unsigned int fvi[3]; + char fileformat[16]; + OpenMesh::Vec3f p, normal; + float radius, sin_square, mue_square, sigma_square; + VHierarchyNodeHandleContainer roots; + OpenMesh::VertexHandle vertex_handle; + VHierarchyNodeIndex node_index, lchild_node_index, rchild_node_index, fund_lcut_index, fund_rcut_index; + VHierarchyNodeHandle node_handle, lchild_handle, rchild_handle; + std::map index2handle_map; + + std::ifstream ifs(_filename, std::ios::binary); + if (!ifs) + { + std::cerr << "read error\n"; + exit(1); + } + + // + bool swap = OpenMesh::Endian::local() != OpenMesh::Endian::LSB; + + // read header + ifs.read(fileformat, 10); fileformat[10] = '\0'; + if (std::string(fileformat) != std::string("VDProgMesh")) + { + std::cerr << "Wrong file format.\n"; + ifs.close(); + exit(1); + } + OpenMesh::IO::restore(ifs, n_base_vertices_, swap); + OpenMesh::IO::restore(ifs, n_base_faces_, swap); + OpenMesh::IO::restore(ifs, n_details_, swap); + + mesh_.clear(); + vfront_.clear(); + vhierarchy_.clear(); + + vhierarchy_.set_num_roots(n_base_vertices_); + + // load base mesh + for (i=0; i index2handle_map; + + std::ifstream ifs(_filename, std::ios::binary); + if (!ifs) + { + std::cerr << "Filename : " << _filename << std::endl; + std::cerr << "read error\n"; + exit(1); + } + + // + bool swap = OpenMesh::Endian::local() != OpenMesh::Endian::LSB; + + // read header + ifs.read(fileformat, 10); fileformat[10] = '\0'; + if (std::string(fileformat) != std::string("VDProgMesh")) + { + std::cerr << "Wrong file format.\n"; + ifs.close(); + exit(1); + } + OpenMesh::IO::restore(ifs, n_base_vertices_, swap); + OpenMesh::IO::restore(ifs, n_base_faces_, swap); + OpenMesh::IO::restore(ifs, n_details_, swap); + + mesh_.clear(); + vfront_.clear(); + vhierarchy_.clear(); + + vhierarchy_.set_num_roots(n_base_vertices_); + + // load base mesh + for (i=0; ikey()) + { + case Qt::Key_Plus: + viewing_parameters_.increase_tolerance(); + std::cout << "Scree-space error tolerance^2 is increased by " + << viewing_parameters_.tolerance_square() << std::endl; + updateGL(); + break; + + case Qt::Key_Minus: + viewing_parameters_.decrease_tolerance(); + std::cout << "Screen-space error tolerance^2 is decreased by " + << viewing_parameters_.tolerance_square() << std::endl; + updateGL(); + break; + + case Qt::Key_A: + adaptive_mode_ = !(adaptive_mode_); + std::cout << "Adaptive refinement mode is " + << ((adaptive_mode_ == true) ? "on" : "off") << std::endl; + updateGL(); + break; + + case Qt::Key_D: + set_debug_print(!debug_print()); + break; + + case Qt::Key_O: + qFilename_ = QFileDialog::getOpenFileName(0,"","d:/data/models/spm/", "*.spm"); + open_vd_base_mesh( qFilename_.toStdString().c_str() ); + break; + + case Qt::Key_BracketLeft: + max_transmitted_datasize_ -= 10000; + std::cout << "Max transmitted data: " << max_transmitted_datasize_ << std::endl; + break; + + case Qt::Key_BracketRight: + max_transmitted_datasize_ += 10000; + std::cout << "Max transmitted data: " << max_transmitted_datasize_ << std::endl; + break; + + case Qt::Key_Space: + memcpy(reserved_modelview_matrix_, modelview_matrix(), 16*sizeof(GLdouble)); + memcpy(reserved_projection_matrix_, projection_matrix(), 16*sizeof(GLdouble)); + std::cout << "Reserving current view-point" << std::endl; + break; + + case Qt::Key_R: + request_base_mesh(); + break; + + case Qt::Key_S: + save_views(); + std::cout << "Saving view-points" << std::endl; + break; + + case Qt::Key_F: + frame_ = 0; + std::cout << "Frame is set to 0" << std::endl; + break; + + case Qt::Key_M: + adaptive_mode_ = false; + current_max_resolution(); + updateGL(); + std::cout << "Current max resolution mesh" << std::endl; + break; + + case Qt::Key_V: + vd_streaming_ = !(vd_streaming_); + if (vd_streaming_) + std::cout << "View-dependent streaing mode" << std::endl; + else + std::cout << "Sequential streaming mode" << std::endl; + break; + + case Qt::Key_C: + adaptive_mode_ = false; + qCameraFileName_ = QFileDialog::getOpenFileName(0, "","./", "*.cmr"); + load_views( qCameraFileName_.toStdString().c_str() ); + std::cout << "Loading view-points" << std::endl; + updateGL(); + break; + + case Qt::Key_9: + save_screen(true); + break; + + case Qt::Key_0: + std::cout << "#faces: " << mesh_.n_faces() << std::endl; + break; + + case Qt::Key_P: + if (qAnimationTimer_->isActive()) + { + qAnimationTimer_->stop(); + std::cout << "print_statistics mode is stopped!" << std::endl; + } + else + { + qAnimationTimer_->setSingleShot( true ); + qAnimationTimer_->start(0); + std::cout << "print_statistics mode is started!" << std::endl; + + adaptive_mode_ = true; + + set_scene_pos( + Vec3f(0.5f*(bbMin_[0] + bbMax_[0]), 0.9f*bbMax_[1], 0.5f*(bbMin_[2] + bbMax_[2])), + 0.15f*(bbMin_ - bbMax_).norm()); + nth_viewpoint_ = 0; + print_statistics(); + } + std::cout << "Frame: " << frame_ << std::endl; + break; + + + case Qt::Key_L: + if (qAnimationTimer_->isActive()) + { + qAnimationTimer_->stop(); + std::cout << "look_around mode is stopped!" << std::endl; + } + else + { + qAnimationTimer_->setSingleShot( true ); + qAnimationTimer_->start(0); + std::cout << "look_around mode is started!" << std::endl; + + adaptive_mode_ = true; + + set_scene_pos( + Vec3f(0.5f*(bbMin_[0] + bbMax_[0]), 0.9f*bbMax_[1], 0.5f*(bbMin_[2] + bbMax_[2])), + 0.15f*(bbMin_ - bbMax_).norm()); + frame_ = 0; + nth_viewpoint_ = 0; + look_around(); + } + + break; + + case Qt::Key_Q: + case Qt::Key_Escape: + qApp->quit(); + + default: + this->MeshViewerWidget::keyPressEvent( _event ); + } + + if (!handled) + _event->ignore(); +} + + + + + +void +VDPMClientViewerWidget:: +update_viewing_parameters() +{ + viewing_parameters_.set_fovy(fovy()); + viewing_parameters_.set_aspect((float) width() / (float) height()); + viewing_parameters_.set_modelview_matrix(modelview_matrix()); + + viewing_parameters_.update_viewing_configurations(); +} + + +///////////////////////////////////////////////// +// streaming related functions +///////////////////////////////////////////////// + + + +bool +VDPMClientViewerWidget:: +request_base_mesh() +{ + if (streaming_phase_ != kBaseMesh) + return false; + + if (qFilename_.isEmpty() == true) + { + std::cout << "Please, specify the base mesh filename." << std::endl; + return false; + } + + QDataStream qTcp(qSocket_); + + qTcp << qFilename_.length(); + qTcp << qFilename_; + qSocket_->flush(); + + return true; +} + +bool +VDPMClientViewerWidget:: +receive_base_mesh() +{ + int status; + QDataStream qTcp(qSocket_); + + while ( qSocket_->bytesAvailable() < sizeof(int) ) + qSocket_->waitForReadyRead(10); + + qTcp >> status; + if (status == 0) + { + std::cout << "There is no such a VDPM files in the server side." << std::endl; + return false; + } + + streaming_phase_ = kVSplitHeader; + + std::cout << "A view-dependent streaming is ready." << std::endl; + return true; +} + + +void +VDPMClientViewerWidget:: +send_viewing_information() +{ + session_timer_.start(); + QDataStream qTCP(qSocket_); + qTCP << modelview_matrix()[0] << modelview_matrix()[1] + << modelview_matrix()[2] << modelview_matrix()[3] + << modelview_matrix()[4] << modelview_matrix()[5] + << modelview_matrix()[6] << modelview_matrix()[7] + << modelview_matrix()[8] << modelview_matrix()[9] + << modelview_matrix()[10] << modelview_matrix()[11] + << modelview_matrix()[12] << modelview_matrix()[13] + << modelview_matrix()[14] << modelview_matrix()[15] + << viewing_parameters_.fovy() + << viewing_parameters_.aspect() + << viewing_parameters_.tolerance_square(); + + qSocket_->flush(); + session_timer_.stop(); + fprintf(session_file, "%d %d\n", frame_, (int) session_timer_.mseconds()); + + + global_timer_.stop(); + fprintf(uplink_file, "%d %ld\n", (int) global_timer_.mseconds(), 16*sizeof(double) + 3*sizeof(float)); + global_timer_.cont(); +} + +void +VDPMClientViewerWidget:: +receive_vsplit_header() +{ + if (qSocket_->bytesAvailable() < sizeof(unsigned int)) + return; + + QDataStream qTcp(qSocket_); + + // while (qSocket_->waitForMore(10) < sizeof(unsigned int)); + + qTcp >> n_vsplit_packets_; + + if (n_vsplit_packets_ > 0) + { + streaming_phase_ = kVSplits; + + if (debug_print() == true) + { + std::cout << "Server will transmit " << n_vsplit_packets_ + << " of vsplit packets to me" << std::endl; + } + + receive_vsplit_packets(); + } + else + { + session_running_ = false; + } +} + +void +VDPMClientViewerWidget:: +receive_vsplit_packets() +{ + static unsigned int n_vsplits = 0; + static unsigned int len = (int) (17 * sizeof(float) + 3 * sizeof(int)); + + if (qSocket_->bytesAvailable() < len) + return; + + QString str; + OpenMesh::Vec3f pos; + VHierarchyNodeIndex node_index, fund_lcut_index, fund_rcut_index; + float radius[2]; + OpenMesh::Vec3f normal[2]; + float sin_square[2]; + float mue_square[2]; + float sigma_square[2]; + unsigned int value[3]; + + global_timer_.stop(); + fprintf(downlink_file, "%d %ld\n", (int) global_timer_.mseconds(), qSocket_->bytesAvailable()); + global_timer_.cont(); + + session_timer_.start(); + + while ( qSocket_->bytesAvailable() >= len ) + { + if (vd_streaming_) transmitted_datasize_ += (int) len; + //if (vd_streaming_) transmitted_datasize_ += (int) 3*sizeof(int) + 3*sizeof(float); // only for non-refinement cliet + else transmitted_datasize_ += (int) 3*sizeof(int) + 3*sizeof(float); + + if (max_transmitted_datasize_ > 0) + { + if (transmitted_datasize_ > max_transmitted_datasize_) + { + if (vd_streaming_) transmitted_datasize_ -= (int) len; + //if (vd_streaming_) transmitted_datasize_ -= (int) 3*sizeof(int) + 3*sizeof(float); // only for non-refinement cliet + else transmitted_datasize_ -= (int) 3*sizeof(int) + 3*sizeof(float); + + return; + } + } + + QDataStream qTcp(qSocket_); + qTcp >> pos[0] >> pos[1] >> pos[2] + >> value[0] + >> value[1] + >> value[2] + >> radius[0] + >> (normal[0])[0] >> (normal[0])[1] >> (normal[0])[2] + >> sin_square[0] + >> mue_square[0] >> sigma_square[0] + >> radius[1] + >> (normal[1])[0] >> (normal[1])[1] >> (normal[1])[2] + >> sin_square[1] + >> mue_square[1] >> sigma_square[1]; + + node_index = VHierarchyNodeIndex(value[0]); + fund_lcut_index = VHierarchyNodeIndex(value[1]); + fund_rcut_index = VHierarchyNodeIndex(value[2]); + + update_vhierarchy(pos, + node_index, fund_lcut_index, fund_rcut_index, + radius, normal, sin_square, mue_square, sigma_square); + + + std::cout << "transmitted datasize: " << transmitted_datasize_ << std::endl; + + if (debug_print() == true) + { + std::cout << "Pkg #" << n_vsplits << std::endl; + } + + ++n_vsplits; + + if (n_vsplits >= n_vsplit_packets_) + { + n_vsplits = 0; + streaming_phase_ = kVSplitHeader; + session_running_ = false; + + if (debug_print() == true) + { + std::cout << "transmission of vsplit packets is complete" << std::endl; + } + break; + } + } + + session_timer_.stop(); + fprintf(session_file, "%d %d\n", frame_, (int) session_timer_.mseconds()); + + updateGL(); + + if (n_vsplits != n_vsplit_packets_){ + qSessionTimer_->setSingleShot( true ); + qSessionTimer_->start(300); + } +} + + +void +VDPMClientViewerWidget:: +update_vhierarchy( + const OpenMesh::Vec3f &_pos, // 3D position of v0 + const VHierarchyNodeIndex &_node_index, // vhierarchy index of v1 + const VHierarchyNodeIndex &_fund_lcut_index, // vhierarchy index of fundamental lcut + const VHierarchyNodeIndex &_fund_rcut_index, // vhierarchy index of fundamental rcut + const float _radius[2], // radius of lchild & rchild + const OpenMesh::Vec3f _normal[2], // normal of lchild & rchild + const float _sin_square[2], // sin_square of lchild & rchild + const float _mue_square[2], // mue_square of lchild & rchild + const float _sigma_square[2] // sigma_square of lchild & rchild + ) +{ + OpenMesh::VertexHandle vertex_handle; + VHierarchyNodeHandle node_handle, lchild_handle, rchild_handle; + + node_handle = vhierarchy_.node_handle(_node_index); + vhierarchy_.make_children(node_handle); + + + lchild_handle = vhierarchy_.lchild_handle(node_handle); + rchild_handle = vhierarchy_.rchild_handle(node_handle); + + vhierarchy_.node(node_handle).set_fund_lcut(_fund_lcut_index); + vhierarchy_.node(node_handle).set_fund_rcut(_fund_rcut_index); + + vertex_handle = mesh_.add_vertex(_pos); + vhierarchy_.node(lchild_handle).set_vertex_handle(vertex_handle); + vhierarchy_.node(rchild_handle).set_vertex_handle(vhierarchy_.node(node_handle).vertex_handle()); + + vhierarchy_.node(lchild_handle).set_radius(_radius[0]); + vhierarchy_.node(lchild_handle).set_normal(_normal[0]); + vhierarchy_.node(lchild_handle).set_sin_square(_sin_square[0]); + vhierarchy_.node(lchild_handle).set_mue_square(_mue_square[0]); + vhierarchy_.node(lchild_handle).set_sigma_square(_sigma_square[0]); + + vhierarchy_.node(rchild_handle).set_radius(_radius[1]); + vhierarchy_.node(rchild_handle).set_normal(_normal[1]); + vhierarchy_.node(rchild_handle).set_sin_square(_sin_square[1]); + vhierarchy_.node(rchild_handle).set_mue_square(_mue_square[1]); + vhierarchy_.node(rchild_handle).set_sigma_square(_sigma_square[1]); + +#ifdef EXAMPLE_CREATION + __add_children(_node_index); +#endif +} + + + +///////////////////////////////////////////////// +// example related functions +///////////////////////////////////////////////// + +void VDPMClientViewerWidget::save_views() +{ + FILE *camera_file = fopen("camera.cmr", "w"); + + GLdouble current_modelview_matrix[16], current_projection_matrix[16]; + + memcpy(current_modelview_matrix, modelview_matrix(), 16*sizeof(GLdouble)); + memcpy(current_projection_matrix, projection_matrix(), 16*sizeof(GLdouble)); + + + fprintf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + current_modelview_matrix[0], current_modelview_matrix[1], current_modelview_matrix[2], current_modelview_matrix[3], + current_modelview_matrix[4], current_modelview_matrix[5], current_modelview_matrix[6], current_modelview_matrix[7], + current_modelview_matrix[8], current_modelview_matrix[9], current_modelview_matrix[10], current_modelview_matrix[11], + current_modelview_matrix[12], current_modelview_matrix[13], current_modelview_matrix[14], current_modelview_matrix[15]); + + fprintf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + current_projection_matrix[0], current_projection_matrix[1], current_projection_matrix[2], current_projection_matrix[3], + current_projection_matrix[4], current_projection_matrix[5], current_projection_matrix[6], current_projection_matrix[7], + current_projection_matrix[8], current_projection_matrix[9], current_projection_matrix[10], current_projection_matrix[11], + current_projection_matrix[12], current_projection_matrix[13], current_projection_matrix[14], current_projection_matrix[15]); + + + fprintf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + reserved_modelview_matrix_[0], reserved_modelview_matrix_[1], reserved_modelview_matrix_[2], reserved_modelview_matrix_[3], + reserved_modelview_matrix_[4], reserved_modelview_matrix_[5], reserved_modelview_matrix_[6], reserved_modelview_matrix_[7], + reserved_modelview_matrix_[8], reserved_modelview_matrix_[9], reserved_modelview_matrix_[10], reserved_modelview_matrix_[11], + reserved_modelview_matrix_[12], reserved_modelview_matrix_[13], reserved_modelview_matrix_[14], reserved_modelview_matrix_[15]); + + fprintf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + reserved_projection_matrix_[0], reserved_projection_matrix_[1], reserved_projection_matrix_[2], reserved_projection_matrix_[3], + reserved_projection_matrix_[4], reserved_projection_matrix_[5], reserved_projection_matrix_[6], reserved_projection_matrix_[7], + reserved_projection_matrix_[8], reserved_projection_matrix_[9], reserved_projection_matrix_[10], reserved_projection_matrix_[11], + reserved_projection_matrix_[12], reserved_projection_matrix_[13], reserved_projection_matrix_[14], reserved_projection_matrix_[15]); + + fclose(camera_file); +} + + +void VDPMClientViewerWidget::load_views(const char *camera_filename) +{ + FILE *camera_file = fopen(camera_filename, "r"); + + GLdouble current_modelview_matrix[16], current_projection_matrix[16]; + + + fscanf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + &(current_modelview_matrix[0]), &(current_modelview_matrix[1]), &(current_modelview_matrix[2]), &(current_modelview_matrix[3]), + &(current_modelview_matrix[4]), &(current_modelview_matrix[5]), &(current_modelview_matrix[6]), &(current_modelview_matrix[7]), + &(current_modelview_matrix[8]), &(current_modelview_matrix[9]), &(current_modelview_matrix[10]), &(current_modelview_matrix[11]), + &(current_modelview_matrix[12]), &(current_modelview_matrix[13]), &(current_modelview_matrix[14]), &(current_modelview_matrix[15])); + + + fscanf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + &(current_projection_matrix[0]), &(current_projection_matrix[1]), &(current_projection_matrix[2]), &(current_projection_matrix[3]), + &(current_projection_matrix[4]), &(current_projection_matrix[5]), &(current_projection_matrix[6]), &(current_projection_matrix[7]), + &(current_projection_matrix[8]), &(current_projection_matrix[9]), &(current_projection_matrix[10]), &(current_projection_matrix[11]), + &(current_projection_matrix[12]), &(current_projection_matrix[13]), &(current_projection_matrix[14]), &(current_projection_matrix[15])); + + + fscanf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + &(reserved_modelview_matrix_[0]), &(reserved_modelview_matrix_[1]), &(reserved_modelview_matrix_[2]), &(reserved_modelview_matrix_[3]), + &(reserved_modelview_matrix_[4]), &(reserved_modelview_matrix_[5]), &(reserved_modelview_matrix_[6]), &(reserved_modelview_matrix_[7]), + &(reserved_modelview_matrix_[8]), &(reserved_modelview_matrix_[9]), &(reserved_modelview_matrix_[10]), &(reserved_modelview_matrix_[11]), + &(reserved_modelview_matrix_[12]), &(reserved_modelview_matrix_[13]), &(reserved_modelview_matrix_[14]), &(reserved_modelview_matrix_[15])); + + + fscanf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + &(reserved_projection_matrix_[0]), &(reserved_projection_matrix_[1]), &(reserved_projection_matrix_[2]), &(reserved_projection_matrix_[3]), + &(reserved_projection_matrix_[4]), &(reserved_projection_matrix_[5]), &(reserved_projection_matrix_[6]), &(reserved_projection_matrix_[7]), + &(reserved_projection_matrix_[8]), &(reserved_projection_matrix_[9]), &(reserved_projection_matrix_[10]), &(reserved_projection_matrix_[11]), + &(reserved_projection_matrix_[12]), &(reserved_projection_matrix_[13]), &(reserved_projection_matrix_[14]), &(reserved_projection_matrix_[15])); + + fclose(camera_file); + + set_modelview_matrix(current_modelview_matrix); + set_projection_matrix(current_projection_matrix); + + adaptive_mode_ = false; +} + +void VDPMClientViewerWidget::print_statistics() +{ + const float angle = 360.0/(float)n_viewpoints_; + Vec3f axis = Vec3f(0,1,0); + Vec3f delta = Vec3f(0, 0.7f*(bbMin_[1] - bbMax_[1])/n_viewpoints_, 0); + + rotate(axis, -angle); + set_scene_pos(center() + delta, 1.0f * radius() ); + + updateGL(); + + if (++nth_viewpoint_ < n_viewpoints_){ + qAnimationTimer_->setSingleShot( true ); + qAnimationTimer_->start(500); + } +} + +void VDPMClientViewerWidget::look_around() +{ + const float angle = 360.0/(float)n_viewpoints_; + Vec3f axis = Vec3f(0,1,0); + Vec3f delta = Vec3f(0, 0.7f*(bbMin_[1] - bbMax_[1])/n_viewpoints_, 0); + + rotate(axis, -angle); + set_scene_pos(center() + delta, 1.0f * radius() ); + + updateGL(); + + save_screen(true); + + if (++nth_viewpoint_ < n_viewpoints_){ + qAnimationTimer_->setSingleShot( true ); + qAnimationTimer_->start(3000); + } +} + + +void VDPMClientViewerWidget::save_screen(bool _flag) +{ + setCursor( Qt::WaitCursor ); + + if (_flag == true) // shot from the reserved view-point + { + GLdouble current_modelview_matrix[16]; + GLdouble current_projection_matrix[16]; + bool current_adaptive_mode = adaptive_mode_; + + memcpy(current_modelview_matrix, modelview_matrix(), 16*sizeof(GLdouble)); + memcpy(current_projection_matrix, projection_matrix(), 16*sizeof(GLdouble)); + + set_modelview_matrix(reserved_modelview_matrix_); + set_projection_matrix(reserved_projection_matrix_); + adaptive_mode_ = false; + + updateGL(); + + // shot from the reserved view-point + char rfilename[256]; + sprintf(rfilename, "rview%03d.bmp", nth_viewpoint_); + screen_capture(rfilename); + std::cout << "shot from the reserved view-point" << std::endl; + + + set_modelview_matrix(current_modelview_matrix); + set_projection_matrix(current_projection_matrix); + adaptive_mode_ = current_adaptive_mode; + } + + updateGL(); + + // shot from the current view-point + char cfilename[256]; + sprintf(cfilename, "cview%03d.bmp", nth_viewpoint_); + screen_capture(cfilename); + std::cout << "shot from the current view-point" << std::endl; + + + setCursor( Qt::PointingHandCursor ); +} + +void VDPMClientViewerWidget::screen_capture(const char * /* _filename */) +{ +// CImageData image(width(), height()); + +// glReadBuffer(GL_BACK); +// glReadPixels(0, 0, width(), height(), GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) image.rgbMap()); + +// image.SaveBMP(_filename, width(), height()); +} + diff --git a/Apps/Unsupported/Streaming-qt4/Client/VDPMClientViewerWidget.hh b/Apps/Unsupported/Streaming-qt4/Client/VDPMClientViewerWidget.hh new file mode 100644 index 0000000000000000000000000000000000000000..04a0741ddbebfe4bd89e41aa109b476824be71d2 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Client/VDPMClientViewerWidget.hh @@ -0,0 +1,320 @@ +#ifndef OPENMESH_APPS_VDPMSTREAMING_CLIENT_VDPMCLIENTVIEWERWIDGET_HH +#define OPENMESH_APPS_VDPMSTREAMING_CLIENT_VDPMCLIENTVIEWERWIDGET_HH + +//== INCLUDES ================================================================= + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +//#include + + + +typedef MeshViewerWidgetT MeshViewerWidget; + + + +using OpenMesh::VDPM::VDPMStreamingPhase; +using OpenMesh::VDPM::kVSplitHeader; +using OpenMesh::VDPM::kVSplits; +using OpenMesh::VDPM::kBaseMesh; + +using OpenMesh::VDPM::Plane3d; + +using OpenMesh::VDPM::VFront; +using OpenMesh::VDPM::VHierarchy; +using OpenMesh::VDPM::VHierarchyNodeIndex; +using OpenMesh::VDPM::VHierarchyNodeHandle; +using OpenMesh::VDPM::ViewingParameters; +using OpenMesh::VDPM::set_debug_print; + + +//== CLASS DEFINITION ========================================================= + + +class VDPMClientViewerWidget : public MeshViewerWidget +{ + + Q_OBJECT + +public: + VDPMClientViewerWidget(QWidget *_parent=0, const char *_name=0) + : MeshViewerWidget(_parent, _name) + { + set_debug_print(true); + adaptive_mode_ = false; + + qSessionTimer_ = new QTimer(this); + qSocket_ = new QTcpSocket(this); + streaming_phase_ = kBaseMesh; + session_running_ = false; + + + connect(qSessionTimer_, SIGNAL(timeout()), + this, SLOT(session_timer_check())); + + connect(qSessionTimer_, SIGNAL(timeout()), + this, SLOT(socketReadyRead())); + + // connect signal-slots about QSocket + connect(qSocket_, SIGNAL(connected()), + this, SLOT(socketConnected())); + + connect(qSocket_, SIGNAL(connectionClosed()), + this, SLOT(socketConnectionClosed())); + + connect(qSocket_, SIGNAL(readyRead()), + this, SLOT(socketReadyRead())); + + connect(qSocket_, SIGNAL(error( QAbstractSocket::SocketError )), + this, SLOT(socketError( QAbstractSocket::SocketError ))); + + + look_around_mode_ = false; + frame_ = 0; + n_viewpoints_ = 60; + + global_timer_.reset(); + global_timer_.start(); + render_timer_.reset(); + refinement_timer_.reset(); + session_timer_.reset(); + + qAnimationTimer_ = new QTimer(this); + + connect(qAnimationTimer_, SIGNAL(timeout()), + this, SLOT(look_around())); + //connect(qAnimationTimer_, SIGNAL(timeout()), + // this, SLOT(print_statistics())); + + + uplink_file = fopen("uplink.txt", "w"); + downlink_file = fopen("downlink.txt", "w"); + + render_file = fopen("render.txt", "w"); + refinement_file = fopen("refinement.txt", "w"); + session_file = fopen("session.txt", "w"); + + vd_streaming_ = true; + max_transmitted_datasize_ = 0; + transmitted_datasize_ = 0; + } + + ~VDPMClientViewerWidget() + { + fclose(uplink_file); + fclose(downlink_file); + + fclose(render_file); + fclose(refinement_file); + fclose(session_file); + } + + + void connectToServer( std::string& _server_name, + int _port= VDPM_STREAMING_PORT ) + { + qSocket_->connectToHost( _server_name.c_str(), _port ); + } + + void openBaseMesh( std::string& _base_mesh ) + { + open_vd_base_mesh( _base_mesh.c_str() ); + std::cout << "spm file: " << _base_mesh << std::endl; + } + +// socket related slots +private slots: + + void closeConnection() + { + close(); + if (qSocket_->state() == QAbstractSocket::ClosingState) // we have a delayed close. + { + connect(this, SIGNAL(delayedCloseFinished()), SLOT(socketClosed())); + } + else // the qSocket is closed. + { + socketClosed(); + } + } + + void socketReadyRead() + { + switch( streaming_phase_) + { + case kVSplits: receive_vsplit_packets(); break; + case kVSplitHeader: receive_vsplit_header(); break; + case kBaseMesh: receive_base_mesh(); break; + } + + } + + void socketConnected() + { + std::cout << "Connected to server" << std::endl; + } + + void socketConnectionClosed() + { + std::cout << "Connection closed by the server" << std::endl; + } + + void socketClosed() + { + std::cout << "Connection closed" << std::endl; + } + + void socketError(QAbstractSocket::SocketError e) + { + std::cout << "Error number " << e << " occurred" << std::endl; + } + + void look_around(); + void print_statistics(); + + + void session_timer_check() + { + std::cout << "Session Timer works" << std::endl; + } + +// for view-dependent PM +private: + VHierarchy vhierarchy_; + //unsigned char tree_id_bits_; + VFront vfront_; + ViewingParameters viewing_parameters_; + float kappa_square_; + bool adaptive_mode_; + + unsigned int n_base_vertices_; + unsigned int n_base_edges_; + unsigned int n_base_faces_; + unsigned int n_details_; + +private: + + bool outside_view_frustum(const OpenMesh::Vec3f &pos, float radius); + bool oriented_away(float sin_square, float distance_square, + float product_value); + bool screen_space_error(float mue_square, float sigma_square, + float distance_square, float product_value); + void update_viewing_parameters(); + + virtual void keyPressEvent(QKeyEvent *_event); + +protected: + + /// inherited drawing method + virtual void draw_scene(const std::string& _draw_mode); + + +public: + + void open_vd_prog_mesh(const char* _filename); + + unsigned int num_base_vertices() const { return n_base_vertices_; } + unsigned int num_base_edges() const { return n_base_edges_; } + unsigned int num_base_faces() const { return n_base_faces_; } + unsigned int num_details() const { return n_details_; } + + void adaptive_refinement(); + bool qrefine(VHierarchyNodeHandle _node_handle); + void force_vsplit(VHierarchyNodeHandle _node_handle); + bool ecol_legal(VHierarchyNodeHandle _parent_handle, MyMesh::HalfedgeHandle& v0v1); + + void get_active_cuts(VHierarchyNodeHandle _node_handle, MyMesh::VertexHandle &vl, MyMesh::VertexHandle &vr); + void vsplit(VHierarchyNodeHandle _node_handle, MyMesh::VertexHandle vl, MyMesh::VertexHandle vr); + void ecol(VHierarchyNodeHandle _parent_handle, const MyMesh::HalfedgeHandle& v0v1); + + void init_vfront(); + + // streaming realted functions +private: + QTimer *qSessionTimer_; + QTcpSocket *qSocket_; + QString qFilename_; + bool session_running_; + VDPMStreamingPhase streaming_phase_; + unsigned int n_vsplit_packets_; + +public: + void connect_to_server(); + bool request_base_mesh(); + bool receive_base_mesh(); + void send_viewing_information(); + void receive_vsplit_header(); + void receive_vsplit_packets(); + void open_vd_base_mesh(const char* _filename); + void update_vhierarchy( + const OpenMesh::Vec3f &_pos, // 3D position of v0 + const VHierarchyNodeIndex &_v, // vhierarchy index of v1 + const VHierarchyNodeIndex &_fund_lcut_index, // vhierarchy index of fundamental lcut + const VHierarchyNodeIndex &_fund_rcut_index, // vhierarchy index of fundamental rcut + const float _radius[2], // radius of lchild & rchild + const OpenMesh::Vec3f _normal[2], // normal of lchild & rchild + const float _sin_square[2], // sin_square of lchild & rchild + const float _mue_square[2], // mue_square of lchild & rchild + const float _sigma_square[2] // sigma_square of lchild & rchild + ); + + + // for example +private: + QTimer *qAnimationTimer_; + QString qCameraFileName_; + MyMesh::Point bbMin_, bbMax_; + unsigned int frame_; + int max_transmitted_datasize_; + int transmitted_datasize_; + bool vd_streaming_; + + unsigned int nth_viewpoint_; + unsigned int n_viewpoints_; + bool look_around_mode_; + GLdouble reserved_modelview_matrix_[16]; + GLdouble reserved_projection_matrix_[16]; + + FILE *uplink_file; + FILE *downlink_file; + FILE *render_file; + FILE *refinement_file; + FILE *session_file; + +public: + void save_screen(bool _flag); + void save_views(); + void load_views(const char *camera_filename); + void screen_capture(const char *_filename); + void current_max_resolution(); + + OpenMesh::Utils::Timer global_timer_; + OpenMesh::Utils::Timer render_timer_; + OpenMesh::Utils::Timer refinement_timer_; + OpenMesh::Utils::Timer session_timer_; + + + +#ifdef EXAMPLE_CREATION + void increase_max_descendents(const VHierarchyNodeIndex &node_index); + void increase_cur_descendents(VHierarchyNodeHandle _node_handle); + void __add_children(const VHierarchyNodeIndex &node_index, bool update_current = true); + void mesh_coloring(); +#endif +}; + +#endif //OPENMESH_APPS_VDPMSTREAMING_CLIENT_VDPMCLIENTVIEWERWIDGET_HH defined diff --git a/Apps/Unsupported/Streaming-qt4/Client/VDPMStreamingClient.cc b/Apps/Unsupported/Streaming-qt4/Client/VDPMStreamingClient.cc new file mode 100644 index 0000000000000000000000000000000000000000..04d87370afbe86e2998e569575f1c66d79e02b14 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Client/VDPMStreamingClient.cc @@ -0,0 +1,72 @@ +// #ifdef _MSC_VER +// # pragma warning(disable: 4267 4311) +// #endif + +#include +#include + +#include + +//#include +#include +//#include +//#include + +#include +#include +#include + + +int main(int argc, char **argv) +{ + // OpenGL check + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication app(argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + std::cerr << "This system has no OpenGL support.\n"; + return -1; + } + + // + int c; + int port = -1; + std::string bmesh = ""; + std::string sname = "localhost"; + + while ( (c=getopt(argc, argv, "b:p:s:"))!=-1 ) + { + switch(c) + { + case 'b': bmesh = optarg; break; + case 's': sname = optarg; break; + case 'p': { std::istringstream istr(optarg); istr >> port; } break; + } + } + + // create widget + VDPMClientViewerWidget* w = + new VDPMClientViewerWidget(0, "VDPMClientViewer"); + + if (port == -1) + w->connectToServer( sname ); + else + w->connectToServer( sname, port ); + + w->resize(800, 800); +// app.setMainWidget(w); + w->show(); + + w->openBaseMesh( bmesh ); + + // print usage info + std::cout << "\n\n" + << "Press Minus : Coarsen mesh\n" + << " Plus : Refine mesh\n" + << " Home : Coarsen down to base mesh\n" + << " End : Refine up to finest mesh\n" + << "\n"; + + return app.exec(); +} + diff --git a/Apps/Unsupported/Streaming-qt4/Client/camera.cmr b/Apps/Unsupported/Streaming-qt4/Client/camera.cmr new file mode 100644 index 0000000000000000000000000000000000000000..7e58ad921668204b2cea40587676775678a8383e --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Client/camera.cmr @@ -0,0 +1,4 @@ +1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.016996 -0.109919 -0.370638 1.000000 +2.414214 0.000000 0.000000 0.000000 0.000000 2.414214 0.000000 0.000000 0.000000 0.000000 -1.000200 -1.000000 0.000000 0.000000 -0.002487 0.000000 +0.000000 1.000000 0.000000 176744288671350421565538919745292424325033476751523693228169963004884932940091916749086946235466103001193375847224942690972512534721986560.000000 0.000000 nan 425134321045072769729657674081032044702092994459323810191320335465371399515446481741965189098676184821816460416151892487150071042707962836116024422753449790030954505984610613125759424311663740707690994610961772976644207938664290688788945427521964959221153792.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 +0.000000 0.000000 0.000000 1.000000 0.000000 43138399251230245763880957247161123402511258100486738812232497009688599814651595596323661983776768.000000 0.000000 nan 56217166495396395288300850038172311276865324027010017909696113739489719293525015037327494588529843730643950329227434086235241736485385775424471015442015055292454325203222134784.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 diff --git a/Apps/Unsupported/Streaming-qt4/Server/ACGMakefile b/Apps/Unsupported/Streaming-qt4/Server/ACGMakefile new file mode 100644 index 0000000000000000000000000000000000000000..4be1fea8f13521653cde6f552aef216b987b5e6a --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Server/ACGMakefile @@ -0,0 +1,18 @@ +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Config +#============================================================================== + +CXX_CFLAGS += -DQT_THREAD_SUPPORT + +SUBDIRS = $(call find-subdirs) + +PACKAGES := qt4 glut opengl + +PROJ_LIBS := OpenMesh/Core OpenMesh/Tools + +MODULES := moc4 cxx + + +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Rules +#============================================================================== diff --git a/Apps/Unsupported/Streaming-qt4/Server/ServerSideVDPM.cc b/Apps/Unsupported/Streaming-qt4/Server/ServerSideVDPM.cc new file mode 100644 index 0000000000000000000000000000000000000000..12e4b97553ba5b410c0ba89b6384f1945b1411ae --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Server/ServerSideVDPM.cc @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include +#include +#include "ServerSideVDPM.hh" + + +using OpenMesh::VDPM::VHierarchyNode; +using OpenMesh::VDPM::VHierarchyNodeIndex; +using OpenMesh::VDPM::VHierarchyNodeHandle; + + +void +ServerSideVDPM:: +clear() +{ + points_.clear(); + triangles_.clear(); + vhierarchy_.clear(); + + n_base_vertices_ = 0; + n_base_faces_ = 0; + n_details_ = 0; +} + +OpenMesh::VertexHandle +ServerSideVDPM:: +add_vertex(const OpenMesh::Vec3f &p) +{ + points_.push_back(p); + + return OpenMesh::VertexHandle(points_.size() - 1); +} + +OpenMesh::FaceHandle +ServerSideVDPM:: +add_face(const unsigned int _triangle[3]) +{ + OpenMesh::Vec3ui fvi; + + fvi[0] = _triangle[0]; + fvi[1] = _triangle[1]; + fvi[2] = _triangle[2]; + + triangles_.push_back(fvi); + + return OpenMesh::FaceHandle(triangles_.size() - 1); +} + + +void +ServerSideVDPM:: +vhierarchy_roots(VHierarchyNodeHandleContainer &roots) const +{ + unsigned int i; + + roots.clear(); + + for (i=0; i index2handle_map; + + std::ifstream ifs(_filename, std::ios::binary); + if (!ifs) + { + std::cerr << "read error\n"; + return false; + } + + // + bool swap = OpenMesh::Endian::local() != OpenMesh::Endian::LSB; + + // read header + ifs.read(fileformat, 10); fileformat[10] = '\0'; + if (std::string(fileformat) != std::string("VDProgMesh")) + { + std::cerr << "Wrong file format.\n"; + ifs.close(); + return false; + } + + clear(); + + OpenMesh::IO::restore(ifs, n_base_vertices_, swap); + OpenMesh::IO::restore(ifs, n_base_faces_, swap); + OpenMesh::IO::restore(ifs, n_details_, swap); + + // update tree_id_bits_ + vhierarchy_.set_num_roots(n_base_vertices_); + + + // read base_mesh + for (i=0; i +#include +#include +#include +#include + + +using OpenMesh::VDPM::VHierarchy; +using OpenMesh::VDPM::VHierarchyNodeHandleContainer; + + +class ServerSideVDPM +{ +private: + + char name_[256]; + + std::vector points_; // points related to this pm + std::vector triangles_; // base mesh triangles + VHierarchy vhierarchy_; + + unsigned int n_base_vertices_; + unsigned int n_base_faces_; + unsigned int n_details_; + unsigned char tree_id_bits_; + +public: + + ServerSideVDPM() { clear(); } + void clear(); + + const char* name() const { return name_; } + + void get_name(char _name[256]) { strcpy(_name, name_); } + void set_name(const char _name[256]) { strcpy(name_, _name); } + + + std::string + basename(const std::string& _f) + { + std::string::size_type dot = _f.rfind("/"); + if (dot == std::string::npos) + return std::string(_f); + return std::string(_f.substr(dot+1, _f.length()-(dot+1))); + } + + + bool is_same_name(const char _name[256]) + { + return (basename( name_ ) == basename( _name )); + } + + OpenMesh::VertexHandle add_vertex(const OpenMesh::Vec3f &p); + OpenMesh::FaceHandle add_face(const unsigned int _triangle[3]); + + const OpenMesh::Vec3f& point(OpenMesh::VertexHandle _vertex_handle) const + { + return points_[_vertex_handle.idx()]; + } + + OpenMesh::Vec3f& point(OpenMesh::VertexHandle _vertex_handle) + { + return points_[_vertex_handle.idx()]; + } + + const VHierarchy& vhierarchy() const { return vhierarchy_; } + VHierarchy& vhierarchy() { return vhierarchy_; } + + void vhierarchy_roots(VHierarchyNodeHandleContainer &roots) const; + + unsigned int n_base_vertices() const { return n_base_vertices_; } + unsigned int n_base_faces() const { return n_base_faces_; } + unsigned int n_details() const { return n_details_; } + + bool open_vd_prog_mesh(const char *_filename); +}; + +std::ostream& operator << ( std::ostream& _os, const ServerSideVDPM& _o ); + + +typedef std::vector ServerSideVDPMContainer; +typedef std::list ServerSideVDPMList; + +#endif //OPENMESH_APP_SERVERSIDEVDPM_HH defined + diff --git a/Apps/Unsupported/Streaming-qt4/Server/VDPMServerSession.cc b/Apps/Unsupported/Streaming-qt4/Server/VDPMServerSession.cc new file mode 100644 index 0000000000000000000000000000000000000000..2b8ba9e25950bc1ddb7b3c063b32afa9010550ea --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Server/VDPMServerSession.cc @@ -0,0 +1,475 @@ +#include +#include +#include +#include + + +using OpenMesh::VDPM::VHierarchyNode; +using OpenMesh::VDPM::Plane3d; +using OpenMesh::VDPM::InvalidVHierarchyNodeHandle; +using OpenMesh::VDPM::debug_print; + + +bool +VDPMServerSession:: +set_vdpm(const char _vdpm_name[256]) +{ +#ifdef DEBUG_COUT + if (debug_print() == true) + { + std::cout << "Setting vdpm" << std::endl; + } +#endif + vdpm_ = ((VDPMServerViewerWidget *) ((VDPMServerSocket *) parent())->parent())->get_vdpm(_vdpm_name); + if (vdpm_ == NULL) + return false; + + vhierarchy_ = &vdpm_->vhierarchy(); + + VHierarchyNodeHandleContainer roots; + unsigned int n_details; + + vdpm_->vhierarchy_roots(roots); + n_details = vdpm_->n_details(); + + //vfront_.init(roots, n_details); + + // vertex hierarchy window + vhwindow_.set_vertex_hierarchy(vdpm_->vhierarchy()); + vhwindow_.init(roots); + + +#ifdef DEBUG_COUT + if (debug_print() == true) + { + std::cout << "setting vdpm ended" << std::endl; + } +#endif + + return true; +} + + +void +VDPMServerSession:: +sendBaseMeshToClient() +{ +#ifdef DEBUG_COUT + if (debug_print() == true) + { + std::cout << "starting sendBaseMeshToClient()" << std::endl; + } +#endif + + + +#ifdef DEBUG_COUT + if (debug_print() == true) + { + std::cout << "sendBaseMeshToClient() is done" << std::endl; + } +#endif +} + +void +VDPMServerSession:: +send_vsplit_packets() +{ + viewing_parameters_.update_viewing_configurations(); + vsplits_.clear(); + + if (((VDPMServerViewerWidget *) this->parent()->parent())->vd_streaming()) + adaptive_refinement(); + else + sequential_refinement(); + + + if (debug_print() == true) + { + std::cout << "adaptive refinement is done on the server side" << std::endl; + } + + stream_vsplits(); + + if (debug_print() == true) + { + std::cout << "streameing vsplits is done" << std::endl; + } + + if (transmission_complete_ == true) + { + std::cout << "transmission is completed" << std::endl; + } + + if (debug_print() == true) + { + std::cout << "send_vsplit_packets() is done" << std::endl; + } +} + + +void +VDPMServerSession:: +readBaseMeshRequestFromClient() +{ + int status; + unsigned int string_length; + QDataStream qTcp(socket_); + QString vdpm_name; + +// while (waitForMore(10) < sizeof(int)); + while ( socket_->bytesAvailable() < sizeof(int) ) + socket_->waitForReadyRead(10); + + qTcp >> string_length; + +// while (waitForMore(10) < (string_length*sizeof(char))); + while (socket_->bytesAvailable() < string_length*sizeof(char) ) + socket_->waitForReadyRead(10); + + qTcp >> vdpm_name; + + if (set_vdpm( vdpm_name.toStdString().c_str() ) != true) status = 0; + else status = 1; + + qTcp << status; + socket_->flush(); + + if (status == 1) + streaming_phase_ = kVSplits; +} + + +void +VDPMServerSession:: +readViewingParametersFromClient() +{ + double modelview_matrix[16]; + float fovy; + float aspect; + float tolerance_square; + +// while (waitForMore(10) < 16*sizeof(double) + 3*sizeof(float)); + while ( socket_->bytesAvailable() < 16*sizeof(double) + 3*sizeof(float) ) + socket_->waitForReadyRead(10); + + QDataStream qTCP(socket_); + qTCP >> modelview_matrix[0] + >> modelview_matrix[1] + >> modelview_matrix[2] + >> modelview_matrix[3] + >> modelview_matrix[4] + >> modelview_matrix[5] + >> modelview_matrix[6] + >> modelview_matrix[7] + >> modelview_matrix[8] + >> modelview_matrix[9] + >> modelview_matrix[10] + >> modelview_matrix[11] + >> modelview_matrix[12] + >> modelview_matrix[13] + >> modelview_matrix[14] + >> modelview_matrix[15] + >> fovy + >> aspect + >> tolerance_square; + + viewing_parameters_.set_modelview_matrix(modelview_matrix); + viewing_parameters_.set_fovy(fovy); + viewing_parameters_.set_aspect(aspect); + viewing_parameters_.set_tolerance_square(tolerance_square); + + send_vsplit_packets(); + + fprintf(mem_file, "%d %d %d\n", + memory_requirements_using_window(true), + memory_requirements_using_window(false), + memory_requirements_using_vfront()); +} + + +void +VDPMServerSession:: +PrintOutVFront() +{ +} + +void +VDPMServerSession:: +stream_vsplits() +{ + // send header (i.e., # of vsplits) + unsigned int i; + VHierarchyNodeHandle node_handle; + OpenMesh::Vec3f pos; + VHierarchyNodeIndex node_index, fund_lcut_index, fund_rcut_index; + float lchild_radius, rchild_radius; + OpenMesh::Vec3f lchild_normal, rchild_normal; + float lchild_sin_square, rchild_sin_square; + float lchild_mue_square, rchild_mue_square; + float lchild_sigma_square, rchild_sigma_square; + unsigned int n_vsplit_packets = (unsigned int) vsplits_.size(); + + QDataStream qTcp(socket_); + qTcp << n_vsplit_packets; + socket_->flush(); + + for (i=0; ilchild_handle(node_handle); + VHierarchyNodeHandle rchild_handle = vhierarchy_->rchild_handle(node_handle); + + VHierarchyNode &node = vhierarchy_->node(node_handle); + VHierarchyNode &lchild = vhierarchy_->node(lchild_handle); + VHierarchyNode &rchild = vhierarchy_->node(rchild_handle); + + pos = vdpm_->point(lchild.vertex_handle()); + node_index = node.node_index(); + fund_lcut_index = node.fund_lcut_index(); + fund_rcut_index = node.fund_rcut_index(); + lchild_radius = lchild.radius(); rchild_radius = rchild.radius(); + lchild_normal = lchild.normal(); rchild_normal = rchild.normal(); + lchild_sin_square = lchild.sin_square(); rchild_sin_square = rchild.sin_square(); + lchild_mue_square = lchild.mue_square(); rchild_mue_square = rchild.mue_square(); + lchild_sigma_square = lchild.sigma_square(); rchild_sigma_square = rchild.sigma_square(); + + qTcp << pos[0] << pos[1] << pos[2] + << node_index.value() + << fund_lcut_index.value() + << fund_rcut_index.value() + << lchild_radius + << lchild_normal[0] << lchild_normal[1] << lchild_normal[2] + << lchild_sin_square + << lchild_mue_square + << lchild_sigma_square + << rchild_radius + << rchild_normal[0] << rchild_normal[1] << rchild_normal[2] + << rchild_sin_square + << rchild_mue_square + << rchild_sigma_square; + socket_->flush(); // socket flush + + if (debug_print() == true) + { + std::cout << "Write to client " << i << "-th vsplit packets: " << std::endl; + } + + } +} + + +void +VDPMServerSession:: +adaptive_refinement() +{ + float fovy = viewing_parameters_.fovy(); + float tolerance_square = viewing_parameters_.tolerance_square(); + float tan_value = tanf(fovy / 2.0f); + kappa_square_ = 4.0f * tan_value * tan_value * tolerance_square; + + transmission_complete_ = true; + for (vhwindow_.begin(); vhwindow_.end() != true; vhwindow_.next()) + { + VHierarchyNodeHandle node_handle = vhwindow_.node_handle(); + + if (vhierarchy_->is_leaf_node(node_handle) != true) + { + transmission_complete_ = false; + if (qrefine(node_handle) == true) + { + force_vsplit(node_handle); + } + } + } +} + +void +VDPMServerSession:: +sequential_refinement() +{ + for (vhwindow_.begin(); vhwindow_.end() != true; vhwindow_.next()) + { + VHierarchyNodeHandle node_handle = vhwindow_.node_handle(); + + if (vhierarchy_->is_leaf_node(node_handle) != true) + force_vsplit(node_handle); + + if (vsplits_.size() > 10) + break; + } +} + + +bool +VDPMServerSession:: +qrefine(VHierarchyNodeHandle _node_handle) +{ + VHierarchyNode &node = vhierarchy_->node(_node_handle); + OpenMesh::Vec3f p = vdpm_->point(node.vertex_handle()); + OpenMesh::Vec3f eye_dir = p - viewing_parameters_.eye_pos(); + float distance = eye_dir.length(); + float distance2 = distance * distance; + float product_value = dot(eye_dir, node.normal()); + + if (outside_view_frustum(p, node.radius()) == true) + return false; + if (oriented_away(node.sin_square(), distance2, product_value) == true) + return false; + if (screen_space_error(node.mue_square(), node.sigma_square(), distance2, product_value) == true) + return false; + + return true; +} + + +bool +VDPMServerSession:: +outside_view_frustum(const OpenMesh::Vec3f &pos, float radius) +{ + Plane3d frustum_plane[4]; + viewing_parameters_.frustum_planes(frustum_plane); + + for (int i = 0; i < 4; i++) { + if (frustum_plane[i].signed_distance(pos) < -radius) + return true; + } + + return false; +} + +bool +VDPMServerSession:: +oriented_away(float sin_square, float distance_square, float product_value) +{ + if (product_value > 0 && product_value*product_value > distance_square * sin_square) + return true; + else + return false; +} + +bool +VDPMServerSession:: +screen_space_error(float mue_square, float sigma_square, float distance_square, float product_value) +{ + if ((mue_square >= kappa_square_ * distance_square) || + (sigma_square * (distance_square - product_value * product_value) >= kappa_square_ * distance_square * distance_square)) + return false; + else + return true; +} + + +void +VDPMServerSession:: +force_vsplit(VHierarchyNodeHandle node_handle) +{ + VHierarchyNodeHandle lcut_handle, rcut_handle; + VHierarchyNodeIndex fund_lcut_index, fund_rcut_index; + + fund_lcut_index = vhierarchy_->fund_lcut_index(node_handle); + fund_rcut_index = vhierarchy_->fund_rcut_index(node_handle); + + lcut_handle = active_ancestor_handle(fund_lcut_index); + rcut_handle = active_ancestor_handle(fund_rcut_index); + assert(lcut_handle != InvalidVHierarchyNodeHandle && rcut_handle != InvalidVHierarchyNodeHandle); + + while (lcut_handle == rcut_handle) + { + force_vsplit(lcut_handle); + lcut_handle = active_ancestor_handle(fund_lcut_index); + rcut_handle = active_ancestor_handle(fund_rcut_index); + assert(lcut_handle != InvalidVHierarchyNodeHandle && rcut_handle != InvalidVHierarchyNodeHandle); + } + + vsplit(node_handle); +} + +void +VDPMServerSession:: +vsplit(VHierarchyNodeHandle _node_handle) +{ + // refine + VHierarchyNodeHandle lchild_handle = vhierarchy_->lchild_handle(_node_handle); + VHierarchyNodeHandle rchild_handle = vhierarchy_->rchild_handle(_node_handle); + + vhwindow_.inactivate(_node_handle); + vhwindow_.activate(lchild_handle); + vhwindow_.activate(rchild_handle); + + //vfront_.remove(_node_handle); + //vfront_.add(lchild_handle); + //vfront_.add(rchild_handle); + + vsplits_.push_back(_node_handle); +} + +VHierarchyNodeHandle +VDPMServerSession:: +active_ancestor_handle(VHierarchyNodeIndex &node_index) +{ + if (node_index.is_valid(vhierarchy_->tree_id_bits()) != true) + return InvalidVHierarchyNodeHandle; + + VHierarchyNodeHandle node_handle = vhierarchy_->node_handle(node_index); + + while (node_handle != InvalidVHierarchyNodeHandle && vhwindow_.is_active(node_handle) != true) + node_handle = vhierarchy_->parent_handle(node_handle); + + return node_handle; +} + +unsigned int +VDPMServerSession:: +memory_requirements_using_window(bool _estimate) +{ + unsigned int mem = 0; + + // common + mem += sizeof(VHierarchy*); + mem += sizeof(ViewingParameters); + mem += sizeof(float); + + if (_estimate) + { + unsigned int min = vhierarchy_->num_nodes(); + unsigned int max = 0; + + for (unsigned int i = 0; i < vhierarchy_->num_nodes(); ++i) + { + if (vhwindow_.is_active(VHierarchyNodeHandle((int) i))) + { + min = std::min(min, i); + max = std::max(max, i); + } + } + + mem += (max - min) / 8; + } + else + { + mem += vhwindow_.buffer_size(); + } + + return mem; +} + +unsigned int +VDPMServerSession:: +memory_requirements_using_vfront() +{ + unsigned int mem = 0; + std::list dummy_vfront; + + mem += (unsigned int) ceil (vhierarchy_->num_nodes() / 8.0); + mem += sizeof(dummy_vfront); + + for (unsigned int i = 0; i < vhierarchy_->num_nodes(); ++i) + { + if (vhwindow_.is_active(VHierarchyNodeHandle((int) i))) + mem += 3*sizeof(int); + } + + return mem; +} + diff --git a/Apps/Unsupported/Streaming-qt4/Server/VDPMServerSession.hh b/Apps/Unsupported/Streaming-qt4/Server/VDPMServerSession.hh new file mode 100644 index 0000000000000000000000000000000000000000..4723da3196421057803d57b91c75db72982cd5e5 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Server/VDPMServerSession.hh @@ -0,0 +1,148 @@ +#ifndef OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSESSION_HH +#define OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSESSION_HH + +#include +#include +#include +#include +#include +// #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using OpenMesh::VDPM::VDPMStreamingPhase; +using OpenMesh::VDPM::kBaseMesh; +using OpenMesh::VDPM::kVSplits; + +using OpenMesh::VDPM::VHierarchyWindow; +using OpenMesh::VDPM::VHierarchyNodeIndex; +using OpenMesh::VDPM::VHierarchyNodeHandle; +using OpenMesh::VDPM::ViewingParameters; + +using OpenMesh::VDPM::set_debug_print; + +class VDPMServerSession : public QThread +{ + + Q_OBJECT + +public: + + VDPMServerSession(QTcpSocket* _socket, QObject *parent=0, const char *name=0) + { + socket_ = _socket; + + set_debug_print(true); + + streaming_phase_ = kBaseMesh; + transmission_complete_ = false; + + connect(socket_, SIGNAL(connected()), this, SLOT(socketConnected())); + QTcpSocket::connect(socket_, SIGNAL(readyRead()), this, SLOT(socketReadyRead())); + //connect(this, SIGNAL(connectionClosed()), SLOT(deleteLater())); + QTcpSocket::connect(socket_, SIGNAL(connectionClosed()), this, SLOT(delayedCloseFinished())); + +///TODO: find out how to port it from QSocket -> QTcpSocket +// setSocket(sock); + + qStatisticsTimer_ = new QTimer(this); + QTcpSocket::connect(qStatisticsTimer_, SIGNAL(timeout()), this, SLOT(print_statistics())); + + mem_file = fopen("mem.txt", "w"); + + start(); + } + + ~VDPMServerSession() + { + fclose(mem_file); + } + +// void run() +// { +// exec(); +// } + +private: + + VDPMStreamingPhase streaming_phase_; + bool transmission_complete_; + + QTcpSocket* socket_; + +private: + + void sendBaseMeshToClient(); + void send_vsplit_packets(); + void readBaseMeshRequestFromClient(); + void readViewingParametersFromClient(); + + void PrintOutVFront(); + +private slots: + + void socketConnected() + { + std::cout << "socket is connected" << std::endl; + } + + void socketReadyRead() + { + if (streaming_phase_ == kBaseMesh) + { + readBaseMeshRequestFromClient(); + } + else if (streaming_phase_ == kVSplits) + { + readViewingParametersFromClient(); + } + } + + void print_statistics() + { + //std::cout << memory_requirements(true) << " " << memory_requirements(false) << std::endl; + } + +private: + unsigned short tree_id_bits_; // obsolete + ServerSideVDPM* vdpm_; + VHierarchy* vhierarchy_; + VHierarchyWindow vhwindow_; + ViewingParameters viewing_parameters_; + float kappa_square_; + VHierarchyNodeHandleContainer vsplits_; + +private: + bool outside_view_frustum(const OpenMesh::Vec3f &pos, float radius); + bool oriented_away(float sin_square, float distance_square, float product_value); + bool screen_space_error(float mue_square, float sigma_square, float distance_square, float product_value); + + void adaptive_refinement(); + void sequential_refinement(); + bool qrefine(VHierarchyNodeHandle _node_handle); + void force_vsplit(VHierarchyNodeHandle node_handle); + void vsplit(VHierarchyNodeHandle _node_handle); + VHierarchyNodeHandle active_ancestor_handle(VHierarchyNodeIndex &node_index); + void stream_vsplits(); + +public: + bool set_vdpm(const char _vdpm_name[256]); + unsigned int memory_requirements_using_window(bool _estimate); + unsigned int memory_requirements_using_vfront(); + + // for example +private: + QTimer *qStatisticsTimer_; + FILE *mem_file; +}; + +#endif //OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSESSION_HH defined diff --git a/Apps/Unsupported/Streaming-qt4/Server/VDPMServerSocket.hh b/Apps/Unsupported/Streaming-qt4/Server/VDPMServerSocket.hh new file mode 100644 index 0000000000000000000000000000000000000000..ab66fb6a5b32ce93b50dd6b386767bdf3c9ae772 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Server/VDPMServerSocket.hh @@ -0,0 +1,51 @@ +#ifndef OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSOCKET_HH +#define OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSOCKET_HH + +#include +#include +#include +#include + +#include +#include +#include + + +class VDPMServerSocket : public QTcpServer +{ + Q_OBJECT + +public: + + VDPMServerSocket(QObject *parent=0) + : QTcpServer(parent) + { + setMaxPendingConnections(1); + if ( !listen(QHostAddress::Any, VDPM_STREAMING_PORT) ) + { + std::cerr << "Failed to bind to port " << VDPM_STREAMING_PORT << std::endl; + exit(1); + } + + connect(this, SIGNAL(newConnection()),this,SLOT(newConnections())); + } + +public slots: + + void newConnections() + { + VDPMServerSession *s = new VDPMServerSession(nextPendingConnection(), this); + //s->set_vdpm(); + emit newConnect(s); + std::cout << "new connection"<< /*socket << */std::endl; + } + +signals: + + void newConnect(VDPMServerSession*); + +}; + + + +#endif //OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSOCKET_HH defined diff --git a/Apps/Unsupported/Streaming-qt4/Server/VDPMServerViewerWidget.cc b/Apps/Unsupported/Streaming-qt4/Server/VDPMServerViewerWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..7bc1e4d9aca16fbf72835bfeefef4909689298f8 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Server/VDPMServerViewerWidget.cc @@ -0,0 +1,81 @@ +#include +#include +#include + +bool +VDPMServerViewerWidget:: +open_vd_prog_mesh(const char *_filename) +{ + ServerSideVDPMListIter vdpm_it; + + vdpm_it = vdpms_.insert(vdpms_.end(), ServerSideVDPM()); + + ServerSideVDPM &vdpm = *vdpm_it; + + return vdpm.open_vd_prog_mesh(_filename); +} + +ServerSideVDPM* +VDPMServerViewerWidget:: +get_vdpm(const char _vdpm_name[256]) +{ + ServerSideVDPMListIter vdpm_it; + + for (vdpm_it=vdpms_.begin(); vdpm_it!=vdpms_.end(); ++vdpm_it) + { + if (vdpm_it->is_same_name(_vdpm_name) == true) + { + return &(*vdpm_it); + } + } + + return NULL; +} + +void +VDPMServerViewerWidget:: +keyPressEvent(QKeyEvent* _event) +{ + bool handled(false); + + QString filename; + + switch (_event->key()) + { + case Qt::Key_D: + set_debug_print(!debug_print()); + std::cout << "debug print mode " + << (debug_print() == true ? "on" : "off") << std::endl; + break; + + case Qt::Key_O: +#if defined(OM_CC_MSVC) + filename = QFileDialog::getOpenFileName(0, "", "d:/data/models/spm/", "*.spm"); +#else + filename = QFileDialog::getOpenFileName(0, "", "~/data/models/spm/", "*.spm"); +#endif + open_vd_prog_mesh( filename.toStdString().c_str() ); + break; + + case Qt::Key_I: + std::copy( vdpms_.begin(), vdpms_.end(), + std::ostream_iterator(std::cout, "\n") ); + break; + + case Qt::Key_V: + vd_streaming_ = !(vd_streaming_); + if (vd_streaming_) + std::cout << "View-dependent streaming mode" << std::endl; + else + std::cout << "Sequential streaming mode" << std::endl; + + break; + + case Qt::Key_Q: + case Qt::Key_Escape: + qApp->quit(); + } + + if (!handled) + _event->ignore(); +} diff --git a/Apps/Unsupported/Streaming-qt4/Server/VDPMServerViewerWidget.hh b/Apps/Unsupported/Streaming-qt4/Server/VDPMServerViewerWidget.hh new file mode 100644 index 0000000000000000000000000000000000000000..fa6780e306b303cbd953ea238025f1c32b623344 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Server/VDPMServerViewerWidget.hh @@ -0,0 +1,72 @@ +#ifndef OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSTREAMINGSERVERWIDGET_HH +#define OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSTREAMINGSERVERWIDGET_HH + +#include +#include +#include +#include +#include +#include +#include + + +using OpenMesh::VDPM::set_debug_print; +using OpenMesh::VDPM::debug_print; + + +class VDPMServerViewerWidget : public QWidget +{ + Q_OBJECT +public: + //VDPMServerViewerWidget(QWidget *_parent) : QWidget(_parent) + VDPMServerViewerWidget() : QWidget() + { + server = new VDPMServerSocket(this); + +// connect(server, +// SIGNAL(newConnection()), +// SLOT(newConnect())); + + vd_streaming_ = true; + } + +private: + typedef ServerSideVDPMList::iterator ServerSideVDPMListIter; + ServerSideVDPMList vdpms_; + bool vd_streaming_; + VDPMServerSocket *server; + +public: + + ServerSideVDPM* get_vdpm(const char _vdpm_name[256]); + + +public: + + bool open_vd_prog_mesh(const char *_filename); + bool vd_streaming() const { return vd_streaming_; } + +private slots: + + void newConnect(VDPMServerSession *s) + { + std::cout << "New connection" << std::endl; + +// connect(s, SIGNAL(connectionClosed()), SLOT(connectionClosed())); + } + + void connectionClosed() + { + std::cout << "Client closed connection" << std::endl; + } + +protected: + + virtual void keyPressEvent(QKeyEvent* _event); + +}; + + +#endif //OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSTREAMINGSERVERWIDGET_HH defined + + diff --git a/Apps/Unsupported/Streaming-qt4/Server/VDPMStreamingServer.cc b/Apps/Unsupported/Streaming-qt4/Server/VDPMStreamingServer.cc new file mode 100644 index 0000000000000000000000000000000000000000..15bc7df4633292a51bbc26e35039b30363f06b65 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Server/VDPMStreamingServer.cc @@ -0,0 +1,34 @@ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + + +int main(int argc, char **argv) +{ + std::cout << "View-dependent streaming of PM server." << std::endl; + + QApplication app(argc, argv); + VDPMServerViewerWidget server_widget; + + server_widget.resize(50, 50); +// app.setMainWidget(&server_widget); + server_widget.show(); + + for (int idx=1; idx < argc; ++idx) + { + std::cout << "loading " << argv[idx] << std::endl; + server_widget.open_vd_prog_mesh( argv[idx] ) ; + } + + return app.exec(); +} + diff --git a/Apps/Unsupported/Streaming-qt4/Server/VDPMStreamingServer.hh b/Apps/Unsupported/Streaming-qt4/Server/VDPMStreamingServer.hh new file mode 100644 index 0000000000000000000000000000000000000000..119b5939e545824dec03a3335bf70b413f29f840 --- /dev/null +++ b/Apps/Unsupported/Streaming-qt4/Server/VDPMStreamingServer.hh @@ -0,0 +1,6 @@ +#ifndef OPENMESH_APP_VDPMSTREAMINGSERVER_HH +#define OPENMESH_APP_VDPMSTREAMINGSERVER_HH + + + +#endif //OPENMESH_APP_VDPMSTREAMINGSERVER_HH defined diff --git a/Apps/Unsupported/Streaming-qt4/Server/bunny.pm b/Apps/Unsupported/Streaming-qt4/Server/bunny.pm new file mode 100755 index 0000000000000000000000000000000000000000..3e049810a15b51ec1efb62e26041a8d2deac2d1b Binary files /dev/null and b/Apps/Unsupported/Streaming-qt4/Server/bunny.pm differ diff --git a/Apps/Unsupported/Streaming-qt4/Server/bunny.spm b/Apps/Unsupported/Streaming-qt4/Server/bunny.spm new file mode 100644 index 0000000000000000000000000000000000000000..6df95b1b8ee99dbfcf7d86f80dd6b8918ba71a6c Binary files /dev/null and b/Apps/Unsupported/Streaming-qt4/Server/bunny.spm differ diff --git a/Apps/Unsupported/Streaming-qt4/Server/rockerArm.pm b/Apps/Unsupported/Streaming-qt4/Server/rockerArm.pm new file mode 100755 index 0000000000000000000000000000000000000000..04034d92e981a5bb1be39a60c8d8d1f8b3e358a4 Binary files /dev/null and b/Apps/Unsupported/Streaming-qt4/Server/rockerArm.pm differ diff --git a/Apps/Unsupported/Streaming/ACGMakefile b/Apps/Unsupported/Streaming/ACGMakefile new file mode 100644 index 0000000000000000000000000000000000000000..d05cdf75519d4171b8f5935a01b479b7222fd013 --- /dev/null +++ b/Apps/Unsupported/Streaming/ACGMakefile @@ -0,0 +1,16 @@ +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Config +#============================================================================== + + +SUBDIRS = $(call find-subdirs) + +PACKAGES := + +PROJ_LIBS := + +MODULES := + +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Rules +#============================================================================== diff --git a/Apps/Unsupported/Streaming/Client/ACGMakefile b/Apps/Unsupported/Streaming/Client/ACGMakefile new file mode 100644 index 0000000000000000000000000000000000000000..b862f196ad491c6c391797f7407848ca5a9215a2 --- /dev/null +++ b/Apps/Unsupported/Streaming/Client/ACGMakefile @@ -0,0 +1,19 @@ +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Config +#============================================================================== + +CXX_CFLAGS += -DQT_THREAD_SUPPORT + +SUBDIRS = $(call find-subdirs) + +PACKAGES := qt glut opengl + +PROJ_LIBS := OpenMesh/Apps/QtViewer \ + OpenMesh/Core OpenMesh/Tools + +MODULES := moc cxx + + +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Rules +#============================================================================== diff --git a/Apps/Unsupported/Streaming/Client/MeshViewerWidgetT.cc b/Apps/Unsupported/Streaming/Client/MeshViewerWidgetT.cc new file mode 100644 index 0000000000000000000000000000000000000000..457ac4f1d27ecaef5efff2803134f62b1e7cdb57 --- /dev/null +++ b/Apps/Unsupported/Streaming/Client/MeshViewerWidgetT.cc @@ -0,0 +1,602 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mo, 19. Mai 2008) $ +// +//============================================================================= +#define OPENMESHAPPS_MESHVIEWERWIDGET_CC + +//== INCLUDES ================================================================= + +#ifdef _MSC_VER +//# pragma warning(disable: 4267 4311) +#endif + +// +#include +#include +#include +#include +#include +#include + +using namespace OpenMesh; + + +//== IMPLEMENTATION ========================================================== + + +template +bool +MeshViewerWidgetT::open_mesh(const char* _filename, + IO::Options _opt) +{ + // load mesh + // calculate normals + // set scene center and radius + + mesh_.request_face_normals(); + mesh_.request_face_colors(); + mesh_.request_vertex_normals(); + mesh_.request_vertex_texcoords2D(); + + if ( IO::read_mesh(mesh_, _filename, _opt )) + { + opt_ = _opt; + + // update face and vertex normals + if ( ! opt_.check( IO::Options::FaceNormal ) ) + mesh_.update_face_normals(); + + if ( ! opt_.check( IO::Options::VertexNormal ) ) + mesh_.update_vertex_normals(); + + if ( mesh_.has_vertex_colors() ) + add_draw_mode("Colored"); + + if ( _opt.check( IO::Options::FaceColor ) ) + add_draw_mode("Colored Faces"); + else + mesh_.release_face_colors(); + + // bounding box + typename Mesh::ConstVertexIter vIt(mesh_.vertices_begin()); + typename Mesh::ConstVertexIter vEnd(mesh_.vertices_end()); + + typedef typename Mesh::Point Point; + using OpenMesh::Vec3f; + + Vec3f bbMin, bbMax; + + bbMin = bbMax = OpenMesh::vector_cast(mesh_.point(vIt)); + + for (size_t count=0; vIt!=vEnd; ++vIt, ++count) + { + bbMin.minimize( OpenMesh::vector_cast(mesh_.point(vIt))); + bbMax.maximize( OpenMesh::vector_cast(mesh_.point(vIt))); + + if ( ! opt_.check( IO::Options::VertexColor ) && + mesh_.has_vertex_colors() ) + { + typename Mesh::Color + c( 54, + (unsigned char)(54.5+200.0*count/mesh_.n_vertices()), + 54 ); + mesh_.set_color( vIt, c ); + } + } + + + // set center and radius + set_scene_pos( (bbMin+bbMax)*0.5, (bbMin-bbMax).norm()*0.5 ); + + // info + std::clog << mesh_.n_vertices() << " vertices, " + << mesh_.n_edges() << " edge, " + << mesh_.n_faces() << " faces\n"; + + // + { + std::clog << "Computing strips.." << std::flush; + OpenMesh::Utils::Timer t; + t.start(); + compute_strips(); + t.stop(); + std::clog << "done [" << strips_.n_strips() + << " strips created in " << t.as_string() << "]\n"; + } + +#if defined(OM_CC_MSVC) + updateGL(); +#endif + + return true; + } + return false; +} + + +//----------------------------------------------------------------------------- + +template +bool MeshViewerWidgetT::open_texture( const char *_filename ) +{ + QImage texsrc; + QString fname = _filename; + + if (texsrc.load( fname )) + { + return set_texture( texsrc ); + } + return false; +} + + +//----------------------------------------------------------------------------- + +template +bool MeshViewerWidgetT::set_texture( QImage& _texsrc ) +{ + std::clog << "set_texture\n"; + + if ( !opt_.vertex_has_texcoord() ) + return false; + + { + // adjust texture size: 2^k * 2^l + int tex_w, w( _texsrc.width() ); + int tex_h, h( _texsrc.height() ); + + for (tex_w=1; tex_w <= w; tex_w <<= 1); + for (tex_h=1; tex_h <= h; tex_h <<= 1); + tex_w >>= 1; + tex_h >>= 1; + _texsrc = _texsrc.smoothScale( tex_w, tex_h ); + } + + QImage texture( QGLWidget::convertToGLFormat ( _texsrc ) ); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + if ( tex_id_ > 0 ) + { + glDeleteTextures(1, &tex_id_); + } + glGenTextures(1, &tex_id_); + glBindTexture(GL_TEXTURE_2D, tex_id_); + + // glTexGenfv( GL_S, GL_SPHERE_MAP, 0 ); + // glTexGenfv( GL_T, GL_SPHERE_MAP, 0 ); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, // target + 0, // level + GL_RGBA, // internal format + texture.width(), // width (2^n) + texture.height(), // height (2^m) + 0, // border + GL_RGBA, // format + GL_UNSIGNED_BYTE, // type + texture.bits() ); // pointer to pixels + + return true; +} + + +//----------------------------------------------------------------------------- + +template +void +MeshViewerWidgetT::draw_openmesh(const std::string& _draw_mode) +{ + typename Mesh::ConstFaceIter fIt(mesh_.faces_begin()), + fEnd(mesh_.faces_end()); + + typename Mesh::ConstFaceVertexIter fvIt; + +#if defined(OM_USE_OSG) && OM_USE_OSG + if (_draw_mode == "OpenSG Indices") // -------------------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, mesh_.vertex_normals()); + + if ( tex_id_ && mesh_.has_vertex_texcoords2D() ) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, mesh_.texcoords2D()); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tex_id_); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_mode_); + } + + glDrawElements(GL_TRIANGLES, + mesh_.osg_indices()->size(), + GL_UNSIGNED_INT, + &mesh_.osg_indices()->getField()[0] ); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + else +#endif + + if (_draw_mode == "Wireframe") // -------------------------------------------- + { + glBegin(GL_TRIANGLES); + for (; fIt!=fEnd; ++fIt) + { + fvIt = mesh_.cfv_iter(fIt.handle()); + glVertex3fv( &mesh_.point(fvIt)[0] ); + ++fvIt; + glVertex3fv( &mesh_.point(fvIt)[0] ); + ++fvIt; + glVertex3fv( &mesh_.point(fvIt)[0] ); + } + glEnd(); + } + + else if (_draw_mode == "Solid Flat") // ------------------------------------- + { + glBegin(GL_TRIANGLES); + for (; fIt!=fEnd; ++fIt) + { + glNormal3fv( &mesh_.normal(fIt)[0] ); + + fvIt = mesh_.cfv_iter(fIt.handle()); + glVertex3fv( &mesh_.point(fvIt)[0] ); + ++fvIt; + glVertex3fv( &mesh_.point(fvIt)[0] ); + ++fvIt; + glVertex3fv( &mesh_.point(fvIt)[0] ); + } + glEnd(); + + + } + + + else if (_draw_mode == "Solid Smooth") // ----------------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, mesh_.vertex_normals()); + + if ( tex_id_ && mesh_.has_vertex_texcoords2D() ) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, mesh_.texcoords2D()); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tex_id_); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_mode_); + } + + glBegin(GL_TRIANGLES); + for (; fIt!=fEnd; ++fIt) + { + fvIt = mesh_.cfv_iter(fIt.handle()); + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + } + glEnd(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + if ( tex_id_ && mesh_.has_vertex_texcoords2D() ) + { + glDisable(GL_TEXTURE_2D); + } + } + + else if (_draw_mode == "Colored") // ---------------------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, mesh_.vertex_normals()); + + if ( mesh_.has_vertex_colors() ) + { + glEnableClientState( GL_COLOR_ARRAY ); + glColorPointer(3, GL_UNSIGNED_BYTE, 0,mesh_.vertex_colors()); + } + + glBegin(GL_TRIANGLES); + for (; fIt!=fEnd; ++fIt) + { + fvIt = mesh_.cfv_iter(fIt.handle()); + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + } + glEnd(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } + + + else if (_draw_mode == "Colored Faces") // ---------------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, mesh_.vertex_normals()); + + glBegin(GL_TRIANGLES); + for (; fIt!=fEnd; ++fIt) + { + glColor( fIt.handle() ); + + fvIt = mesh_.cfv_iter(fIt.handle()); + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + ++fvIt; + glArrayElement(fvIt.handle().idx()); + } + glEnd(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + } + + + else if ( _draw_mode == "Strips'n VertexArrays" ) // ------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, mesh_.vertex_normals()); + + if ( tex_id_ && mesh_.has_vertex_texcoords2D() ) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, mesh_.texcoords2D()); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, tex_id_); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_mode_); + } + + typename MyStripifier::StripsIterator strip_it = strips_.begin(); + typename MyStripifier::StripsIterator strip_last = strips_.end(); + + // Draw all strips + for (; strip_it!=strip_last; ++strip_it) + { + glDrawElements(GL_TRIANGLE_STRIP, + strip_it->size(), GL_UNSIGNED_INT, &(*strip_it)[0] ); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + + + else if (_draw_mode == "Show Strips" && strips_.is_valid() ) // ------------- + { + typename MyStripifier::StripsIterator strip_it = strips_.begin(); + typename MyStripifier::StripsIterator strip_last = strips_.end(); + + float cmax = 256.0f; + int range = 220; + int base = (int)cmax-range; + int drcol = 13; + int dgcol = 31; + int dbcol = 17; + + int rcol=0, gcol=dgcol, bcol=dbcol+dbcol; + + // Draw all strips + for (; strip_it!=strip_last; ++strip_it) + { + typename MyStripifier::IndexIterator idx_it = strip_it->begin(); + typename MyStripifier::IndexIterator idx_last = strip_it->end(); + + rcol = (rcol+drcol) % range; + gcol = (gcol+dgcol) % range; + bcol = (bcol+dbcol) % range; + + glBegin(GL_TRIANGLE_STRIP); + glColor3f((rcol+base)/cmax, (gcol+base)/cmax, (bcol+base)/cmax); + for ( ;idx_it != idx_last; ++idx_it ) + glVertex3fv( &mesh_.point( OM_TYPENAME Mesh::VertexHandle(*idx_it))[0] ); + glEnd(); + } + glColor3f(1.0, 1.0, 1.0); + } + + + else if( _draw_mode == "Points" ) // ----------------------------------------- + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, mesh_.points()); + glDrawArrays( GL_POINTS, 0, mesh_.n_vertices() ); + glDisableClientState(GL_VERTEX_ARRAY); + } + + +} + + +//----------------------------------------------------------------------------- + + +template +void +MeshViewerWidgetT::draw_scene(const std::string& _draw_mode) +{ + + if ( ! mesh_.n_vertices() ) + return; + +#if defined(OM_USE_OSG) && OM_USE_OSG + else if ( _draw_mode == "OpenSG Indices") + { + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); + draw_openmesh( _draw_mode ); + } + else +#endif + if ( _draw_mode == "Points" ) + { + glDisable(GL_LIGHTING); + draw_openmesh(_draw_mode); + } + else if (_draw_mode == "Wireframe") + { + glDisable(GL_LIGHTING); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + draw_openmesh(_draw_mode); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + + else if ( _draw_mode == "Hidden-Line" ) + { + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glDepthRange(0.01, 1.0); + draw_openmesh("Solid Smooth"); + + glDisable(GL_LIGHTING); + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE); + glColor4f( 0.4f, 0.4f, 0.4f, 1.0f ); + glDepthRange( 0.0, 1.0 ); + draw_openmesh( "Wireframe" ); + + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL); + } + + else if (_draw_mode == "Solid Flat") + { + glEnable(GL_LIGHTING); + glShadeModel(GL_FLAT); + draw_openmesh(_draw_mode); + } + + else if (_draw_mode == "Solid Smooth" || + _draw_mode == "Strips'n VertexArrays" ) + { + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); + draw_openmesh(_draw_mode); + } + + else if (_draw_mode == "Show Strips") + { + glDisable(GL_LIGHTING); + draw_openmesh(_draw_mode); + } + + else if (_draw_mode == "Colored" ) + { + glDisable(GL_LIGHTING); + draw_openmesh(_draw_mode); + } + + else if (_draw_mode == "Colored Faces" ) + { + glDisable(GL_LIGHTING); + draw_openmesh(_draw_mode); + } +} + + +//----------------------------------------------------------------------------- + +#define TEXMODE( Mode ) \ + tex_mode_ = Mode; std::cout << "Texture mode set to " << #Mode << std::endl + +template +void +MeshViewerWidgetT::keyPressEvent( QKeyEvent* _event) +{ + switch( _event->key() ) + { + case Key_I: + std::cout << "\n# Vertices : " << mesh_.n_vertices() << std::endl; + std::cout << "# Edges : " << mesh_.n_edges() << std::endl; + std::cout << "# Faces : " << mesh_.n_faces() << std::endl; + std::cout << "binary input : " << opt_.check(opt_.Binary) << std::endl; + std::cout << "swapped input : " << opt_.check(opt_.Swap) << std::endl; + std::cout << "vertex normal : " + << opt_.check(opt_.VertexNormal) << std::endl; + std::cout << "vertex texcoord: " + << opt_.check(opt_.VertexTexCoord) << std::endl; + std::cout << "vertex color : " + << opt_.check(opt_.VertexColor) << std::endl; + this->QGLViewerWidget::keyPressEvent( _event ); + break; + + case Key_T: + switch( tex_mode_ ) + { + case GL_MODULATE: TEXMODE(GL_DECAL); break; + case GL_DECAL: TEXMODE(GL_BLEND); break; + case GL_BLEND: TEXMODE(GL_REPLACE); break; + case GL_REPLACE: TEXMODE(GL_MODULATE); break; + } + updateGL(); + break; + + default: + this->QGLViewerWidget::keyPressEvent( _event ); + } +} + +#undef TEXMODE + +//============================================================================= diff --git a/Apps/Unsupported/Streaming/Client/MeshViewerWidgetT.hh b/Apps/Unsupported/Streaming/Client/MeshViewerWidgetT.hh new file mode 100644 index 0000000000000000000000000000000000000000..5172d84d3241075dfbd9c2a8d440e74e5d0a1d60 --- /dev/null +++ b/Apps/Unsupported/Streaming/Client/MeshViewerWidgetT.hh @@ -0,0 +1,163 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mo, 19. Mai 2008) $ +// +//============================================================================= + + +#ifndef OPENMESHAPPS_MESHVIEWERWIDGETT_HH +#define OPENMESHAPPS_MESHVIEWERWIDGETT_HH + + +//== INCLUDES ================================================================= + +#include +#include +#include +#include +#include +#include +#include +#include + + +//== FORWARDS ================================================================= + +class QImage; + + +//== CLASS DEFINITION ========================================================= + + +template +class MeshViewerWidgetT : public QGLViewerWidget +{ +public: + typedef M Mesh; + typedef OpenMesh::StripifierT MyStripifier; + + + /// default constructor + MeshViewerWidgetT(QWidget* _parent=0, const char* _name=0) + : QGLViewerWidget(_parent, _name), + f_strips_(false), + tex_id_(0), + tex_mode_(GL_MODULATE), + strips_(mesh_) + { + add_draw_mode("Points"); + add_draw_mode("Hidden-Line"); +#if defined(OM_USE_OSG) && OM_USE_OSG + add_draw_mode("OpenSG Indices"); +#endif + } + + void enable_strips() { + f_strips_ = true; + add_draw_mode("Strips'n VertexArrays"); + add_draw_mode("Show Strips"); + } + void disable_strips() { f_strips_ = false; } + + /// destructor + ~MeshViewerWidgetT() {} + + /// open mesh + virtual bool open_mesh(const char* _filename, OpenMesh::IO::Options _opt); + + /// load texture + virtual bool open_texture( const char *_filename ); + bool set_texture( QImage& _texsrc ); + + + Mesh& mesh() { return mesh_; } + const Mesh& mesh() const { return mesh_; } + + +protected: + + /// inherited drawing method + virtual void draw_scene(const std::string& _draw_mode); + +protected: + + /// draw the mesh + virtual void draw_openmesh(const std::string& _drawmode); + + void glVertex( const typename Mesh::VertexHandle vh ) + { glVertex3fv( &mesh_.point( vh )[0] ); } + + void glNormal( const typename Mesh::VertexHandle vh ) + { glNormal3fv( &mesh_.normal( vh )[0] ); } + + void glTexCoord( const typename Mesh::VertexHandle vh ) + { glTexCoord2fv( &mesh_.texcoord(vh)[0] ); } + + void glColor( const typename Mesh::VertexHandle vh ) + { glColor3ubv( &mesh_.color(vh)[0] ); } + + void glColor( const typename Mesh::FaceHandle fh ) + { glColor3ubv( &mesh_.color(fh)[0] ); } + + + +protected: // Strip support + + void compute_strips(void) + { + if (f_strips_) + { + strips_.clear(); + strips_.stripify(); + } + } + +protected: // inherited + + virtual void keyPressEvent( QKeyEvent* _event); + +protected: + + bool f_strips_; // enable/disable strip usage + GLuint tex_id_; + GLint tex_mode_; + OpenMesh::IO::Options opt_; // mesh file contained texcoords? + + Mesh mesh_; + MyStripifier strips_; +}; + + +//============================================================================= +#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESHAPPS_MESHVIEWERWIDGET_CC) +# define OPENMESH_MESHVIEWERWIDGET_TEMPLATES +# include "MeshViewerWidgetT.cc" +#endif +//============================================================================= +#endif // OPENMESHAPPS_MESHVIEWERWIDGETT_HH defined +//============================================================================= + diff --git a/Apps/Unsupported/Streaming/Client/MyMesh.hh b/Apps/Unsupported/Streaming/Client/MyMesh.hh new file mode 100644 index 0000000000000000000000000000000000000000..b6dfdb2e65168fc0b449a9ced184e49f4f51c479 --- /dev/null +++ b/Apps/Unsupported/Streaming/Client/MyMesh.hh @@ -0,0 +1,23 @@ +#ifndef OPENMESH_APPS_VDPMSTREAMING_CLIENT_MYMESH_HH +#define OPENMESH_APPS_VDPMSTREAMING_CLIENT_MYMESH_HH + +#include +#include +#include +#include + + +using OpenMesh::VDPM::MeshTraits; + + +//== CLASS DEFINITION ========================================================= + + +typedef OpenMesh::TriMesh_ArrayKernelT MyMesh; + +static QMutex mutex_; + + +//== CLASS DEFINITION ========================================================= + +#endif //OPENMESH_APPS_VDPMSTREAMING_CLIENT_MYMESH_HH defined diff --git a/Apps/Unsupported/Streaming/Client/QGLViewerWidget.cc b/Apps/Unsupported/Streaming/Client/QGLViewerWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..c77f9a21da50b86692aef076ba3f1dc4e1d2460e --- /dev/null +++ b/Apps/Unsupported/Streaming/Client/QGLViewerWidget.cc @@ -0,0 +1,621 @@ +//============================================================================= +// +// OpenMesh +// Copyright (C) 2003 by Computer Graphics Group, RWTH Aachen +// www.openmesh.org +// +//----------------------------------------------------------------------------- +// +// License +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, version 2.1. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +//----------------------------------------------------------------------------- +// +// $Revision: 1800 $ +// $Date: 2008-05-19 11:51:23 +0200 (Mo, 19. Mai 2008) $ +// +//============================================================================= + + +//== INCLUDES ================================================================= + +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311 4305) +#endif + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#if !defined(M_PI) +# define M_PI 3.1415926535897931 +#endif + +using namespace OpenMesh; + + +//== IMPLEMENTATION ========================================================== + + +QGLViewerWidget::QGLViewerWidget( QWidget* _parent, const char* _name ) + : QGLWidget( _parent, _name ) +{ + // qt stuff + setBackgroundMode( NoBackground ); + setFocusPolicy(QWidget::StrongFocus); + setAcceptDrops( true ); + setCursor(pointingHandCursor); + + + // popup menu + popup_menu_ = new QPopupMenu(this, "Draw Mode Menu"); + popup_menu_->setCheckable(true); + connect( popup_menu_, SIGNAL(activated(int)), + this, SLOT(slotPopupMenu(int))); + + + // init draw modes + n_draw_modes_ = 0; + add_draw_mode("Wireframe"); + add_draw_mode("Solid Flat"); + add_draw_mode("Solid Smooth"); + + // for example + add_draw_mode("Colored"); + + slotPopupMenu(2); +} + + +//---------------------------------------------------------------------------- + + +QGLViewerWidget::~QGLViewerWidget() +{ +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::initializeGL() +{ + // OpenGL state + glClearColor(1.0, 1.0, 1.0, 0.0); + glDisable( GL_DITHER ); + glEnable( GL_DEPTH_TEST ); + glEnable( GL_CULL_FACE ); + + + // material + GLfloat mat_a[] = {0.7, 0.6, 0.5, 1.0}; + GLfloat mat_d[] = {0.8, 0.7, 0.6, 1.0}; + GLfloat mat_s[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat shine[] = {120.0}; + +// GLfloat mat_a[] = {0.2, 0.2, 0.2, 1.0}; +// GLfloat mat_d[] = {0.4, 0.4, 0.4, 1.0}; +// GLfloat mat_s[] = {0.8, 0.8, 0.8, 1.0}; +// GLfloat shine[] = {128.0}; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_a); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_d); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_s); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shine); + + + // lighting + glLoadIdentity(); + + GLfloat pos1[] = { 0.1, 0.1, -0.02, 0.0}; + GLfloat pos2[] = {-0.1, 0.1, -0.02, 0.0}; + GLfloat pos3[] = { 0.0, 0.0, 0.1, 0.0}; + GLfloat col1[] = {.05, .05, .4, 1.0}; + GLfloat col2[] = {.4, .05, .05, 1.0}; + GLfloat col3[] = {1.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0,GL_POSITION, pos1); + glLightfv(GL_LIGHT0,GL_DIFFUSE, col1); + glLightfv(GL_LIGHT0,GL_SPECULAR, col1); + + glEnable(GL_LIGHT1); + glLightfv(GL_LIGHT1,GL_POSITION, pos2); + glLightfv(GL_LIGHT1,GL_DIFFUSE, col2); + glLightfv(GL_LIGHT1,GL_SPECULAR, col2); + + glEnable(GL_LIGHT2); + glLightfv(GL_LIGHT2,GL_POSITION, pos3); + glLightfv(GL_LIGHT2,GL_DIFFUSE, col3); + glLightfv(GL_LIGHT2,GL_SPECULAR, col3); + + + // Fog + GLfloat fogColor[4] = { 0.4, 0.4, 0.5, 1.0 }; + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogfv(GL_FOG_COLOR, fogColor); + glFogf(GL_FOG_DENSITY, 0.35); + glHint(GL_FOG_HINT, GL_DONT_CARE); + glFogf(GL_FOG_START, 5.0f); + glFogf(GL_FOG_END, 25.0f); + + // scene pos and size + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix_); + set_scene_pos(Vec3f(0.0, 0.0, 0.0), 1.0); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::resizeGL( int _w, int _h ) +{ + update_projection_matrix(); + glViewport(0, 0, _w, _h); + updateGL(); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::paintGL() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode( GL_PROJECTION ); + glLoadMatrixd( projection_matrix_ ); + glMatrixMode( GL_MODELVIEW ); + glLoadMatrixd( modelview_matrix_ ); + + if (draw_mode_) + { + assert(draw_mode_ <= n_draw_modes_); + draw_scene(draw_mode_names_[draw_mode_-1]); + } +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::draw_scene(const std::string& _draw_mode) +{ + if (_draw_mode == "Wireframe") + { + glDisable(GL_LIGHTING); + glutWireTeapot(0.5); + } + + else if (_draw_mode == "Solid Flat") + { + glEnable(GL_LIGHTING); + glShadeModel(GL_FLAT); + glutSolidTeapot(0.5); + } + + else if (_draw_mode == "Solid Smooth") + { + glEnable(GL_LIGHTING); + glShadeModel(GL_SMOOTH); + glutSolidTeapot(0.5); + } + +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::mousePressEvent( QMouseEvent* _event ) +{ + // popup menu + if (_event->button() == RightButton) + { + popup_menu_->exec(QCursor::pos()); + } + + else + { + last_point_ok_ = map_to_sphere( last_point_2D_=_event->pos(), + last_point_3D_ ); + } +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::mouseMoveEvent( QMouseEvent* _event ) +{ + QPoint newPoint2D = _event->pos(); + + if ( (newPoint2D.x()<0) || (newPoint2D.x()>width()) || + (newPoint2D.y()<0) || (newPoint2D.y()>height()) ) return; + + + // Left button: rotate around center_ + // Middle button: translate object + // Left & middle button: zoom in/out + + + float value_y; + Vec3f newPoint3D; + bool newPoint_hitSphere = map_to_sphere( newPoint2D, newPoint3D ); + + float dx = newPoint2D.x() - last_point_2D_.x(); + float dy = newPoint2D.y() - last_point_2D_.y(); + + float w = width(); + float h = height(); + + + + // enable GL context + makeCurrent(); + + + // move in z direction + if ( (_event->state() & LeftButton) && (_event->state() & MidButton)) + { + value_y = radius_ * dy * 3.0 / h; + translate(Vec3f(0.0, 0.0, value_y)); + } + + + // move in x,y direction + else if (_event->state() & MidButton) + { + float z = - (modelview_matrix_[ 2]*center_[0] + + modelview_matrix_[ 6]*center_[1] + + modelview_matrix_[10]*center_[2] + + modelview_matrix_[14]) / + (modelview_matrix_[ 3]*center_[0] + + modelview_matrix_[ 7]*center_[1] + + modelview_matrix_[11]*center_[2] + + modelview_matrix_[15]); + + float aspect = w / h; + float near_plane = 0.01 * radius_; + float top = tan(fovy()/2.0f*M_PI/180.0f) * near_plane; + float right = aspect*top; + + translate(Vec3f( 2.0*dx/w*right/near_plane*z, + -2.0*dy/h*top/near_plane*z, + 0.0f)); + } + + + + // rotate + else if (_event->state() & LeftButton) + { + if (last_point_ok_) + { + if (newPoint_hitSphere = map_to_sphere(newPoint2D, newPoint3D)) + { + Vec3f axis = last_point_3D_ % newPoint3D; + float cos_angle = (last_point_3D_ | newPoint3D); + if ( fabs(cos_angle) < 1.0 ) + { + float angle = 2.0 * acos( cos_angle ) * 180.0 / M_PI; + rotate( axis, angle ); + } + } + } + } + + + // remember this point + last_point_2D_ = newPoint2D; + last_point_3D_ = newPoint3D; + last_point_ok_ = newPoint_hitSphere; + + // trigger redraw + updateGL(); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::mouseReleaseEvent( QMouseEvent* /* _event */ ) +{ + last_point_ok_ = false; +} + + +//----------------------------------------------------------------------------- + + +void QGLViewerWidget::wheelEvent(QWheelEvent* _event) +{ + // Use the mouse wheel to zoom in/out + + float d = -(float)_event->delta() / 120.0 * 0.2 * radius_; + translate(Vec3f(0.0, 0.0, d)); + updateGL(); + _event->accept(); +} + + +//---------------------------------------------------------------------------- + + +void QGLViewerWidget::keyPressEvent( QKeyEvent* _event) +{ + switch( _event->key() ) + { + case Key_C: + if ( glIsEnabled( GL_CULL_FACE ) ) + { + glDisable( GL_CULL_FACE ); + std::cout << "Back face culling: disabled\n"; + } + else + { + glEnable( GL_CULL_FACE ); + std::cout << "Back face culling: enabled\n"; + } + updateGL(); + break; + + case Key_I: + std::cout << "Radius: " << radius_ << std::endl; + std::cout << "Center: " << center_ << std::endl; + break; + + case Key_Space: + case Key_M: + { + double fps = performance(); + std::cout << "fps: " +#if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000) + << std::setiosflags (std::ios::fixed) +#else + << std::setiosflags (std::ios_base::fixed) +#endif + << fps << std::endl; + } + break; + + case Key_Q: + case Key_Escape: + qApp->quit(); + } + _event->ignore(); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::translate( const Vec3f& _trans ) +{ + // Translate the object by _trans + // Update modelview_matrix_ + makeCurrent(); + glLoadIdentity(); + glTranslated( _trans[0], _trans[1], _trans[2] ); + glMultMatrixd( modelview_matrix_ ); + glGetDoublev( GL_MODELVIEW_MATRIX, modelview_matrix_); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::rotate( const Vec3f& _axis, float _angle ) +{ + // Rotate around center center_, axis _axis, by angle _angle + // Update modelview_matrix_ + + Vec3f t( modelview_matrix_[0]*center_[0] + + modelview_matrix_[4]*center_[1] + + modelview_matrix_[8]*center_[2] + + modelview_matrix_[12], + modelview_matrix_[1]*center_[0] + + modelview_matrix_[5]*center_[1] + + modelview_matrix_[9]*center_[2] + + modelview_matrix_[13], + modelview_matrix_[2]*center_[0] + + modelview_matrix_[6]*center_[1] + + modelview_matrix_[10]*center_[2] + + modelview_matrix_[14] ); + + makeCurrent(); + glLoadIdentity(); + glTranslatef(t[0], t[1], t[2]); + glRotated( _angle, _axis[0], _axis[1], _axis[2]); + glTranslatef(-t[0], -t[1], -t[2]); + glMultMatrixd(modelview_matrix_); + glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix_); +} + + +//---------------------------------------------------------------------------- + + +bool +QGLViewerWidget::map_to_sphere( const QPoint& _v2D, Vec3f& _v3D ) +{ + if ( (_v2D.x() >= 0) && (_v2D.x() <= width()) && + (_v2D.y() >= 0) && (_v2D.y() <= height()) ) + { + double x = (double)(_v2D.x() - 0.5*width()) / (double)width(); + double y = (double)(0.5*height() - _v2D.y()) / (double)height(); + double sinx = sin(M_PI * x * 0.5); + double siny = sin(M_PI * y * 0.5); + double sinx2siny2 = sinx * sinx + siny * siny; + + _v3D[0] = sinx; + _v3D[1] = siny; + _v3D[2] = sinx2siny2 < 1.0 ? sqrt(1.0 - sinx2siny2) : 0.0; + + return true; + } + else return false; +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::update_projection_matrix() +{ + makeCurrent(); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + gluPerspective(45.0, (GLfloat) width() / (GLfloat) height(), + 0.01*radius_, 100.0*radius_); + glGetDoublev( GL_PROJECTION_MATRIX, projection_matrix_); + glMatrixMode( GL_MODELVIEW ); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::view_all() +{ + translate( Vec3f( -(modelview_matrix_[0]*center_[0] + + modelview_matrix_[4]*center_[1] + + modelview_matrix_[8]*center_[2] + + modelview_matrix_[12]), + -(modelview_matrix_[1]*center_[0] + + modelview_matrix_[5]*center_[1] + + modelview_matrix_[9]*center_[2] + + modelview_matrix_[13]), + -(modelview_matrix_[2]*center_[0] + + modelview_matrix_[6]*center_[1] + + modelview_matrix_[10]*center_[2] + + modelview_matrix_[14] + + 3.0*radius_) ) ); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::set_scene_pos( const Vec3f& _cog, float _radius ) +{ + center_ = _cog; + radius_ = _radius; + glFogf( GL_FOG_START, _radius ); + glFogf( GL_FOG_END, 4.0*_radius ); + + update_projection_matrix(); + view_all(); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::add_draw_mode(const std::string& _s) +{ + ++n_draw_modes_; + + // insert in popup menu + popup_menu_->insertItem(_s.c_str(), n_draw_modes_); + + // store draw mode + draw_mode_names_.push_back(_s); +} + + +//---------------------------------------------------------------------------- + + +void +QGLViewerWidget::slotPopupMenu(int _id) +{ + // un-check all entries + for (size_t i=1; i <= n_draw_modes_; ++i) + popup_menu_->setItemChecked(i, false); + + // save draw mode + draw_mode_ = _id; + + // check selected draw mode + popup_menu_->setItemChecked(_id, true); +} + + +//---------------------------------------------------------------------------- + + +double +QGLViewerWidget::performance() +{ + setCursor( waitCursor ); + + double fps(0.0); + + makeCurrent(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + OpenMesh::Utils::Timer timer; + + unsigned int frames = 60; + const float angle = 360.0/(float)frames; + unsigned int i; + Vec3f axis; + + glFinish(); + timer.start(); + + for (i=0, axis=Vec3f(1,0,0); i +#include +#include +#include + + +//== FORWARD DECLARATIONS ===================================================== + + +class QPopupMenu; + + +//== CLASS DEFINITION ========================================================= + + +class QGLViewerWidget : public QGLWidget +{ + + Q_OBJECT + +public: + + // Default constructor. + QGLViewerWidget( QWidget* _parent=0, const char* _name=0 ); + + // Destructor. + virtual ~QGLViewerWidget(); + + /* Sets the center and size of the whole scene. + The _center is used as fixpoint for rotations and for adjusting + the camera/viewer (see view_all()). */ + void set_scene_pos( const OpenMesh::Vec3f& _center, float _radius ); + + /* view the whole scene: the eye point is moved far enough from the + center so that the whole scene is visible. */ + void view_all(); + + /// add draw mode to popup menu + void add_draw_mode(const std::string& _s); + + float radius() const { return radius_; } + const OpenMesh::Vec3f& center() const { return center_; } + + const GLdouble* modelview_matrix() const { return modelview_matrix_; } + const GLdouble* projection_matrix() const { return projection_matrix_; } + void set_modelview_matrix(const GLdouble _modelview_matrix[16]) + { memcpy(modelview_matrix_, _modelview_matrix, 16*sizeof(GLdouble)); } + void set_projection_matrix(const GLdouble _projection_matrix[16]) + { memcpy(projection_matrix_, _projection_matrix, 16*sizeof(GLdouble)); } + + float fovy() const { return 45.0f; } + +protected: + + // draw the scene: will be called by the painGL() method. + virtual void draw_scene(const std::string& _draw_mode); + + double performance(void); + +private slots: + + // popup menu clicked + void slotPopupMenu(int _id); + +private: // inherited + + // initialize OpenGL states (triggered by Qt) + void initializeGL(); + + // draw the scene (triggered by Qt) + void paintGL(); + + // handle resize events (triggered by Qt) + void resizeGL( int w, int h ); + +protected: + + // Qt mouse events + virtual void mousePressEvent( QMouseEvent* ); + virtual void mouseReleaseEvent( QMouseEvent* ); + virtual void mouseMoveEvent( QMouseEvent* ); + virtual void wheelEvent( QWheelEvent* ); + virtual void keyPressEvent( QKeyEvent* ); + +private: + + // updates projection matrix + void update_projection_matrix(); + +protected: + // translate the scene and update modelview matrix + void translate(const OpenMesh::Vec3f& _trans); + + // rotate the scene (around its center) and update modelview matrix + void rotate(const OpenMesh::Vec3f& _axis, float _angle); + + OpenMesh::Vec3f center_; + float radius_; + + GLdouble projection_matrix_[16], + modelview_matrix_[16]; + + + // popup menu for draw mode selection + QPopupMenu* popup_menu_; + unsigned int draw_mode_; + unsigned int n_draw_modes_; + std::vector draw_mode_names_; + + + + // virtual trackball: map 2D screen point to unit sphere + bool map_to_sphere(const QPoint& _point, OpenMesh::Vec3f& _result); + + QPoint last_point_2D_; + OpenMesh::Vec3f last_point_3D_; + bool last_point_ok_; + +}; + + +//============================================================================= +#endif // OPENMESHAPPS_QGLVIEWERWIDGET_HH +//============================================================================= + diff --git a/Apps/Unsupported/Streaming/Client/VDPMClientViewerWidget.cc b/Apps/Unsupported/Streaming/Client/VDPMClientViewerWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..4ef38de1b517bd0cc4f831f19f2c1b838266e588 --- /dev/null +++ b/Apps/Unsupported/Streaming/Client/VDPMClientViewerWidget.cc @@ -0,0 +1,1340 @@ + +//== INCLUDES ================================================================= + +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311) +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +// #include "ImageData.h" + + +using OpenMesh::VDPM::debug_print; +using OpenMesh::VDPM::set_debug_print; + +using OpenMesh::VDPM::VHierarchyNode; +using OpenMesh::VDPM::VHierarchyNodeHandle; +using OpenMesh::VDPM::VHierarchyNodeHandleContainer; + + + +#ifdef EXAMPLE_CREATION + +static OpenMesh::Vec3uc myYellow = OpenMesh::Vec3uc(255, 255, 0); +static OpenMesh::Vec3uc myBlue = OpenMesh::Vec3uc(0, 0, 255); +std::map g_index2numdesc_map; + +void VDPMClientViewerWidget::increase_max_descendents(const VHierarchyNodeIndex &_node_index) +{ + g_index2numdesc_map[_node_index] = 2 + g_index2numdesc_map[_node_index]; + + unsigned char tree_id_bits = vhierarchy_.tree_id_bits(); + VHierarchyNodeIndex parent_index + = VHierarchyNodeIndex(_node_index.tree_id(tree_id_bits), _node_index.node_id(tree_id_bits) / 2, tree_id_bits); + + if (parent_index.is_valid(tree_id_bits) == true) + increase_max_descendents(parent_index); +} + +void VDPMClientViewerWidget::increase_cur_descendents(VHierarchyNodeHandle _node_handle) +{ + unsigned int cur_desc = vhierarchy_.node(_node_handle).cur_descendents(); + + vhierarchy_.node(_node_handle).set_cur_descendents(2 + cur_desc); + + VHierarchyNodeHandle parent_handle = vhierarchy_.parent_handle(_node_handle); + if (parent_handle.is_valid()) + increase_cur_descendents(parent_handle); +} + +void VDPMClientViewerWidget::__add_children(const VHierarchyNodeIndex &_node_index, bool update_current) +{ + if (update_current == true) + { + increase_cur_descendents(vhierarchy_.node_handle(_node_index)); + } + else + { + unsigned char tree_id_bits = vhierarchy_.tree_id_bits(); + + VHierarchyNodeIndex lchild_index + = VHierarchyNodeIndex(_node_index.tree_id(tree_id_bits), 2*_node_index.node_id(tree_id_bits), tree_id_bits); + VHierarchyNodeIndex rchild_index + = VHierarchyNodeIndex(_node_index.tree_id(tree_id_bits), 1+2*_node_index.node_id(tree_id_bits), tree_id_bits); + + g_index2numdesc_map[lchild_index] = 1; + g_index2numdesc_map[rchild_index] = 1; + + increase_max_descendents(_node_index); + } +} + +void VDPMClientViewerWidget::mesh_coloring() +{ + MyMesh::VertexIter vIt(mesh_.vertices_begin()), + vEnd(mesh_.vertices_end()); + + VHierarchyNodeHandle node_handle; + float ratio; + unsigned char r, g, b; + + for (; vIt!=vEnd; ++vIt) + { + node_handle = mesh_.data(vIt.handle()).vhierarchy_node_handle(); + ratio = vhierarchy_.node(node_handle).ratio(); + + r = (unsigned char) ((1.0f - ratio) * myYellow[0] + ratio * myBlue[0]); + g = (unsigned char) ((1.0f - ratio) * myYellow[1] + ratio * myBlue[1]); + b = (unsigned char) ((1.0f - ratio) * myYellow[2] + ratio * myBlue[2]); + + mesh_.set_color(vIt.handle(), OpenMesh::Vec3uc(r,g,b)); + } +} + +#endif + + + +void +VDPMClientViewerWidget:: +draw_scene(const std::string &_draw_mode) +{ + //std::cout << frame_ << "-th frame statistics" << std::endl; + + if (adaptive_mode_ == true) + { + + refinement_timer_.start(); + adaptive_refinement(); + refinement_timer_.stop(); + fprintf(refinement_file, "%d %d\n", frame_, (int) refinement_timer_.mseconds()); + +#ifdef EXAMPLE_CREATION + mesh_coloring(); +#endif + } + + render_timer_.start(); + MeshViewerWidget::draw_scene(_draw_mode); + render_timer_.stop(); + fprintf(render_file, "%d %d %d\n", frame_, (int) render_timer_.mseconds(), mesh_.n_faces()); + + ++frame_; +} + + +void +VDPMClientViewerWidget:: +adaptive_refinement() +{ + update_viewing_parameters(); + + MyMesh::HalfedgeHandle v0v1; + float fovy = viewing_parameters_.fovy(); + float tolerance_square = viewing_parameters_.tolerance_square(); + float tan_value = tanf(fovy / 2.0f); + kappa_square_ = 4.0f * tan_value * tan_value * tolerance_square; + + + for (vfront_.begin(); vfront_.end() != true;) + { + VHierarchyNodeHandle + node_handle = vfront_.node_handle(), + parent_handle = vhierarchy_.parent_handle(node_handle); + + if (qrefine(node_handle) == true) + { + if (vhierarchy_.is_leaf_node(node_handle) != true) + { + force_vsplit(node_handle); + } + else + { + //if (qSocket_->bytesAvailable() == 0) + if (session_running_ != true) + { + session_running_ = true; + send_viewing_information(); + } + vfront_.next(); + } + } + else if (vhierarchy_.is_root_node(node_handle) != true && + ecol_legal(parent_handle, v0v1) == true && + qrefine(parent_handle) != true) + { + ecol(parent_handle, v0v1); + } + else + { + vfront_.next(); + } + } + + // free memories taged as 'deleted' + mesh_.garbage_collection(false, true, true); + mesh_.update_face_normals(); +} + + +void +VDPMClientViewerWidget:: +current_max_resolution() +{ + for (vfront_.begin(); vfront_.end() != true;) + { + VHierarchyNodeHandle + node_handle = vfront_.node_handle(), + parent_handle = vhierarchy_.parent_handle(node_handle); + + if (vhierarchy_.is_leaf_node(node_handle) != true) + force_vsplit(node_handle); + else + vfront_.next(); + } + + // free memories taged as 'deleted' + mesh_.garbage_collection(false, true, true); + mesh_.update_face_normals(); +} + + +bool +VDPMClientViewerWidget:: +qrefine(VHierarchyNodeHandle _node_handle) +{ + VHierarchyNode &node = vhierarchy_.node(_node_handle); + OpenMesh::Vec3f p = mesh_.point(node.vertex_handle()); + OpenMesh::Vec3f eye_dir = p - viewing_parameters_.eye_pos(); + float distance = eye_dir.length(); + float distance2 = distance * distance; + float product_value = dot(eye_dir, node.normal()); + + if (outside_view_frustum(p, node.radius()) == true) + return false; + + if (oriented_away(node.sin_square(), distance2, product_value) == true) + return false; + + if (screen_space_error(node.mue_square(), + node.sigma_square(), distance2, product_value) == true) + return false; + + return true; +} + + +void +VDPMClientViewerWidget:: +force_vsplit(VHierarchyNodeHandle node_handle) +{ + MyMesh::VertexHandle vl, vr; + + get_active_cuts(node_handle, vl, vr); + + while (vl == vr) { + force_vsplit(mesh_.data(vl).vhierarchy_node_handle()); + get_active_cuts(node_handle, vl, vr); + } + + vsplit(node_handle, vl, vr); +} + + + +void +VDPMClientViewerWidget:: +vsplit(VHierarchyNodeHandle _node_handle, MyMesh::VertexHandle vl, MyMesh::VertexHandle vr) +{ + // refine + VHierarchyNodeHandle lchild_handle = vhierarchy_.lchild_handle(_node_handle); + VHierarchyNodeHandle rchild_handle = vhierarchy_.rchild_handle(_node_handle); + MyMesh::VertexHandle v0 = vhierarchy_.vertex_handle(lchild_handle); + MyMesh::VertexHandle v1 = vhierarchy_.vertex_handle(rchild_handle); + + mesh_.vertex_split(v0, v1, vl, vr); + mesh_.set_normal(v0, vhierarchy_.normal(lchild_handle)); + mesh_.set_normal(v1, vhierarchy_.normal(rchild_handle)); + mesh_.data(v0).set_vhierarchy_node_handle(lchild_handle); + mesh_.data(v1).set_vhierarchy_node_handle(rchild_handle); + mesh_.status(v0).set_deleted(false); + mesh_.status(v1).set_deleted(false); + + vfront_.remove(_node_handle); + vfront_.add(lchild_handle); + vfront_.add(rchild_handle); +} + + +void +VDPMClientViewerWidget:: +ecol(VHierarchyNodeHandle _node_handle, const MyMesh::HalfedgeHandle& v0v1) +{ + VHierarchyNodeHandle lchild_handle = vhierarchy_.lchild_handle(_node_handle); + VHierarchyNodeHandle rchild_handle = vhierarchy_.rchild_handle(_node_handle); + MyMesh::VertexHandle v0 = vhierarchy_.vertex_handle(lchild_handle); + MyMesh::VertexHandle v1 = vhierarchy_.vertex_handle(rchild_handle); + + // coarsen + mesh_.collapse(v0v1); + mesh_.set_normal(v1, vhierarchy_.normal(_node_handle)); + mesh_.data(v0).set_vhierarchy_node_handle(lchild_handle); + mesh_.data(v1).set_vhierarchy_node_handle(_node_handle); + mesh_.status(v0).set_deleted(false); + mesh_.status(v1).set_deleted(false); + + vfront_.add(_node_handle); + vfront_.remove(lchild_handle); + vfront_.remove(rchild_handle); +} + + +bool +VDPMClientViewerWidget:: +ecol_legal(VHierarchyNodeHandle _parent_handle, MyMesh::HalfedgeHandle& v0v1) +{ + VHierarchyNodeHandle lchild_handle = vhierarchy_.lchild_handle(_parent_handle); + VHierarchyNodeHandle rchild_handle = vhierarchy_.rchild_handle(_parent_handle); + + // test whether lchild & rchild present in the current vfront + if (vfront_.is_active(lchild_handle) != true || vfront_.is_active(rchild_handle) != true) + return false; + + MyMesh::VertexHandle v0, v1; + v0 = vhierarchy_.vertex_handle(lchild_handle); + v1 = vhierarchy_.vertex_handle(rchild_handle); + v0v1 = mesh_.find_halfedge(v0, v1); + + return mesh_.is_collapse_ok(v0v1); +} + +void +VDPMClientViewerWidget:: +get_active_cuts(const VHierarchyNodeHandle _node_handle, MyMesh::VertexHandle &vl, MyMesh::VertexHandle &vr) +{ + MyMesh::VertexVertexIter vv_it; + VHierarchyNodeHandle nnode_handle; + VHierarchyNodeIndex nnode_index; + VHierarchyNodeIndex fund_lcut_index = vhierarchy_.fund_lcut_index(_node_handle); + VHierarchyNodeIndex fund_rcut_index = vhierarchy_.fund_rcut_index(_node_handle); + + vl = MyMesh::InvalidVertexHandle; + vr = MyMesh::InvalidVertexHandle; + + for (vv_it=mesh_.vv_iter(vhierarchy_.vertex_handle(_node_handle)); vv_it; ++vv_it) + { + nnode_handle = mesh_.data(vv_it.handle()).vhierarchy_node_handle(); + nnode_index = vhierarchy_.node_index(nnode_handle); + + if (vl == MyMesh::InvalidVertexHandle && vhierarchy_.is_ancestor(nnode_index, fund_lcut_index) == true) + vl = vv_it.handle(); + if (vr == MyMesh::InvalidVertexHandle && vhierarchy_.is_ancestor(nnode_index, fund_rcut_index) == true) + vr = vv_it.handle(); + + /*if (vl == MyMesh::InvalidVertexHandle && nnode_index.is_ancestor_index(fund_lcut_index) == true) + vl = vv_it.handle(); + if (vr == MyMesh::InvalidVertexHandle && nnode_index.is_ancestor_index(fund_rcut_index) == true) + vr = vv_it.handle();*/ + + if (vl != MyMesh::InvalidVertexHandle && vr != MyMesh::InvalidVertexHandle) + break; + } +} + +bool +VDPMClientViewerWidget:: +outside_view_frustum(const OpenMesh::Vec3f &pos, float radius) +{ + Plane3d frustum_plane[4]; + + viewing_parameters_.frustum_planes(frustum_plane); + + for (int i = 0; i < 4; i++) { + if (frustum_plane[i].signed_distance(pos) < -radius) + return true; + } + + return false; +} + +bool +VDPMClientViewerWidget:: +oriented_away(float sin_square, float distance_square, float product_value) +{ + if (product_value > 0 && product_value*product_value > distance_square * sin_square) + return true; + else + return false; +} + +bool +VDPMClientViewerWidget:: +screen_space_error(float mue_square, float sigma_square, float distance_square, float product_value) +{ + if ((mue_square >= kappa_square_ * distance_square) || + (sigma_square * (distance_square - product_value * product_value) >= kappa_square_ * distance_square * distance_square)) + return false; + else + return true; +} + +void +VDPMClientViewerWidget:: +open_vd_prog_mesh(const char* _filename) +{ + unsigned int i; + unsigned int value; + unsigned int fvi[3]; + char fileformat[16]; + OpenMesh::Vec3f p, normal; + float radius, sin_square, mue_square, sigma_square; + VHierarchyNodeHandleContainer roots; + OpenMesh::VertexHandle vertex_handle; + VHierarchyNodeIndex node_index, lchild_node_index, rchild_node_index, fund_lcut_index, fund_rcut_index; + VHierarchyNodeHandle node_handle, lchild_handle, rchild_handle; + std::map index2handle_map; + + std::ifstream ifs(_filename, std::ios::binary); + if (!ifs) + { + std::cerr << "read error\n"; + exit(1); + } + + // + bool swap = OpenMesh::Endian::local() != OpenMesh::Endian::LSB; + + // read header + ifs.read(fileformat, 10); fileformat[10] = '\0'; + if (std::string(fileformat) != std::string("VDProgMesh")) + { + std::cerr << "Wrong file format.\n"; + ifs.close(); + exit(1); + } + OpenMesh::IO::restore(ifs, n_base_vertices_, swap); + OpenMesh::IO::restore(ifs, n_base_faces_, swap); + OpenMesh::IO::restore(ifs, n_details_, swap); + + mesh_.clear(); + vfront_.clear(); + vhierarchy_.clear(); + + vhierarchy_.set_num_roots(n_base_vertices_); + + // load base mesh + for (i=0; i index2handle_map; + + std::ifstream ifs(_filename, std::ios::binary); + if (!ifs) + { + std::cerr << "read error\n"; + exit(1); + } + + // + bool swap = OpenMesh::Endian::local() != OpenMesh::Endian::LSB; + + // read header + ifs.read(fileformat, 10); fileformat[10] = '\0'; + if (std::string(fileformat) != std::string("VDProgMesh")) + { + std::cerr << "Wrong file format.\n"; + ifs.close(); + exit(1); + } + OpenMesh::IO::restore(ifs, n_base_vertices_, swap); + OpenMesh::IO::restore(ifs, n_base_faces_, swap); + OpenMesh::IO::restore(ifs, n_details_, swap); + + mesh_.clear(); + vfront_.clear(); + vhierarchy_.clear(); + + vhierarchy_.set_num_roots(n_base_vertices_); + + // load base mesh + for (i=0; ikey()) + { + case Key_Plus: + viewing_parameters_.increase_tolerance(); + std::cout << "Scree-space error tolerance^2 is increased by " + << viewing_parameters_.tolerance_square() << std::endl; + updateGL(); + break; + + case Key_Minus: + viewing_parameters_.decrease_tolerance(); + std::cout << "Screen-space error tolerance^2 is decreased by " + << viewing_parameters_.tolerance_square() << std::endl; + updateGL(); + break; + + case Key_A: + adaptive_mode_ = !(adaptive_mode_); + std::cout << "Adaptive refinement mode is " + << ((adaptive_mode_ == true) ? "on" : "off") << std::endl; + updateGL(); + break; + + case Key_D: + set_debug_print(!debug_print()); + break; + + case Key_O: + qFilename_ = QFileDialog::getOpenFileName("d:/data/models/spm/", "*.spm"); + open_vd_base_mesh(qFilename_); + break; + + case Key_BracketLeft: + max_transmitted_datasize_ -= 10000; + std::cout << "Max transmitted data: " << max_transmitted_datasize_ << std::endl; + break; + + case Key_BracketRight: + max_transmitted_datasize_ += 10000; + std::cout << "Max transmitted data: " << max_transmitted_datasize_ << std::endl; + break; + + case Key_Space: + memcpy(reserved_modelview_matrix_, modelview_matrix(), 16*sizeof(GLdouble)); + memcpy(reserved_projection_matrix_, projection_matrix(), 16*sizeof(GLdouble)); + std::cout << "Reserving current view-point" << std::endl; + break; + + case Key_R: + request_base_mesh(); + break; + + case Key_S: + save_views(); + std::cout << "Saving view-points" << std::endl; + break; + + case Key_F: + frame_ = 0; + std::cout << "Frame is set to 0" << std::endl; + break; + + case Key_M: + adaptive_mode_ = false; + current_max_resolution(); + updateGL(); + std::cout << "Current max resolution mesh" << std::endl; + break; + + case Key_V: + vd_streaming_ = !(vd_streaming_); + if (vd_streaming_) + std::cout << "View-dependent streaing mode" << std::endl; + else + std::cout << "Sequential streaming mode" << std::endl; + break; + + case Key_C: + adaptive_mode_ = false; + qCameraFileName_ = QFileDialog::getOpenFileName("./", "*.cmr"); + load_views(qCameraFileName_); + std::cout << "Loading view-points" << std::endl; + updateGL(); + break; + + case Key_9: + save_screen(true); + break; + + case Key_0: + std::cout << "#faces: " << mesh_.n_faces() << std::endl; + break; + + case Key_P: + if (qAnimationTimer_->isActive()) + { + qAnimationTimer_->stop(); + std::cout << "print_statistics mode is stopped!" << std::endl; + } + else + { + qAnimationTimer_->start(0, true); + std::cout << "print_statistics mode is started!" << std::endl; + + adaptive_mode_ = true; + + set_scene_pos( + Vec3f(0.5f*(bbMin_[0] + bbMax_[0]), 0.9f*bbMax_[1], 0.5f*(bbMin_[2] + bbMax_[2])), + 0.15f*(bbMin_ - bbMax_).norm()); + nth_viewpoint_ = 0; + print_statistics(); + } + std::cout << "Frame: " << frame_ << std::endl; + break; + + + case Key_L: + if (qAnimationTimer_->isActive()) + { + qAnimationTimer_->stop(); + std::cout << "look_around mode is stopped!" << std::endl; + } + else + { + qAnimationTimer_->start(0, true); + std::cout << "look_around mode is started!" << std::endl; + + adaptive_mode_ = true; + + set_scene_pos( + Vec3f(0.5f*(bbMin_[0] + bbMax_[0]), 0.9f*bbMax_[1], 0.5f*(bbMin_[2] + bbMax_[2])), + 0.15f*(bbMin_ - bbMax_).norm()); + frame_ = 0; + nth_viewpoint_ = 0; + look_around(); + } + + break; + + case Key_Q: + case Key_Escape: + qApp->quit(); + + default: + this->MeshViewerWidget::keyPressEvent( _event ); + } + + if (!handled) + _event->ignore(); +} + + + + + +void +VDPMClientViewerWidget:: +update_viewing_parameters() +{ + viewing_parameters_.set_fovy(fovy()); + viewing_parameters_.set_aspect((float) width() / (float) height()); + viewing_parameters_.set_modelview_matrix(modelview_matrix()); + + viewing_parameters_.update_viewing_configurations(); +} + + +///////////////////////////////////////////////// +// streaming related functions +///////////////////////////////////////////////// + + + +bool +VDPMClientViewerWidget:: +request_base_mesh() +{ + if (streaming_phase_ != kBaseMesh) + return false; + + if (qFilename_.isEmpty() == true) + { + std::cout << "Please, specify the base mesh filename." << std::endl; + return false; + } + + QDataStream qTcp(qSocket_); + + qTcp << qFilename_.length(); + qTcp << qFilename_; + qSocket_->flush(); + + return true; +} + +bool +VDPMClientViewerWidget:: +receive_base_mesh() +{ + int status; + QDataStream qTcp(qSocket_); + + while (qSocket_->waitForMore(10) < sizeof(int)); + qTcp >> status; + if (status == 0) + { + std::cout << "There is no such a VDPM files in the server side." << std::endl; + return false; + } + + streaming_phase_ = kVSplitHeader; + + std::cout << "A view-dependent streaming is ready." << std::endl; + return true; +} + + +void +VDPMClientViewerWidget:: +send_viewing_information() +{ + session_timer_.start(); + QDataStream qTCP(qSocket_); + qTCP << modelview_matrix()[0] << modelview_matrix()[1] + << modelview_matrix()[2] << modelview_matrix()[3] + << modelview_matrix()[4] << modelview_matrix()[5] + << modelview_matrix()[6] << modelview_matrix()[7] + << modelview_matrix()[8] << modelview_matrix()[9] + << modelview_matrix()[10] << modelview_matrix()[11] + << modelview_matrix()[12] << modelview_matrix()[13] + << modelview_matrix()[14] << modelview_matrix()[15] + << viewing_parameters_.fovy() + << viewing_parameters_.aspect() + << viewing_parameters_.tolerance_square(); + + qSocket_->flush(); + session_timer_.stop(); + fprintf(session_file, "%d %d\n", frame_, (int) session_timer_.mseconds()); + + + global_timer_.stop(); + fprintf(uplink_file, "%d %ld\n", (int) global_timer_.mseconds(), 16*sizeof(double) + 3*sizeof(float)); + global_timer_.cont(); +} + +void +VDPMClientViewerWidget:: +receive_vsplit_header() +{ + if (qSocket_->bytesAvailable() < sizeof(unsigned int)) + return; + + QDataStream qTcp(qSocket_); + + // while (qSocket_->waitForMore(10) < sizeof(unsigned int)); + + qTcp >> n_vsplit_packets_; + + if (n_vsplit_packets_ > 0) + { + streaming_phase_ = kVSplits; + + if (debug_print() == true) + { + std::cout << "Server will transmit " << n_vsplit_packets_ + << " of vsplit packets to me" << std::endl; + } + + receive_vsplit_packets(); + } + else + { + session_running_ = false; + } +} + +void +VDPMClientViewerWidget:: +receive_vsplit_packets() +{ + static unsigned int n_vsplits = 0; + static unsigned int len = (int) (17 * sizeof(float) + 3 * sizeof(int)); + + if (qSocket_->bytesAvailable() < len) + return; + + QString str; + OpenMesh::Vec3f pos; + VHierarchyNodeIndex node_index, fund_lcut_index, fund_rcut_index; + float radius[2]; + OpenMesh::Vec3f normal[2]; + float sin_square[2]; + float mue_square[2]; + float sigma_square[2]; + unsigned int value[3]; + + global_timer_.stop(); + fprintf(downlink_file, "%d %ld\n", (int) global_timer_.mseconds(), qSocket_->bytesAvailable()); + global_timer_.cont(); + + session_timer_.start(); + + while ( qSocket_->bytesAvailable() >= len ) + { + if (vd_streaming_) transmitted_datasize_ += (int) len; + //if (vd_streaming_) transmitted_datasize_ += (int) 3*sizeof(int) + 3*sizeof(float); // only for non-refinement cliet + else transmitted_datasize_ += (int) 3*sizeof(int) + 3*sizeof(float); + + if (max_transmitted_datasize_ > 0) + { + if (transmitted_datasize_ > max_transmitted_datasize_) + { + if (vd_streaming_) transmitted_datasize_ -= (int) len; + //if (vd_streaming_) transmitted_datasize_ -= (int) 3*sizeof(int) + 3*sizeof(float); // only for non-refinement cliet + else transmitted_datasize_ -= (int) 3*sizeof(int) + 3*sizeof(float); + + return; + } + } + + QDataStream qTcp(qSocket_); + qTcp >> pos[0] >> pos[1] >> pos[2] + >> value[0] + >> value[1] + >> value[2] + >> radius[0] + >> (normal[0])[0] >> (normal[0])[1] >> (normal[0])[2] + >> sin_square[0] + >> mue_square[0] >> sigma_square[0] + >> radius[1] + >> (normal[1])[0] >> (normal[1])[1] >> (normal[1])[2] + >> sin_square[1] + >> mue_square[1] >> sigma_square[1]; + + node_index = VHierarchyNodeIndex(value[0]); + fund_lcut_index = VHierarchyNodeIndex(value[1]); + fund_rcut_index = VHierarchyNodeIndex(value[2]); + + update_vhierarchy(pos, + node_index, fund_lcut_index, fund_rcut_index, + radius, normal, sin_square, mue_square, sigma_square); + + + std::cout << "transmitted datasize: " << transmitted_datasize_ << std::endl; + + if (debug_print() == true) + { + std::cout << "Pkg #" << n_vsplits << std::endl; + } + + ++n_vsplits; + + if (n_vsplits >= n_vsplit_packets_) + { + n_vsplits = 0; + streaming_phase_ = kVSplitHeader; + session_running_ = false; + + if (debug_print() == true) + { + std::cout << "transmission of vsplit packets is complete" << std::endl; + } + break; + } + } + + session_timer_.stop(); + fprintf(session_file, "%d %d\n", frame_, (int) session_timer_.mseconds()); + + updateGL(); + + if (n_vsplits != n_vsplit_packets_) + qSessionTimer_->start(300, true); +} + + +void +VDPMClientViewerWidget:: +update_vhierarchy( + const OpenMesh::Vec3f &_pos, // 3D position of v0 + const VHierarchyNodeIndex &_node_index, // vhierarchy index of v1 + const VHierarchyNodeIndex &_fund_lcut_index, // vhierarchy index of fundamental lcut + const VHierarchyNodeIndex &_fund_rcut_index, // vhierarchy index of fundamental rcut + const float _radius[2], // radius of lchild & rchild + const OpenMesh::Vec3f _normal[2], // normal of lchild & rchild + const float _sin_square[2], // sin_square of lchild & rchild + const float _mue_square[2], // mue_square of lchild & rchild + const float _sigma_square[2] // sigma_square of lchild & rchild + ) +{ + OpenMesh::VertexHandle vertex_handle; + VHierarchyNodeHandle node_handle, lchild_handle, rchild_handle; + + node_handle = vhierarchy_.node_handle(_node_index); + vhierarchy_.make_children(node_handle); + + + lchild_handle = vhierarchy_.lchild_handle(node_handle); + rchild_handle = vhierarchy_.rchild_handle(node_handle); + + vhierarchy_.node(node_handle).set_fund_lcut(_fund_lcut_index); + vhierarchy_.node(node_handle).set_fund_rcut(_fund_rcut_index); + + vertex_handle = mesh_.add_vertex(_pos); + vhierarchy_.node(lchild_handle).set_vertex_handle(vertex_handle); + vhierarchy_.node(rchild_handle).set_vertex_handle(vhierarchy_.node(node_handle).vertex_handle()); + + vhierarchy_.node(lchild_handle).set_radius(_radius[0]); + vhierarchy_.node(lchild_handle).set_normal(_normal[0]); + vhierarchy_.node(lchild_handle).set_sin_square(_sin_square[0]); + vhierarchy_.node(lchild_handle).set_mue_square(_mue_square[0]); + vhierarchy_.node(lchild_handle).set_sigma_square(_sigma_square[0]); + + vhierarchy_.node(rchild_handle).set_radius(_radius[1]); + vhierarchy_.node(rchild_handle).set_normal(_normal[1]); + vhierarchy_.node(rchild_handle).set_sin_square(_sin_square[1]); + vhierarchy_.node(rchild_handle).set_mue_square(_mue_square[1]); + vhierarchy_.node(rchild_handle).set_sigma_square(_sigma_square[1]); + +#ifdef EXAMPLE_CREATION + __add_children(_node_index); +#endif +} + + + +///////////////////////////////////////////////// +// example related functions +///////////////////////////////////////////////// + +void VDPMClientViewerWidget::save_views() +{ + FILE *camera_file = fopen("camera.cmr", "w"); + + GLdouble current_modelview_matrix[16], current_projection_matrix[16]; + + memcpy(current_modelview_matrix, modelview_matrix(), 16*sizeof(GLdouble)); + memcpy(current_projection_matrix, projection_matrix(), 16*sizeof(GLdouble)); + + + fprintf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + current_modelview_matrix[0], current_modelview_matrix[1], current_modelview_matrix[2], current_modelview_matrix[3], + current_modelview_matrix[4], current_modelview_matrix[5], current_modelview_matrix[6], current_modelview_matrix[7], + current_modelview_matrix[8], current_modelview_matrix[9], current_modelview_matrix[10], current_modelview_matrix[11], + current_modelview_matrix[12], current_modelview_matrix[13], current_modelview_matrix[14], current_modelview_matrix[15]); + + fprintf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + current_projection_matrix[0], current_projection_matrix[1], current_projection_matrix[2], current_projection_matrix[3], + current_projection_matrix[4], current_projection_matrix[5], current_projection_matrix[6], current_projection_matrix[7], + current_projection_matrix[8], current_projection_matrix[9], current_projection_matrix[10], current_projection_matrix[11], + current_projection_matrix[12], current_projection_matrix[13], current_projection_matrix[14], current_projection_matrix[15]); + + + fprintf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + reserved_modelview_matrix_[0], reserved_modelview_matrix_[1], reserved_modelview_matrix_[2], reserved_modelview_matrix_[3], + reserved_modelview_matrix_[4], reserved_modelview_matrix_[5], reserved_modelview_matrix_[6], reserved_modelview_matrix_[7], + reserved_modelview_matrix_[8], reserved_modelview_matrix_[9], reserved_modelview_matrix_[10], reserved_modelview_matrix_[11], + reserved_modelview_matrix_[12], reserved_modelview_matrix_[13], reserved_modelview_matrix_[14], reserved_modelview_matrix_[15]); + + fprintf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + reserved_projection_matrix_[0], reserved_projection_matrix_[1], reserved_projection_matrix_[2], reserved_projection_matrix_[3], + reserved_projection_matrix_[4], reserved_projection_matrix_[5], reserved_projection_matrix_[6], reserved_projection_matrix_[7], + reserved_projection_matrix_[8], reserved_projection_matrix_[9], reserved_projection_matrix_[10], reserved_projection_matrix_[11], + reserved_projection_matrix_[12], reserved_projection_matrix_[13], reserved_projection_matrix_[14], reserved_projection_matrix_[15]); + + fclose(camera_file); +} + + +void VDPMClientViewerWidget::load_views(const char *camera_filename) +{ + FILE *camera_file = fopen(camera_filename, "r"); + + GLdouble current_modelview_matrix[16], current_projection_matrix[16]; + + + fscanf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + &(current_modelview_matrix[0]), &(current_modelview_matrix[1]), &(current_modelview_matrix[2]), &(current_modelview_matrix[3]), + &(current_modelview_matrix[4]), &(current_modelview_matrix[5]), &(current_modelview_matrix[6]), &(current_modelview_matrix[7]), + &(current_modelview_matrix[8]), &(current_modelview_matrix[9]), &(current_modelview_matrix[10]), &(current_modelview_matrix[11]), + &(current_modelview_matrix[12]), &(current_modelview_matrix[13]), &(current_modelview_matrix[14]), &(current_modelview_matrix[15])); + + + fscanf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + &(current_projection_matrix[0]), &(current_projection_matrix[1]), &(current_projection_matrix[2]), &(current_projection_matrix[3]), + &(current_projection_matrix[4]), &(current_projection_matrix[5]), &(current_projection_matrix[6]), &(current_projection_matrix[7]), + &(current_projection_matrix[8]), &(current_projection_matrix[9]), &(current_projection_matrix[10]), &(current_projection_matrix[11]), + &(current_projection_matrix[12]), &(current_projection_matrix[13]), &(current_projection_matrix[14]), &(current_projection_matrix[15])); + + + fscanf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + &(reserved_modelview_matrix_[0]), &(reserved_modelview_matrix_[1]), &(reserved_modelview_matrix_[2]), &(reserved_modelview_matrix_[3]), + &(reserved_modelview_matrix_[4]), &(reserved_modelview_matrix_[5]), &(reserved_modelview_matrix_[6]), &(reserved_modelview_matrix_[7]), + &(reserved_modelview_matrix_[8]), &(reserved_modelview_matrix_[9]), &(reserved_modelview_matrix_[10]), &(reserved_modelview_matrix_[11]), + &(reserved_modelview_matrix_[12]), &(reserved_modelview_matrix_[13]), &(reserved_modelview_matrix_[14]), &(reserved_modelview_matrix_[15])); + + + fscanf(camera_file, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\n", + &(reserved_projection_matrix_[0]), &(reserved_projection_matrix_[1]), &(reserved_projection_matrix_[2]), &(reserved_projection_matrix_[3]), + &(reserved_projection_matrix_[4]), &(reserved_projection_matrix_[5]), &(reserved_projection_matrix_[6]), &(reserved_projection_matrix_[7]), + &(reserved_projection_matrix_[8]), &(reserved_projection_matrix_[9]), &(reserved_projection_matrix_[10]), &(reserved_projection_matrix_[11]), + &(reserved_projection_matrix_[12]), &(reserved_projection_matrix_[13]), &(reserved_projection_matrix_[14]), &(reserved_projection_matrix_[15])); + + fclose(camera_file); + + set_modelview_matrix(current_modelview_matrix); + set_projection_matrix(current_projection_matrix); + + adaptive_mode_ = false; +} + +void VDPMClientViewerWidget::print_statistics() +{ + const float angle = 360.0/(float)n_viewpoints_; + Vec3f axis = Vec3f(0,1,0); + Vec3f delta = Vec3f(0, 0.7f*(bbMin_[1] - bbMax_[1])/n_viewpoints_, 0); + + rotate(axis, -angle); + set_scene_pos(center() + delta, 1.0f * radius() ); + + updateGL(); + + if (++nth_viewpoint_ < n_viewpoints_) + qAnimationTimer_->start(500, true); +} + +void VDPMClientViewerWidget::look_around() +{ + const float angle = 360.0/(float)n_viewpoints_; + Vec3f axis = Vec3f(0,1,0); + Vec3f delta = Vec3f(0, 0.7f*(bbMin_[1] - bbMax_[1])/n_viewpoints_, 0); + + rotate(axis, -angle); + set_scene_pos(center() + delta, 1.0f * radius() ); + + updateGL(); + + save_screen(true); + + if (++nth_viewpoint_ < n_viewpoints_) + qAnimationTimer_->start(3000, true); +} + + +void VDPMClientViewerWidget::save_screen(bool _flag) +{ + setCursor( waitCursor ); + + if (_flag == true) // shot from the reserved view-point + { + GLdouble current_modelview_matrix[16]; + GLdouble current_projection_matrix[16]; + bool current_adaptive_mode = adaptive_mode_; + + memcpy(current_modelview_matrix, modelview_matrix(), 16*sizeof(GLdouble)); + memcpy(current_projection_matrix, projection_matrix(), 16*sizeof(GLdouble)); + + set_modelview_matrix(reserved_modelview_matrix_); + set_projection_matrix(reserved_projection_matrix_); + adaptive_mode_ = false; + + updateGL(); + + // shot from the reserved view-point + char rfilename[256]; + sprintf(rfilename, "rview%03d.bmp", nth_viewpoint_); + screen_capture(rfilename); + std::cout << "shot from the reserved view-point" << std::endl; + + + set_modelview_matrix(current_modelview_matrix); + set_projection_matrix(current_projection_matrix); + adaptive_mode_ = current_adaptive_mode; + } + + updateGL(); + + // shot from the current view-point + char cfilename[256]; + sprintf(cfilename, "cview%03d.bmp", nth_viewpoint_); + screen_capture(cfilename); + std::cout << "shot from the current view-point" << std::endl; + + + setCursor( pointingHandCursor ); +} + +void VDPMClientViewerWidget::screen_capture(const char * /* _filename */) +{ +// CImageData image(width(), height()); + +// glReadBuffer(GL_BACK); +// glReadPixels(0, 0, width(), height(), GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) image.rgbMap()); + +// image.SaveBMP(_filename, width(), height()); +} + diff --git a/Apps/Unsupported/Streaming/Client/VDPMClientViewerWidget.hh b/Apps/Unsupported/Streaming/Client/VDPMClientViewerWidget.hh new file mode 100644 index 0000000000000000000000000000000000000000..d5cec4d7f2fafe79727374d1cdc0596e53e4c560 --- /dev/null +++ b/Apps/Unsupported/Streaming/Client/VDPMClientViewerWidget.hh @@ -0,0 +1,320 @@ +#ifndef OPENMESH_APPS_VDPMSTREAMING_CLIENT_VDPMCLIENTVIEWERWIDGET_HH +#define OPENMESH_APPS_VDPMSTREAMING_CLIENT_VDPMCLIENTVIEWERWIDGET_HH + +//== INCLUDES ================================================================= + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +//#include + + + +typedef MeshViewerWidgetT MeshViewerWidget; + + + +using OpenMesh::VDPM::VDPMStreamingPhase; +using OpenMesh::VDPM::kVSplitHeader; +using OpenMesh::VDPM::kVSplits; +using OpenMesh::VDPM::kBaseMesh; + +using OpenMesh::VDPM::Plane3d; + +using OpenMesh::VDPM::VFront; +using OpenMesh::VDPM::VHierarchy; +using OpenMesh::VDPM::VHierarchyNodeIndex; +using OpenMesh::VDPM::VHierarchyNodeHandle; +using OpenMesh::VDPM::ViewingParameters; +using OpenMesh::VDPM::set_debug_print; + + +//== CLASS DEFINITION ========================================================= + + +class VDPMClientViewerWidget : public MeshViewerWidget +{ + + Q_OBJECT + +public: + VDPMClientViewerWidget(QWidget *_parent=0, const char *_name=0) + : MeshViewerWidget(_parent, _name) + { + set_debug_print(true); + adaptive_mode_ = false; + + qSessionTimer_ = new QTimer(this); + qSocket_ = new QSocket(this); + streaming_phase_ = kBaseMesh; + session_running_ = false; + + + connect(qSessionTimer_, SIGNAL(timeout()), + this, SLOT(session_timer_check())); + + connect(qSessionTimer_, SIGNAL(timeout()), + this, SLOT(socketReadyRead())); + + // connect signal-slots about QSocket + connect(qSocket_, SIGNAL(connected()), + this, SLOT(socketConnected())); + + connect(qSocket_, SIGNAL(connectionClosed()), + this, SLOT(socketConnectionClosed())); + + connect(qSocket_, SIGNAL(readyRead()), + this, SLOT(socketReadyRead())); + + connect(qSocket_, SIGNAL(error(int)), + this, SLOT(socketError(int))); + + + look_around_mode_ = false; + frame_ = 0; + n_viewpoints_ = 60; + + global_timer_.reset(); + global_timer_.start(); + render_timer_.reset(); + refinement_timer_.reset(); + session_timer_.reset(); + + qAnimationTimer_ = new QTimer(this); + + connect(qAnimationTimer_, SIGNAL(timeout()), + this, SLOT(look_around())); + //connect(qAnimationTimer_, SIGNAL(timeout()), + // this, SLOT(print_statistics())); + + + uplink_file = fopen("uplink.txt", "w"); + downlink_file = fopen("downlink.txt", "w"); + + render_file = fopen("render.txt", "w"); + refinement_file = fopen("refinement.txt", "w"); + session_file = fopen("session.txt", "w"); + + vd_streaming_ = true; + max_transmitted_datasize_ = 0; + transmitted_datasize_ = 0; + } + + ~VDPMClientViewerWidget() + { + fclose(uplink_file); + fclose(downlink_file); + + fclose(render_file); + fclose(refinement_file); + fclose(session_file); + } + + + void connectToServer( std::string& _server_name, + int _port= VDPM_STREAMING_PORT ) + { + qSocket_->connectToHost( _server_name.c_str(), _port ); + } + + void openBaseMesh( std::string& _base_mesh ) + { + open_vd_base_mesh( qFilename_ = _base_mesh.c_str() ); + std::cout << "spm file: " << qFilename_ << std::endl; + } + +// socket related slots +private slots: + + void closeConnection() + { + close(); + if (qSocket_->state() == QSocket::Closing) // we have a delayed close. + { + connect(this, SIGNAL(delayedCloseFinished()), SLOT(socketClosed())); + } + else // the qSocket is closed. + { + socketClosed(); + } + } + + void socketReadyRead() + { + switch( streaming_phase_) + { + case kVSplits: receive_vsplit_packets(); break; + case kVSplitHeader: receive_vsplit_header(); break; + case kBaseMesh: receive_base_mesh(); break; + } + + } + + void socketConnected() + { + std::cout << "Connected to server" << std::endl; + } + + void socketConnectionClosed() + { + std::cout << "Connection closed by the server" << std::endl; + } + + void socketClosed() + { + std::cout << "Connection closed" << std::endl; + } + + void socketError(int e) + { + std::cout << "Error number " << e << " occurred" << std::endl; + } + + void look_around(); + void print_statistics(); + + + void session_timer_check() + { + std::cout << "Session Timer works" << std::endl; + } + +// for view-dependent PM +private: + VHierarchy vhierarchy_; + //unsigned char tree_id_bits_; + VFront vfront_; + ViewingParameters viewing_parameters_; + float kappa_square_; + bool adaptive_mode_; + + unsigned int n_base_vertices_; + unsigned int n_base_edges_; + unsigned int n_base_faces_; + unsigned int n_details_; + +private: + + bool outside_view_frustum(const OpenMesh::Vec3f &pos, float radius); + bool oriented_away(float sin_square, float distance_square, + float product_value); + bool screen_space_error(float mue_square, float sigma_square, + float distance_square, float product_value); + void update_viewing_parameters(); + + virtual void keyPressEvent(QKeyEvent *_event); + +protected: + + /// inherited drawing method + virtual void draw_scene(const std::string& _draw_mode); + + +public: + + void open_vd_prog_mesh(const char* _filename); + + unsigned int num_base_vertices() const { return n_base_vertices_; } + unsigned int num_base_edges() const { return n_base_edges_; } + unsigned int num_base_faces() const { return n_base_faces_; } + unsigned int num_details() const { return n_details_; } + + void adaptive_refinement(); + bool qrefine(VHierarchyNodeHandle _node_handle); + void force_vsplit(VHierarchyNodeHandle _node_handle); + bool ecol_legal(VHierarchyNodeHandle _parent_handle, MyMesh::HalfedgeHandle& v0v1); + + void get_active_cuts(VHierarchyNodeHandle _node_handle, MyMesh::VertexHandle &vl, MyMesh::VertexHandle &vr); + void vsplit(VHierarchyNodeHandle _node_handle, MyMesh::VertexHandle vl, MyMesh::VertexHandle vr); + void ecol(VHierarchyNodeHandle _parent_handle, const MyMesh::HalfedgeHandle& v0v1); + + void init_vfront(); + + // streaming realted functions +private: + QTimer *qSessionTimer_; + QSocket *qSocket_; + QString qFilename_; + bool session_running_; + VDPMStreamingPhase streaming_phase_; + unsigned int n_vsplit_packets_; + +public: + void connect_to_server(); + bool request_base_mesh(); + bool receive_base_mesh(); + void send_viewing_information(); + void receive_vsplit_header(); + void receive_vsplit_packets(); + void open_vd_base_mesh(const char* _filename); + void update_vhierarchy( + const OpenMesh::Vec3f &_pos, // 3D position of v0 + const VHierarchyNodeIndex &_v, // vhierarchy index of v1 + const VHierarchyNodeIndex &_fund_lcut_index, // vhierarchy index of fundamental lcut + const VHierarchyNodeIndex &_fund_rcut_index, // vhierarchy index of fundamental rcut + const float _radius[2], // radius of lchild & rchild + const OpenMesh::Vec3f _normal[2], // normal of lchild & rchild + const float _sin_square[2], // sin_square of lchild & rchild + const float _mue_square[2], // mue_square of lchild & rchild + const float _sigma_square[2] // sigma_square of lchild & rchild + ); + + + // for example +private: + QTimer *qAnimationTimer_; + QString qCameraFileName_; + MyMesh::Point bbMin_, bbMax_; + unsigned int frame_; + int max_transmitted_datasize_; + int transmitted_datasize_; + bool vd_streaming_; + + unsigned int nth_viewpoint_; + unsigned int n_viewpoints_; + bool look_around_mode_; + GLdouble reserved_modelview_matrix_[16]; + GLdouble reserved_projection_matrix_[16]; + + FILE *uplink_file; + FILE *downlink_file; + FILE *render_file; + FILE *refinement_file; + FILE *session_file; + +public: + void save_screen(bool _flag); + void save_views(); + void load_views(const char *camera_filename); + void screen_capture(const char *_filename); + void current_max_resolution(); + + OpenMesh::Utils::Timer global_timer_; + OpenMesh::Utils::Timer render_timer_; + OpenMesh::Utils::Timer refinement_timer_; + OpenMesh::Utils::Timer session_timer_; + + + +#ifdef EXAMPLE_CREATION + void increase_max_descendents(const VHierarchyNodeIndex &node_index); + void increase_cur_descendents(VHierarchyNodeHandle _node_handle); + void __add_children(const VHierarchyNodeIndex &node_index, bool update_current = true); + void mesh_coloring(); +#endif +}; + +#endif //OPENMESH_APPS_VDPMSTREAMING_CLIENT_VDPMCLIENTVIEWERWIDGET_HH defined diff --git a/Apps/Unsupported/Streaming/Client/VDPMStreamingClient.cc b/Apps/Unsupported/Streaming/Client/VDPMStreamingClient.cc new file mode 100644 index 0000000000000000000000000000000000000000..c8efcf929444b078cf5ec6bba3a3cad18987037a --- /dev/null +++ b/Apps/Unsupported/Streaming/Client/VDPMStreamingClient.cc @@ -0,0 +1,73 @@ +// #ifdef _MSC_VER +// # pragma warning(disable: 4267 4311) +// #endif + +#include +#include + +#include +#include + +//#include +#include +//#include +//#include + +#include +#include +#include + + +int main(int argc, char **argv) +{ + // OpenGL check + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication app(argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + std::cerr << "This system has no OpenGL support.\n"; + return -1; + } + + // + int c; + int port = -1; + std::string bmesh = ""; + std::string sname = "localhost"; + + while ( (c=getopt(argc, argv, "b:p:s:"))!=-1 ) + { + switch(c) + { + case 'b': bmesh = optarg; break; + case 's': sname = optarg; break; + case 'p': { std::istringstream istr(optarg); istr >> port; } break; + } + } + + // create widget + VDPMClientViewerWidget* w = + new VDPMClientViewerWidget(0, "VDPMClientViewer"); + + if (port == -1) + w->connectToServer( sname ); + else + w->connectToServer( sname, port ); + + w->resize(800, 800); + app.setMainWidget(w); + w->show(); + + w->openBaseMesh( bmesh ); + + // print usage info + std::cout << "\n\n" + << "Press Minus : Coarsen mesh\n" + << " Plus : Refine mesh\n" + << " Home : Coarsen down to base mesh\n" + << " End : Refine up to finest mesh\n" + << "\n"; + + return app.exec(); +} + diff --git a/Apps/Unsupported/Streaming/Server/ACGMakefile b/Apps/Unsupported/Streaming/Server/ACGMakefile new file mode 100644 index 0000000000000000000000000000000000000000..b9cfe76569df9cbdada3569f69e763705e5ad8d2 --- /dev/null +++ b/Apps/Unsupported/Streaming/Server/ACGMakefile @@ -0,0 +1,18 @@ +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Config +#============================================================================== + +CXX_CFLAGS += -DQT_THREAD_SUPPORT + +SUBDIRS = $(call find-subdirs) + +PACKAGES := qt glut opengl + +PROJ_LIBS := OpenMesh/Core OpenMesh/Tools + +MODULES := moc cxx + + +#== SYSTEM PART -- DON'T TOUCH ============================================== +include $(ACGMAKE)/Rules +#============================================================================== diff --git a/Apps/Unsupported/Streaming/Server/ServerSideVDPM.cc b/Apps/Unsupported/Streaming/Server/ServerSideVDPM.cc new file mode 100644 index 0000000000000000000000000000000000000000..12e4b97553ba5b410c0ba89b6384f1945b1411ae --- /dev/null +++ b/Apps/Unsupported/Streaming/Server/ServerSideVDPM.cc @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include +#include +#include "ServerSideVDPM.hh" + + +using OpenMesh::VDPM::VHierarchyNode; +using OpenMesh::VDPM::VHierarchyNodeIndex; +using OpenMesh::VDPM::VHierarchyNodeHandle; + + +void +ServerSideVDPM:: +clear() +{ + points_.clear(); + triangles_.clear(); + vhierarchy_.clear(); + + n_base_vertices_ = 0; + n_base_faces_ = 0; + n_details_ = 0; +} + +OpenMesh::VertexHandle +ServerSideVDPM:: +add_vertex(const OpenMesh::Vec3f &p) +{ + points_.push_back(p); + + return OpenMesh::VertexHandle(points_.size() - 1); +} + +OpenMesh::FaceHandle +ServerSideVDPM:: +add_face(const unsigned int _triangle[3]) +{ + OpenMesh::Vec3ui fvi; + + fvi[0] = _triangle[0]; + fvi[1] = _triangle[1]; + fvi[2] = _triangle[2]; + + triangles_.push_back(fvi); + + return OpenMesh::FaceHandle(triangles_.size() - 1); +} + + +void +ServerSideVDPM:: +vhierarchy_roots(VHierarchyNodeHandleContainer &roots) const +{ + unsigned int i; + + roots.clear(); + + for (i=0; i index2handle_map; + + std::ifstream ifs(_filename, std::ios::binary); + if (!ifs) + { + std::cerr << "read error\n"; + return false; + } + + // + bool swap = OpenMesh::Endian::local() != OpenMesh::Endian::LSB; + + // read header + ifs.read(fileformat, 10); fileformat[10] = '\0'; + if (std::string(fileformat) != std::string("VDProgMesh")) + { + std::cerr << "Wrong file format.\n"; + ifs.close(); + return false; + } + + clear(); + + OpenMesh::IO::restore(ifs, n_base_vertices_, swap); + OpenMesh::IO::restore(ifs, n_base_faces_, swap); + OpenMesh::IO::restore(ifs, n_details_, swap); + + // update tree_id_bits_ + vhierarchy_.set_num_roots(n_base_vertices_); + + + // read base_mesh + for (i=0; i +#include +#include +#include + + +using OpenMesh::VDPM::VHierarchy; +using OpenMesh::VDPM::VHierarchyNodeHandleContainer; + + +class ServerSideVDPM +{ +private: + + char name_[256]; + + std::vector points_; // points related to this pm + std::vector triangles_; // base mesh triangles + VHierarchy vhierarchy_; + + unsigned int n_base_vertices_; + unsigned int n_base_faces_; + unsigned int n_details_; + unsigned char tree_id_bits_; + +public: + + ServerSideVDPM() { clear(); } + void clear(); + + const char* name() const { return name_; } + + void get_name(char _name[256]) { strcpy(_name, name_); } + void set_name(const char _name[256]) { strcpy(name_, _name); } + + + std::string + basename(const std::string& _f) + { + std::string::size_type dot = _f.rfind("/"); + if (dot == std::string::npos) + return std::string(_f); + return std::string(_f.substr(dot+1, _f.length()-(dot+1))); + } + + + bool is_same_name(const char _name[256]) + { + return (basename( name_ ) == basename( _name )); + } + + OpenMesh::VertexHandle add_vertex(const OpenMesh::Vec3f &p); + OpenMesh::FaceHandle add_face(const unsigned int _triangle[3]); + + const OpenMesh::Vec3f& point(OpenMesh::VertexHandle _vertex_handle) const + { + return points_[_vertex_handle.idx()]; + } + + OpenMesh::Vec3f& point(OpenMesh::VertexHandle _vertex_handle) + { + return points_[_vertex_handle.idx()]; + } + + const VHierarchy& vhierarchy() const { return vhierarchy_; } + VHierarchy& vhierarchy() { return vhierarchy_; } + + void vhierarchy_roots(VHierarchyNodeHandleContainer &roots) const; + + unsigned int n_base_vertices() const { return n_base_vertices_; } + unsigned int n_base_faces() const { return n_base_faces_; } + unsigned int n_details() const { return n_details_; } + + bool open_vd_prog_mesh(const char *_filename); +}; + +std::ostream& operator << ( std::ostream& _os, const ServerSideVDPM& _o ); + + +typedef std::vector ServerSideVDPMContainer; +typedef std::list ServerSideVDPMList; + +#endif //OPENMESH_APP_SERVERSIDEVDPM_HH defined + diff --git a/Apps/Unsupported/Streaming/Server/VDPMServerSession.cc b/Apps/Unsupported/Streaming/Server/VDPMServerSession.cc new file mode 100644 index 0000000000000000000000000000000000000000..2203b8ff3114536d6ba5ab6b0418d1cb972a1c43 --- /dev/null +++ b/Apps/Unsupported/Streaming/Server/VDPMServerSession.cc @@ -0,0 +1,467 @@ +#include +#include +#include +#include + + +using OpenMesh::VDPM::VHierarchyNode; +using OpenMesh::VDPM::Plane3d; +using OpenMesh::VDPM::InvalidVHierarchyNodeHandle; +using OpenMesh::VDPM::debug_print; + + +bool +VDPMServerSession:: +set_vdpm(const char _vdpm_name[256]) +{ +#ifdef DEBUG_COUT + if (debug_print() == true) + { + std::cout << "Setting vdpm" << std::endl; + } +#endif + vdpm_ = ((VDPMServerViewerWidget *) ((VDPMServerSocket *) parent())->parent())->get_vdpm(_vdpm_name); + if (vdpm_ == NULL) + return false; + + vhierarchy_ = &vdpm_->vhierarchy(); + + VHierarchyNodeHandleContainer roots; + unsigned int n_details; + + vdpm_->vhierarchy_roots(roots); + n_details = vdpm_->n_details(); + + //vfront_.init(roots, n_details); + + // vertex hierarchy window + vhwindow_.set_vertex_hierarchy(vdpm_->vhierarchy()); + vhwindow_.init(roots); + + +#ifdef DEBUG_COUT + if (debug_print() == true) + { + std::cout << "setting vdpm ended" << std::endl; + } +#endif + + return true; +} + + +void +VDPMServerSession:: +sendBaseMeshToClient() +{ +#ifdef DEBUG_COUT + if (debug_print() == true) + { + std::cout << "starting sendBaseMeshToClient()" << std::endl; + } +#endif + + + +#ifdef DEBUG_COUT + if (debug_print() == true) + { + std::cout << "sendBaseMeshToClient() is done" << std::endl; + } +#endif +} + +void +VDPMServerSession:: +send_vsplit_packets() +{ + viewing_parameters_.update_viewing_configurations(); + vsplits_.clear(); + + if (((VDPMServerViewerWidget *) this->parent()->parent())->vd_streaming()) + adaptive_refinement(); + else + sequential_refinement(); + + + if (debug_print() == true) + { + std::cout << "adaptive refinement is done on the server side" << std::endl; + } + + stream_vsplits(); + + if (debug_print() == true) + { + std::cout << "streameing vsplits is done" << std::endl; + } + + if (transmission_complete_ == true) + { + std::cout << "transmission is completed" << std::endl; + } + + if (debug_print() == true) + { + std::cout << "send_vsplit_packets() is done" << std::endl; + } +} + + +void +VDPMServerSession:: +readBaseMeshRequestFromClient() +{ + int status; + unsigned int string_length; + QDataStream qTcp(this); + QString vdpm_name; + + while (waitForMore(10) < sizeof(int)); + qTcp >> string_length; + + while (waitForMore(10) < (string_length*sizeof(char))); + qTcp >> vdpm_name; + + if (set_vdpm(vdpm_name) != true) status = 0; + else status = 1; + + qTcp << status; + flush(); + + if (status == 1) + streaming_phase_ = kVSplits; +} + + +void +VDPMServerSession:: +readViewingParametersFromClient() +{ + double modelview_matrix[16]; + float fovy; + float aspect; + float tolerance_square; + + while (waitForMore(10) < 16*sizeof(double) + 3*sizeof(float)); + + QDataStream qTCP(this); + qTCP >> modelview_matrix[0] + >> modelview_matrix[1] + >> modelview_matrix[2] + >> modelview_matrix[3] + >> modelview_matrix[4] + >> modelview_matrix[5] + >> modelview_matrix[6] + >> modelview_matrix[7] + >> modelview_matrix[8] + >> modelview_matrix[9] + >> modelview_matrix[10] + >> modelview_matrix[11] + >> modelview_matrix[12] + >> modelview_matrix[13] + >> modelview_matrix[14] + >> modelview_matrix[15] + >> fovy + >> aspect + >> tolerance_square; + + viewing_parameters_.set_modelview_matrix(modelview_matrix); + viewing_parameters_.set_fovy(fovy); + viewing_parameters_.set_aspect(aspect); + viewing_parameters_.set_tolerance_square(tolerance_square); + + send_vsplit_packets(); + + fprintf(mem_file, "%d %d %d\n", + memory_requirements_using_window(true), + memory_requirements_using_window(false), + memory_requirements_using_vfront()); +} + + +void +VDPMServerSession:: +PrintOutVFront() +{ +} + +void +VDPMServerSession:: +stream_vsplits() +{ + // send header (i.e., # of vsplits) + unsigned int i; + VHierarchyNodeHandle node_handle; + OpenMesh::Vec3f pos; + VHierarchyNodeIndex node_index, fund_lcut_index, fund_rcut_index; + float lchild_radius, rchild_radius; + OpenMesh::Vec3f lchild_normal, rchild_normal; + float lchild_sin_square, rchild_sin_square; + float lchild_mue_square, rchild_mue_square; + float lchild_sigma_square, rchild_sigma_square; + unsigned int n_vsplit_packets = (unsigned int) vsplits_.size(); + + QDataStream qTcp(this); + qTcp << n_vsplit_packets; + flush(); + + for (i=0; ilchild_handle(node_handle); + VHierarchyNodeHandle rchild_handle = vhierarchy_->rchild_handle(node_handle); + + VHierarchyNode &node = vhierarchy_->node(node_handle); + VHierarchyNode &lchild = vhierarchy_->node(lchild_handle); + VHierarchyNode &rchild = vhierarchy_->node(rchild_handle); + + pos = vdpm_->point(lchild.vertex_handle()); + node_index = node.node_index(); + fund_lcut_index = node.fund_lcut_index(); + fund_rcut_index = node.fund_rcut_index(); + lchild_radius = lchild.radius(); rchild_radius = rchild.radius(); + lchild_normal = lchild.normal(); rchild_normal = rchild.normal(); + lchild_sin_square = lchild.sin_square(); rchild_sin_square = rchild.sin_square(); + lchild_mue_square = lchild.mue_square(); rchild_mue_square = rchild.mue_square(); + lchild_sigma_square = lchild.sigma_square(); rchild_sigma_square = rchild.sigma_square(); + + qTcp << pos[0] << pos[1] << pos[2] + << node_index.value() + << fund_lcut_index.value() + << fund_rcut_index.value() + << lchild_radius + << lchild_normal[0] << lchild_normal[1] << lchild_normal[2] + << lchild_sin_square + << lchild_mue_square + << lchild_sigma_square + << rchild_radius + << rchild_normal[0] << rchild_normal[1] << rchild_normal[2] + << rchild_sin_square + << rchild_mue_square + << rchild_sigma_square; + flush(); // socket flush + + if (debug_print() == true) + { + std::cout << "Write to client " << i << "-th vsplit packets: " << std::endl; + } + + } +} + + +void +VDPMServerSession:: +adaptive_refinement() +{ + float fovy = viewing_parameters_.fovy(); + float tolerance_square = viewing_parameters_.tolerance_square(); + float tan_value = tanf(fovy / 2.0f); + kappa_square_ = 4.0f * tan_value * tan_value * tolerance_square; + + transmission_complete_ = true; + for (vhwindow_.begin(); vhwindow_.end() != true; vhwindow_.next()) + { + VHierarchyNodeHandle node_handle = vhwindow_.node_handle(); + + if (vhierarchy_->is_leaf_node(node_handle) != true) + { + transmission_complete_ = false; + if (qrefine(node_handle) == true) + { + force_vsplit(node_handle); + } + } + } +} + +void +VDPMServerSession:: +sequential_refinement() +{ + for (vhwindow_.begin(); vhwindow_.end() != true; vhwindow_.next()) + { + VHierarchyNodeHandle node_handle = vhwindow_.node_handle(); + + if (vhierarchy_->is_leaf_node(node_handle) != true) + force_vsplit(node_handle); + + if (vsplits_.size() > 10) + break; + } +} + + +bool +VDPMServerSession:: +qrefine(VHierarchyNodeHandle _node_handle) +{ + VHierarchyNode &node = vhierarchy_->node(_node_handle); + OpenMesh::Vec3f p = vdpm_->point(node.vertex_handle()); + OpenMesh::Vec3f eye_dir = p - viewing_parameters_.eye_pos(); + float distance = eye_dir.length(); + float distance2 = distance * distance; + float product_value = dot(eye_dir, node.normal()); + + if (outside_view_frustum(p, node.radius()) == true) + return false; + if (oriented_away(node.sin_square(), distance2, product_value) == true) + return false; + if (screen_space_error(node.mue_square(), node.sigma_square(), distance2, product_value) == true) + return false; + + return true; +} + + +bool +VDPMServerSession:: +outside_view_frustum(const OpenMesh::Vec3f &pos, float radius) +{ + Plane3d frustum_plane[4]; + viewing_parameters_.frustum_planes(frustum_plane); + + for (int i = 0; i < 4; i++) { + if (frustum_plane[i].signed_distance(pos) < -radius) + return true; + } + + return false; +} + +bool +VDPMServerSession:: +oriented_away(float sin_square, float distance_square, float product_value) +{ + if (product_value > 0 && product_value*product_value > distance_square * sin_square) + return true; + else + return false; +} + +bool +VDPMServerSession:: +screen_space_error(float mue_square, float sigma_square, float distance_square, float product_value) +{ + if ((mue_square >= kappa_square_ * distance_square) || + (sigma_square * (distance_square - product_value * product_value) >= kappa_square_ * distance_square * distance_square)) + return false; + else + return true; +} + + +void +VDPMServerSession:: +force_vsplit(VHierarchyNodeHandle node_handle) +{ + VHierarchyNodeHandle lcut_handle, rcut_handle; + VHierarchyNodeIndex fund_lcut_index, fund_rcut_index; + + fund_lcut_index = vhierarchy_->fund_lcut_index(node_handle); + fund_rcut_index = vhierarchy_->fund_rcut_index(node_handle); + + lcut_handle = active_ancestor_handle(fund_lcut_index); + rcut_handle = active_ancestor_handle(fund_rcut_index); + assert(lcut_handle != InvalidVHierarchyNodeHandle && rcut_handle != InvalidVHierarchyNodeHandle); + + while (lcut_handle == rcut_handle) + { + force_vsplit(lcut_handle); + lcut_handle = active_ancestor_handle(fund_lcut_index); + rcut_handle = active_ancestor_handle(fund_rcut_index); + assert(lcut_handle != InvalidVHierarchyNodeHandle && rcut_handle != InvalidVHierarchyNodeHandle); + } + + vsplit(node_handle); +} + +void +VDPMServerSession:: +vsplit(VHierarchyNodeHandle _node_handle) +{ + // refine + VHierarchyNodeHandle lchild_handle = vhierarchy_->lchild_handle(_node_handle); + VHierarchyNodeHandle rchild_handle = vhierarchy_->rchild_handle(_node_handle); + + vhwindow_.inactivate(_node_handle); + vhwindow_.activate(lchild_handle); + vhwindow_.activate(rchild_handle); + + //vfront_.remove(_node_handle); + //vfront_.add(lchild_handle); + //vfront_.add(rchild_handle); + + vsplits_.push_back(_node_handle); +} + +VHierarchyNodeHandle +VDPMServerSession:: +active_ancestor_handle(VHierarchyNodeIndex &node_index) +{ + if (node_index.is_valid(vhierarchy_->tree_id_bits()) != true) + return InvalidVHierarchyNodeHandle; + + VHierarchyNodeHandle node_handle = vhierarchy_->node_handle(node_index); + + while (node_handle != InvalidVHierarchyNodeHandle && vhwindow_.is_active(node_handle) != true) + node_handle = vhierarchy_->parent_handle(node_handle); + + return node_handle; +} + +unsigned int +VDPMServerSession:: +memory_requirements_using_window(bool _estimate) +{ + unsigned int mem = 0; + + // common + mem += sizeof(VHierarchy*); + mem += sizeof(ViewingParameters); + mem += sizeof(float); + + if (_estimate) + { + unsigned int min = vhierarchy_->num_nodes(); + unsigned int max = 0; + + for (unsigned int i = 0; i < vhierarchy_->num_nodes(); ++i) + { + if (vhwindow_.is_active(VHierarchyNodeHandle((int) i))) + { + min = std::min(min, i); + max = std::max(max, i); + } + } + + mem += (max - min) / 8; + } + else + { + mem += vhwindow_.buffer_size(); + } + + return mem; +} + +unsigned int +VDPMServerSession:: +memory_requirements_using_vfront() +{ + unsigned int mem = 0; + std::list dummy_vfront; + + mem += (unsigned int) ceil (vhierarchy_->num_nodes() / 8.0); + mem += sizeof(dummy_vfront); + + for (unsigned int i = 0; i < vhierarchy_->num_nodes(); ++i) + { + if (vhwindow_.is_active(VHierarchyNodeHandle((int) i))) + mem += 3*sizeof(int); + } + + return mem; +} + diff --git a/Apps/Unsupported/Streaming/Server/VDPMServerSession.hh b/Apps/Unsupported/Streaming/Server/VDPMServerSession.hh new file mode 100644 index 0000000000000000000000000000000000000000..156b4822c0a03a1983e433787e7c8f62fb38f30e --- /dev/null +++ b/Apps/Unsupported/Streaming/Server/VDPMServerSession.hh @@ -0,0 +1,146 @@ +#ifndef OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSESSION_HH +#define OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSESSION_HH + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using OpenMesh::VDPM::VDPMStreamingPhase; +using OpenMesh::VDPM::kBaseMesh; +using OpenMesh::VDPM::kVSplits; + +using OpenMesh::VDPM::VHierarchyWindow; +using OpenMesh::VDPM::VHierarchyNodeIndex; +using OpenMesh::VDPM::VHierarchyNodeHandle; +using OpenMesh::VDPM::ViewingParameters; + +using OpenMesh::VDPM::set_debug_print; + +class VDPMServerSession : public QSocket, public QThread +{ + + Q_OBJECT + +public: + + VDPMServerSession(int sock, QObject *parent=0, const char *name=0) + : QSocket(parent, name) + { + set_debug_print(true); + + streaming_phase_ = kBaseMesh; + transmission_complete_ = false; + + connect(this, SIGNAL(connected()), SLOT(socketConnected())); + connect(this, SIGNAL(readyRead()), SLOT(socketReadyRead())); + //connect(this, SIGNAL(connectionClosed()), SLOT(deleteLater())); + connect(this, SIGNAL(connectionClosed()), SLOT(delayedCloseFinished())); + setSocket(sock); + + + qStatisticsTimer_ = new QTimer(this); + connect(qStatisticsTimer_, SIGNAL(timeout()), this, SLOT(print_statistics())); + + mem_file = fopen("mem.txt", "w"); + + start(); + } + + ~VDPMServerSession() + { + fclose(mem_file); + } + + void run() + { + while (true) + { + sleep(1); + } + } + +private: + + VDPMStreamingPhase streaming_phase_; + bool transmission_complete_; + +private: + + void sendBaseMeshToClient(); + void send_vsplit_packets(); + void readBaseMeshRequestFromClient(); + void readViewingParametersFromClient(); + + void PrintOutVFront(); + +private slots: + + void socketConnected() + { + std::cout << "socket is connected" << std::endl; + } + + void socketReadyRead() + { + if (streaming_phase_ == kBaseMesh) + { + readBaseMeshRequestFromClient(); + } + else if (streaming_phase_ == kVSplits) + { + readViewingParametersFromClient(); + } + } + + void print_statistics() + { + //std::cout << memory_requirements(true) << " " << memory_requirements(false) << std::endl; + } + +private: + unsigned short tree_id_bits_; // obsolete + ServerSideVDPM* vdpm_; + VHierarchy* vhierarchy_; + VHierarchyWindow vhwindow_; + ViewingParameters viewing_parameters_; + float kappa_square_; + VHierarchyNodeHandleContainer vsplits_; + +private: + bool outside_view_frustum(const OpenMesh::Vec3f &pos, float radius); + bool oriented_away(float sin_square, float distance_square, float product_value); + bool screen_space_error(float mue_square, float sigma_square, float distance_square, float product_value); + + void adaptive_refinement(); + void sequential_refinement(); + bool qrefine(VHierarchyNodeHandle _node_handle); + void force_vsplit(VHierarchyNodeHandle node_handle); + void vsplit(VHierarchyNodeHandle _node_handle); + VHierarchyNodeHandle active_ancestor_handle(VHierarchyNodeIndex &node_index); + void stream_vsplits(); + +public: + bool set_vdpm(const char _vdpm_name[256]); + unsigned int memory_requirements_using_window(bool _estimate); + unsigned int memory_requirements_using_vfront(); + + // for example +private: + QTimer *qStatisticsTimer_; + FILE *mem_file; +}; + +#endif //OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSESSION_HH defined diff --git a/Apps/Unsupported/Streaming/Server/VDPMServerSocket.hh b/Apps/Unsupported/Streaming/Server/VDPMServerSocket.hh new file mode 100644 index 0000000000000000000000000000000000000000..cb71718b7db5442f8798e732314bf5615e57e074 --- /dev/null +++ b/Apps/Unsupported/Streaming/Server/VDPMServerSocket.hh @@ -0,0 +1,47 @@ +#ifndef OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSOCKET_HH +#define OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSOCKET_HH + +#include +#include +#include +#include + +#include +#include +#include + + +class VDPMServerSocket : public QServerSocket +{ + Q_OBJECT + +public: + + VDPMServerSocket(QObject *parent=0) + : QServerSocket(VDPM_STREAMING_PORT, 1, parent) + { + if (!ok()) + { + std::cerr << "Failed to bind to port " + << VDPM_STREAMING_PORT << std::endl; + exit(1); + } + } + + void newConnection(int socket) + { + VDPMServerSession *s = new VDPMServerSession(socket, this); + //s->set_vdpm(); + emit newConnect(s); + std::cout << "new connection with: " << socket << std::endl; + } + +signals: + + void newConnect(VDPMServerSession*); + +}; + + + +#endif //OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSERVERSOCKET_HH defined diff --git a/Apps/Unsupported/Streaming/Server/VDPMServerViewerWidget.cc b/Apps/Unsupported/Streaming/Server/VDPMServerViewerWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..f1554bda0eaa923d4534530b672c3071de3f6b0f --- /dev/null +++ b/Apps/Unsupported/Streaming/Server/VDPMServerViewerWidget.cc @@ -0,0 +1,80 @@ +#include +#include + +bool +VDPMServerViewerWidget:: +open_vd_prog_mesh(const char *_filename) +{ + ServerSideVDPMListIter vdpm_it; + + vdpm_it = vdpms_.insert(vdpms_.end(), ServerSideVDPM()); + + ServerSideVDPM &vdpm = *vdpm_it; + + return vdpm.open_vd_prog_mesh(_filename); +} + +ServerSideVDPM* +VDPMServerViewerWidget:: +get_vdpm(const char _vdpm_name[256]) +{ + ServerSideVDPMListIter vdpm_it; + + for (vdpm_it=vdpms_.begin(); vdpm_it!=vdpms_.end(); ++vdpm_it) + { + if (vdpm_it->is_same_name(_vdpm_name) == true) + { + return &(*vdpm_it); + } + } + + return NULL; +} + +void +VDPMServerViewerWidget:: +keyPressEvent(QKeyEvent* _event) +{ + bool handled(false); + + QString filename; + + switch (_event->key()) + { + case Key_D: + set_debug_print(!debug_print()); + std::cout << "debug print mode " + << (debug_print() == true ? "on" : "off") << std::endl; + break; + + case Key_O: +#if defined(OM_CC_MSVC) + filename = QFileDialog::getOpenFileName("d:/data/models/spm/", "*.spm"); +#else + filename = QFileDialog::getOpenFileName("~/data/models/spm/", "*.spm"); +#endif + open_vd_prog_mesh(filename); + break; + + case Key_I: + std::copy( vdpms_.begin(), vdpms_.end(), + std::ostream_iterator(std::cout, "\n") ); + break; + + case Key_V: + vd_streaming_ = !(vd_streaming_); + if (vd_streaming_) + std::cout << "View-dependent streaming mode" << std::endl; + else + std::cout << "Sequential streaming mode" << std::endl; + + break; + + case Key_Q: + case Key_Escape: + qApp->quit(); + } + + if (!handled) + _event->ignore(); +} diff --git a/Apps/Unsupported/Streaming/Server/VDPMServerViewerWidget.hh b/Apps/Unsupported/Streaming/Server/VDPMServerViewerWidget.hh new file mode 100644 index 0000000000000000000000000000000000000000..5b4e7d9df7ce0cab0011caa303e446806de7b45f --- /dev/null +++ b/Apps/Unsupported/Streaming/Server/VDPMServerViewerWidget.hh @@ -0,0 +1,70 @@ +#ifndef OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSTREAMINGSERVERWIDGET_HH +#define OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSTREAMINGSERVERWIDGET_HH + +#include +#include +#include +#include +#include +#include +#include + + +using OpenMesh::VDPM::set_debug_print; +using OpenMesh::VDPM::debug_print; + + +class VDPMServerViewerWidget : public QWidget +{ + Q_OBJECT +public: + //VDPMServerViewerWidget(QWidget *_parent) : QWidget(_parent) + VDPMServerViewerWidget() : QWidget() + { + VDPMServerSocket *server = new VDPMServerSocket(this); + connect(server, + SIGNAL(newConnect(VDPMServerSession*)), + SLOT(newConnect(VDPMServerSession*))); + + vd_streaming_ = true; + } + +private: + typedef ServerSideVDPMList::iterator ServerSideVDPMListIter; + ServerSideVDPMList vdpms_; + bool vd_streaming_; + +public: + + ServerSideVDPM* get_vdpm(const char _vdpm_name[256]); + + +public: + + bool open_vd_prog_mesh(const char *_filename); + bool vd_streaming() const { return vd_streaming_; } + +private slots: + + void newConnect(VDPMServerSession *s) + { + std::cout << "New connection" << std::endl; + + connect(s, SIGNAL(connectionClosed()), SLOT(connectionClosed())); + } + + void connectionClosed() + { + std::cout << "Client closed connection" << std::endl; + } + +protected: + + virtual void keyPressEvent(QKeyEvent* _event); + +}; + + +#endif //OPENMESH_APP_VDPMSTREAMING_SERVER_VDPMSTREAMINGSERVERWIDGET_HH defined + + diff --git a/Apps/Unsupported/Streaming/Server/VDPMStreamingServer.cc b/Apps/Unsupported/Streaming/Server/VDPMStreamingServer.cc new file mode 100644 index 0000000000000000000000000000000000000000..e1c0219f3d1900626d9181479b538ee87db9c1af --- /dev/null +++ b/Apps/Unsupported/Streaming/Server/VDPMStreamingServer.cc @@ -0,0 +1,34 @@ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + + +int main(int argc, char **argv) +{ + std::cout << "View-dependent streaming of PM server." << std::endl; + + QApplication app(argc, argv); + VDPMServerViewerWidget server_widget; + + server_widget.resize(50, 50); + app.setMainWidget(&server_widget); + server_widget.show(); + + for (int idx=1; idx < argc; ++idx) + { + std::cout << "loading " << argv[idx] << std::endl; + server_widget.open_vd_prog_mesh( argv[idx] ) ; + } + + return app.exec(); +} + diff --git a/Apps/Unsupported/Streaming/Server/VDPMStreamingServer.hh b/Apps/Unsupported/Streaming/Server/VDPMStreamingServer.hh new file mode 100644 index 0000000000000000000000000000000000000000..119b5939e545824dec03a3335bf70b413f29f840 --- /dev/null +++ b/Apps/Unsupported/Streaming/Server/VDPMStreamingServer.hh @@ -0,0 +1,6 @@ +#ifndef OPENMESH_APP_VDPMSTREAMINGSERVER_HH +#define OPENMESH_APP_VDPMSTREAMINGSERVER_HH + + + +#endif //OPENMESH_APP_VDPMSTREAMINGSERVER_HH defined diff --git a/Apps/Unsupported/VDProgMesh/Analyzer/Analyzer.pro b/Apps/Unsupported/VDProgMesh/Analyzer/Analyzer.pro new file mode 100644 index 0000000000000000000000000000000000000000..26505412dea92e385907026931bacd935c1b6bfc --- /dev/null +++ b/Apps/Unsupported/VDProgMesh/Analyzer/Analyzer.pro @@ -0,0 +1,30 @@ +################################################################################ +# +################################################################################ + +contains( OPENFLIPPER , OpenFlipper ){ + include( $$TOPDIR/qmake/all.include ) +} else { + include( $$TOPDIR/OpenMesh/qmake/all.include ) +} + +INCLUDEPATH += ../../../.. + +CONFIG += glew glut + +Application() + +LIBS += -Wl,-rpath=$${TOPDIR}/OpenMesh/Core/lib/$${BUILDDIRECTORY} -lCore +LIBS += -Wl,-rpath=$${TOPDIR}/OpenMesh/Tools/lib/$${BUILDDIRECTORY} -lTools +LIBS += -lglut +QMAKE_LIBDIR += $${TOPDIR}/OpenMesh/Core/lib/$${BUILDDIRECTORY} +QMAKE_LIBDIR += $${TOPDIR}/OpenMesh/Tools/lib/$${BUILDDIRECTORY} + +DIRECTORIES = . + +# Input +HEADERS += $$getFilesFromDir($$DIRECTORIES,*.hh) +SOURCES += $$getFilesFromDir($$DIRECTORIES,*.cc) +FORMS += $$getFilesFromDir($$DIRECTORIES,*.ui) + +################################################################################ diff --git a/Apps/Unsupported/VDProgMesh/Analyzer/vdpmanalyzer.cc b/Apps/Unsupported/VDProgMesh/Analyzer/vdpmanalyzer.cc new file mode 100644 index 0000000000000000000000000000000000000000..d40230e49ba8c78ccf84e062dc649f778f38a296 --- /dev/null +++ b/Apps/Unsupported/VDProgMesh/Analyzer/vdpmanalyzer.cc @@ -0,0 +1,1161 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen * + * www.openmesh.org * + * * + *---------------------------------------------------------------------------* + * * + * License * + * * + * This library is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published * + * by the Free Software Foundation, version 2.1. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * * +\*===========================================================================*/ + +// -------------------------------------------------------------- includes ---- + +#include +// -------------------- STL +#include +#include +#include +#include +#include +#include +// -------------------- OpenMesh +#include +#include +#include +#include +#include +// -------------------- OpenMesh VDPM +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + + +// ---------------------------------------------------------------------------- + +using namespace OpenMesh; + +// ---------------------------------------------------------------------------- + +// using view dependent progressive mesh +using VDPM::Plane3d; +using VDPM::VFront; +using VDPM::VHierarchy; +using VDPM::VHierarchyNode; +using VDPM::VHierarchyNodeIndex; +using VDPM::VHierarchyNodeHandle; +using VDPM::VHierarchyNodeHandleContainer; +using VDPM::ViewingParameters; + + +// ------------------------------------------------------------- mesh type ---- +// Generate an OpenMesh suitable for the analyzing task + +struct AnalyzerTraits : public DefaultTraits +{ + VertexTraits + { + public: + + VHierarchyNodeHandle vhierarchy_node_handle() + { return node_handle_; } + + void set_vhierarchy_node_handle(VHierarchyNodeHandle _node_handle) + { node_handle_ = _node_handle; } + + bool is_ancestor(const VHierarchyNodeIndex &_other) + { return false; } + + private: + + VHierarchyNodeHandle node_handle_; + + }; + + + HalfedgeTraits + { + public: + + VHierarchyNodeHandle + vhierarchy_leaf_node_handle() + { return leaf_node_handle_; } + + void + set_vhierarchy_leaf_node_handle(VHierarchyNodeHandle _leaf_node_handle) + { leaf_node_handle_ = _leaf_node_handle; } + + private: + + VHierarchyNodeHandle leaf_node_handle_; + + }; + + VertexAttributes(Attributes::Status | + Attributes::Normal); + HalfedgeAttributes(Attributes::PrevHalfedge); + EdgeAttributes(Attributes::Status); + FaceAttributes(Attributes::Status | + Attributes::Normal); + +}; + +typedef TriMesh_ArrayKernelT Mesh; + +// ----------------------------------------------------------------- types ---- + +struct PMInfo +{ + Mesh::Point p0; + Mesh::VertexHandle v0, v1, vl, vr; +}; + +typedef std::vector PMInfoContainer; +typedef PMInfoContainer::iterator PMInfoIter; +typedef std::vector VertexHandleContainer; +typedef std::vector ResidualContainer; + + +// -------------------------------------------------------------- forwards ---- + +/// open progressive mesh +void open_prog_mesh(const std::string &_filename); + +/// save view-dependent progressive mesh +void save_vd_prog_mesh(const std::string &_filename); + + +/// locate fundamental cut vertices +void locate_fund_cut_vertices(); + +void create_vertex_hierarchy(); + + +/// refine mesh up to _n vertices +void refine(unsigned int _n); + +/// coarsen mesh down to _n vertices +void coarsen(unsigned int _n); + +void vdpm_analysis(); + +void get_leaf_node_handles(VHierarchyNodeHandle node_handle, + VHierarchyNodeHandleContainer &leaf_nodes); +void compute_bounding_box(VHierarchyNodeHandle node_handle, + VHierarchyNodeHandleContainer &leaf_nodes); +void compute_cone_of_normals(VHierarchyNodeHandle node_handle, + VHierarchyNodeHandleContainer &leaf_nodes); +void compute_screen_space_error(VHierarchyNodeHandle node_handle, + VHierarchyNodeHandleContainer &leaf_nodes); +void compute_mue_sigma(VHierarchyNodeHandle node_handle, + ResidualContainer &residuals); + +Vec3f +point2triangle_residual(const Vec3f &p, + const Vec3f tri[3], float &s, float &t); + + +void PrintOutFundCuts(); +void PrintVertexNormals(); + +// --------------------------------------------------------------- globals ---- +// mesh data + +Mesh mesh_; +PMInfoContainer pminfos_; +PMInfoIter pmiter_; + +VHierarchy vhierarchy_; + +unsigned int n_base_vertices_, n_base_faces_, n_details_; +unsigned int n_current_res_; +unsigned int n_max_res_; +bool verbose = false; + + +// ---------------------------------------------------------------------------- + +void usage_and_exit(int xcode) +{ + using namespace std; + + cout << "Usage: vdpmanalyzer [-h] [-o output.spm] input.pm\n"; + + exit(xcode); +} + +// ---------------------------------------------------------------------------- + +inline +std::string& +replace_extension( std::string& _s, const std::string& _e ) +{ + std::string::size_type dot = _s.rfind("."); + if (dot == std::string::npos) + { _s += "." + _e; } + else + { _s = _s.substr(0,dot+1)+_e; } + return _s; +} + +// ---------------------------------------------------------------------------- + +inline +std::string +basename(const std::string& _f) +{ + std::string::size_type dot = _f.rfind("/"); + if (dot == std::string::npos) + return _f; + return _f.substr(dot+1, _f.length()-(dot+1)); +} + + +// ---------------------------------------------------------------------------- +// just for debugging + +typedef std::vector MyPoints; +typedef MyPoints::iterator MyPointsIter; + +MyPoints projected_points; +MyPoints original_points; + + +// ------------------------------------------------------------------ main ---- + + +int main(int argc, char **argv) +{ + int c; + std::string ifname; + std::string ofname; + + while ( (c=getopt(argc, argv, "o:"))!=-1 ) + { + switch(c) + { + case 'v': verbose = true; break; + case 'o': ofname = optarg; break; + case 'h': usage_and_exit(0); + default: usage_and_exit(1); + } + } + + if (optind >= argc) + usage_and_exit(1); + + ifname = argv[optind]; + + if (ofname == "." || ofname == ".." ) + ofname += "/" + basename(ifname); + std::string spmfname = ofname.empty() ? ifname : ofname; + replace_extension(spmfname, "spm"); + + if ( ifname.empty() || spmfname.empty() ) + { + usage_and_exit(1); + } + + try + { + open_prog_mesh(ifname); + vdpm_analysis(); + save_vd_prog_mesh(spmfname.c_str()); + } + catch( std::bad_alloc& ) + { + std::cerr << "Error: out of memory!\n" << std::endl; + return 1; + } + catch( std::exception& x ) + { + std::cerr << "Error: " << x.what() << std::endl; + return 1; + } + catch( ... ) + { + std::cerr << "Fatal! Unknown error!\n"; + return 1; + } + return 0; +} + + +// ---------------------------------------------------------------------------- + +void +open_prog_mesh(const std::string& _filename) +{ + Mesh::Point p; + unsigned int i, i0, i1, i2; + unsigned int v1, vl, vr; + char c[10]; + VertexHandle vertex_handle; + VHierarchyNodeHandle node_handle, lchild_handle, rchild_handle; + VHierarchyNodeIndex node_index; + + std::ifstream ifs(_filename.c_str(), std::ios::binary); + if (!ifs) + { + std::cerr << "read error\n"; + exit(1); + } + + // + bool swap = Endian::local() != Endian::LSB; + + // read header + ifs.read(c, 8); c[8] = '\0'; + if (std::string(c) != std::string("ProgMesh")) + { + std::cerr << "Wrong file format.\n"; + ifs.close(); + exit(1); + } + IO::restore(ifs, n_base_vertices_, swap); + IO::restore(ifs, n_base_faces_, swap); + IO::restore(ifs, n_details_, swap); + + vhierarchy_.set_num_roots(n_base_vertices_); + + for (i=0; i handle2index_map; + + std::ofstream ofs(_filename.c_str(), std::ios::binary); + if (!ofs) + { + std::cerr << "write error\n"; + exit(1); + } + + // + bool swap = Endian::local() != Endian::LSB; + + // write header + ofs << "VDProgMesh"; + + IO::store(ofs, n_base_vertices_, swap); + IO::store(ofs, n_base_faces_, swap); + IO::store(ofs, n_details_, swap); + + // write base mesh + coarsen(0); + mesh_.garbage_collection( false, true, true ); + + for (i=0; iv0, + pmiter_->v1, + pmiter_->vl, + pmiter_->vr); + + VHierarchyNodeHandle + parent_handle = mesh_.data(pmiter_->v1).vhierarchy_node_handle(); + + VHierarchyNodeHandle + lchild_handle = vhierarchy_.lchild_handle(parent_handle), + rchild_handle = vhierarchy_.rchild_handle(parent_handle); + + mesh_.data(pmiter_->v0).set_vhierarchy_node_handle(lchild_handle); + mesh_.data(pmiter_->v1).set_vhierarchy_node_handle(rchild_handle); + + ++pmiter_; + ++n_current_res_; + } +} + + +//----------------------------------------------------------------------------- + + +void coarsen(unsigned int _n) +{ + while (n_current_res_ > _n && pmiter_ != pminfos_.begin()) + { + --pmiter_; + + Mesh::HalfedgeHandle hh = + mesh_.find_halfedge(pmiter_->v0, pmiter_->v1); + mesh_.collapse(hh); + + VHierarchyNodeHandle + rchild_handle = mesh_.data(pmiter_->v1).vhierarchy_node_handle(); + + VHierarchyNodeHandle + parent_handle = vhierarchy_.parent_handle(rchild_handle); + + mesh_.data(pmiter_->v1).set_vhierarchy_node_handle(parent_handle); + + --n_current_res_; + } +} + + +//----------------------------------------------------------------------------- + + +void +vdpm_analysis() +{ + unsigned int i; + Mesh::VertexHandle vh; + Mesh::VertexIter v_it; + Mesh::HalfedgeIter h_it; + Mesh::HalfedgeHandle h, o, hn, op, hpo, on, ono; + VHierarchyNodeHandleContainer leaf_nodes; + + OpenMesh::Utils::Timer tana; + tana.start(); + + refine(n_max_res_); + + mesh_.update_face_normals(); + mesh_.update_vertex_normals(); + + std::cout << "Init view-dependent PM analysis" << std::endl; + + // initialize + for (h_it=mesh_.halfedges_begin(); h_it!=mesh_.halfedges_end(); ++h_it) + { + vh = mesh_.to_vertex_handle(h_it.handle()); + mesh_.data(h_it).set_vhierarchy_leaf_node_handle(mesh_.data(vh).vhierarchy_node_handle()); + } + + for (v_it=mesh_.vertices_begin(); v_it!=mesh_.vertices_end(); ++v_it) + { + VHierarchyNodeHandle + node_handle = mesh_.data(v_it.handle()).vhierarchy_node_handle(); + + vhierarchy_.node(node_handle).set_normal(mesh_.normal(v_it.handle())); + } + + std::cout << "Start view-dependent PM analysis" << std::endl; + + // locate fundamental cut vertices in each edge collapse + OpenMesh::Utils::Timer t; + + for (i=n_max_res_; i>0; --i) + { + t.start(); + PMInfo pminfo = pminfos_[i-1]; + + if (verbose) + std::cout << "Analyzing " << i << "-th detail vertex" << std::endl; + + // maintain leaf node pointers & locate fundamental cut vertices + h = mesh_.find_halfedge(pminfo.v0, pminfo.v1); + o = mesh_.opposite_halfedge_handle(h); + hn = mesh_.next_halfedge_handle(h); + hpo = mesh_.opposite_halfedge_handle(mesh_.prev_halfedge_handle(h)); + op = mesh_.prev_halfedge_handle(o); + on = mesh_.next_halfedge_handle(o); + ono = mesh_.opposite_halfedge_handle(on); + + VHierarchyNodeHandle + rchild_handle = mesh_.data(pminfo.v1).vhierarchy_node_handle(); + + VHierarchyNodeHandle + parent_handle = vhierarchy_.parent_handle(rchild_handle); + + if (pminfo.vl != Mesh::InvalidVertexHandle) + { + VHierarchyNodeHandle + fund_lcut_handle = mesh_.data(hn).vhierarchy_leaf_node_handle(); + + VHierarchyNodeHandle + left_leaf_handle = mesh_.data(hpo).vhierarchy_leaf_node_handle(); + + mesh_.data(hn).set_vhierarchy_leaf_node_handle(left_leaf_handle); + + vhierarchy_.node(parent_handle). + set_fund_lcut(vhierarchy_.node_index(fund_lcut_handle)); + } + + if (pminfo.vr != Mesh::InvalidVertexHandle) + { + VHierarchyNodeHandle + fund_rcut_handle = mesh_.data(on).vhierarchy_leaf_node_handle(), + right_leaf_handle = mesh_.data(ono).vhierarchy_leaf_node_handle(); + + mesh_.data(op).set_vhierarchy_leaf_node_handle(right_leaf_handle); + + vhierarchy_.node(parent_handle). + set_fund_rcut(vhierarchy_.node_index(fund_rcut_handle)); + } + + coarsen(i-1); + + leaf_nodes.clear(); + + get_leaf_node_handles(parent_handle, leaf_nodes); + compute_bounding_box(parent_handle, leaf_nodes); + compute_cone_of_normals(parent_handle, leaf_nodes); + compute_screen_space_error(parent_handle, leaf_nodes); + + t.stop(); + + if (verbose) + { + std::cout << " radius of bounding sphere: " + << vhierarchy_.node(parent_handle).radius() << std::endl; + std::cout << " direction of cone of normals: " + << vhierarchy_.node(parent_handle).normal() << std::endl; + std::cout << " sin(semi-angle of cone of normals) ^2: " + << vhierarchy_.node(parent_handle).sin_square() << std::endl; + std::cout << " (mue^2, sigma^2) : (" + << vhierarchy_.node(parent_handle).mue_square() << ", " + << vhierarchy_.node(parent_handle).sigma_square() << ")" + << std::endl; + std::cout << "- " << t.as_string() << std::endl; + } + + } // end for all collapses + + tana.stop(); + std::cout << "Analyzing step completed in " + << tana.as_string() << std::endl; +} + + +// ---------------------------------------------------------------------------- + +void +get_leaf_node_handles(VHierarchyNodeHandle node_handle, + VHierarchyNodeHandleContainer &leaf_nodes) +{ + if (vhierarchy_.node(node_handle).is_leaf()) + { + leaf_nodes.push_back(node_handle); + } + else + { + get_leaf_node_handles(vhierarchy_.node(node_handle).lchild_handle(), + leaf_nodes); + get_leaf_node_handles(vhierarchy_.node(node_handle).rchild_handle(), + leaf_nodes); + } +} + + +// ---------------------------------------------------------------------------- + +void +compute_bounding_box(VHierarchyNodeHandle node_handle, VHierarchyNodeHandleContainer &leaf_nodes) +{ + float max_distance; + Vec3f p, lp; + VHierarchyNodeHandleContainer::iterator n_it, n_end(leaf_nodes.end()); + + max_distance = 0.0f; + VertexHandle vh = vhierarchy_.node(node_handle).vertex_handle(); + p = mesh_.point(vh); + for ( n_it = leaf_nodes.begin(); n_it != n_end; ++n_it ) + { + lp = mesh_.point(vhierarchy_.vertex_handle(*n_it)); + max_distance = std::max(max_distance, (p - lp).length()); + } + + vhierarchy_.node(node_handle).set_radius(max_distance); +} + + +// ---------------------------------------------------------------------------- + +void +compute_cone_of_normals(VHierarchyNodeHandle node_handle, + VHierarchyNodeHandleContainer &leaf_nodes) +{ + float max_angle, angle; + Vec3f n, ln; + VertexHandle vh = vhierarchy_.node(node_handle).vertex_handle(); + VHierarchyNodeHandleContainer::iterator n_it, n_end(leaf_nodes.end()); + + n = mesh_.calc_vertex_normal(vh); + max_angle = 0.0f; + + n_it = leaf_nodes.begin(); + while( n_it != n_end ) + { + ln = vhierarchy_.node(*n_it).normal(); + angle = acosf( dot(n,ln) ); + max_angle = std::max(max_angle, angle ); + + ++n_it; + } + + max_angle = std::min(max_angle, float(M_PI_2)); + mesh_.set_normal(vh, n); + vhierarchy_.node(node_handle).set_normal(n); + vhierarchy_.node(node_handle).set_semi_angle(max_angle); +} + + +// ---------------------------------------------------------------------------- + +void +compute_screen_space_error(VHierarchyNodeHandle node_handle, VHierarchyNodeHandleContainer &leaf_nodes) +{ + std::vector residuals; + Mesh::VertexFaceIter vf_it; + Mesh::HalfedgeHandle heh; + Mesh::VertexHandle vh; + Vec3f residual, res; + Vec3f lp, tri[3]; + float min_distance; + float s, t; + VHierarchyNodeHandleContainer::iterator n_it, n_end(leaf_nodes.end()); + + for ( n_it = leaf_nodes.begin(); n_it != n_end; ++n_it ) + { + lp = mesh_.point(vhierarchy_.node(*n_it).vertex_handle()); + + // compute residual of a leaf-vertex from the current mesh_ + vh = vhierarchy_.node(node_handle).vertex_handle(); + residual = lp - mesh_.point(vh); + min_distance = residual.length(); + + for (vf_it=mesh_.vf_iter(vh); vf_it; ++vf_it) + { + heh = mesh_.halfedge_handle(vf_it.handle()); + tri[0] = mesh_.point(mesh_.to_vertex_handle(heh)); + heh = mesh_.next_halfedge_handle(heh); + tri[1] = mesh_.point(mesh_.to_vertex_handle(heh)); + heh = mesh_.next_halfedge_handle(heh); + tri[2] = mesh_.point(mesh_.to_vertex_handle(heh)); + + res = point2triangle_residual(lp, tri, s, t); + + if (res.length() < min_distance) + { + residual = res; + min_distance = res.length(); + } + } + + residuals.push_back(residual); + } + + compute_mue_sigma(node_handle, residuals); +} + + +// ---------------------------------------------------------------------------- + +void +compute_mue_sigma(VHierarchyNodeHandle node_handle, + ResidualContainer &residuals) +{ + Vec3f vn; + float max_inner, max_cross; + ResidualContainer::iterator r_it, r_end(residuals.end()); + + max_inner = max_cross = 0.0f; + vn = mesh_.normal(vhierarchy_.node(node_handle).vertex_handle()); + for (r_it = residuals.begin(); r_it != r_end; ++r_it) + { + float inner = fabsf(dot(*r_it, vn)); + float cross = OpenMesh::cross(*r_it, vn).length(); + + max_inner = std::max(max_inner, inner); + max_cross = std::max(max_cross, cross); + } + + if (max_cross < 1.0e-7) + { + vhierarchy_.node(node_handle).set_mue(max_cross); + vhierarchy_.node(node_handle).set_sigma(max_inner); + } + else { + float ratio = std::max(1.0f, max_inner/max_cross); + float whole_degree = acosf(1.0f/ratio); + float mue, max_mue; + float degree; + float res_length; + Vec3f res; + + max_mue = 0.0f; + for (r_it = residuals.begin(); r_it != r_end; ++r_it) + { + res = *r_it; + res_length = res.length(); + + // TODO: take care when res.length() is too small + degree = acosf(dot(vn,res) / res_length); + + if (degree < 0.0f) degree = -degree; + if (degree > float(M_PI_2)) degree = float(M_PI) - degree; + + if (degree < whole_degree) + mue = cosf(whole_degree - degree) * res_length; + else + mue = res_length; + + max_mue = std::max(max_mue, mue); + } + + vhierarchy_.node(node_handle).set_mue(max_mue); + vhierarchy_.node(node_handle).set_sigma(ratio*max_mue); + } +} + +// ---------------------------------------------------------------------------- + + +Vec3f +point2triangle_residual(const Vec3f &p, const Vec3f tri[3], float &s, float &t) +{ + OpenMesh::Vec3f B = tri[0]; // Tri.Origin(); + OpenMesh::Vec3f E0 = tri[1] - tri[0]; // rkTri.Edge0() + OpenMesh::Vec3f E1 = tri[2] - tri[0]; // rkTri.Edge1() + OpenMesh::Vec3f D = tri[0] - p; // kDiff + float a = dot(E0, E0); // fA00 + float b = dot(E0, E1); // fA01 + float c = dot(E1, E1); // fA11 + float d = dot(E0, D); // fB0 + float e = dot(E1, D); // fB1 + float f = dot(D, D); // fC + float det = fabsf(a*c - b*b); + s = b*e-c*d; + t = b*d-a*e; + + OpenMesh::Vec3f residual; + + float distance2; + + if ( s + t <= det ) + { + if ( s < 0.0f ) + { + if ( t < 0.0f ) // region 4 + { + if ( d < 0.0f ) + { + t = 0.0f; + if ( -d >= a ) + { + s = 1.0f; + distance2 = a+2.0f*d+f; + } + else + { + s = -d/a; + distance2 = d*s+f; + } + } + else + { + s = 0.0f; + if ( e >= 0.0f ) + { + t = 0.0f; + distance2 = f; + } + else if ( -e >= c ) + { + t = 1.0f; + distance2 = c+2.0f*e+f; + } + else + { + t = -e/c; + distance2 = e*t+f; + } + } + } + else // region 3 + { + s = 0.0f; + if ( e >= 0.0f ) + { + t = 0.0f; + distance2 = f; + } + else if ( -e >= c ) + { + t = 1.0f; + distance2 = c+2.0f*e+f; + } + else + { + t = -e/c; + distance2 = e*t+f; + } + } + } + else if ( t < 0.0f ) // region 5 + { + t = 0.0f; + if ( d >= 0.0f ) + { + s = 0.0f; + distance2 = f; + } + else if ( -d >= a ) + { + s = 1.0f; + distance2 = a+2.0f*d+f; + } + else + { + s = -d/a; + distance2 = d*s+f; + } + } + else // region 0 + { + // minimum at interior point + float inv_det = 1.0f/det; + s *= inv_det; + t *= inv_det; + distance2 = s*(a*s+b*t+2.0f*d) + + t*(b*s+c*t+2.0f*e)+f; + } + } + else + { + float tmp0, tmp1, numer, denom; + + if ( s < 0.0f ) // region 2 + { + tmp0 = b + d; + tmp1 = c + e; + if ( tmp1 > tmp0 ) + { + numer = tmp1 - tmp0; + denom = a-2.0f*b+c; + if ( numer >= denom ) + { + s = 1.0f; + t = 0.0f; + distance2 = a+2.0f*d+f; + } + else + { + s = numer/denom; + t = 1.0f - s; + distance2 = s*(a*s+b*t+2.0f*d) + + t*(b*s+c*t+2.0f*e)+f; + } + } + else + { + s = 0.0f; + if ( tmp1 <= 0.0f ) + { + t = 1.0f; + distance2 = c+2.0f*e+f; + } + else if ( e >= 0.0f ) + { + t = 0.0f; + distance2 = f; + } + else + { + t = -e/c; + distance2 = e*t+f; + } + } + } + else if ( t < 0.0f ) // region 6 + { + tmp0 = b + e; + tmp1 = a + d; + if ( tmp1 > tmp0 ) + { + numer = tmp1 - tmp0; + denom = a-2.0f*b+c; + if ( numer >= denom ) + { + t = 1.0f; + s = 0.0f; + distance2 = c+2.0f*e+f; + } + else + { + t = numer/denom; + s = 1.0f - t; + distance2 = s*(a*s+b*t+2.0f*d)+ t*(b*s+c*t+2.0f*e)+f; + } + } + else + { + t = 0.0f; + if ( tmp1 <= 0.0f ) + { + s = 1.0f; + distance2 = a+2.0f*d+f; + } + else if ( d >= 0.0f ) + { + s = 0.0f; + distance2 = f; + } + else + { + s = -d/a; + distance2 = d*s+f; + } + } + } + else // region 1 + { + numer = c + e - b - d; + if ( numer <= 0.0f ) + { + s = 0.0f; + t = 1.0f; + distance2 = c+2.0f*e+f; + } + else + { + denom = a-2.0f*b+c; + if ( numer >= denom ) + { + s = 1.0f; + t = 0.0f; + distance2 = a+2.0f*d+f; + } + else + { + s = numer/denom; + t = 1.0f - s; + distance2 = s*(a*s+b*t+2.0f*d) + t*(b*s+c*t+2.0f*e)+f; + } + } + } + } + + residual = p - (B + s*E0 + t*E1); + + return residual; +} + +// ============================================================================ diff --git a/Apps/Unsupported/VDProgMesh/Synthesizer/Synthesizer.pro b/Apps/Unsupported/VDProgMesh/Synthesizer/Synthesizer.pro new file mode 100644 index 0000000000000000000000000000000000000000..9347920f97da76bbba536a5f3fa8cf84d294ddb6 --- /dev/null +++ b/Apps/Unsupported/VDProgMesh/Synthesizer/Synthesizer.pro @@ -0,0 +1,31 @@ +################################################################################ +# +################################################################################ + +contains( OPENFLIPPER , OpenFlipper ){ + include( $$TOPDIR/qmake/all.include ) +} else { + include( $$TOPDIR/OpenMesh/qmake/all.include ) +} + +INCLUDEPATH += ../../../.. + +CONFIG += glew glut + +Application() + +LIBS += -Wl,-rpath=$${TOPDIR}/OpenMesh/Core/lib/$${BUILDDIRECTORY} -lCore +LIBS += -Wl,-rpath=$${TOPDIR}/OpenMesh/Tools/lib/$${BUILDDIRECTORY} -lTools +LIBS += -lglut +QMAKE_LIBDIR += $${TOPDIR}/OpenMesh/Core/lib/$${BUILDDIRECTORY} +QMAKE_LIBDIR += $${TOPDIR}/OpenMesh/Tools/lib/$${BUILDDIRECTORY} + +DIRECTORIES = . ../../QtViewer + +# Input +HEADERS += $$getFilesFromDir($$DIRECTORIES,*.hh) +SOURCES += $$getFilesFromDir($$DIRECTORIES,*.cc) +SOURCES -= ../../QtViewer/meshviewer.cc +FORMS += $$getFilesFromDir($$DIRECTORIES,*.ui) + +################################################################################ diff --git a/Apps/Unsupported/VDProgMesh/Synthesizer/VDPMSynthesizerViewerWidget.cc b/Apps/Unsupported/VDProgMesh/Synthesizer/VDPMSynthesizerViewerWidget.cc new file mode 100644 index 0000000000000000000000000000000000000000..3bee305e205cf0d8d24ecc581b8c1ed8e9afb575 --- /dev/null +++ b/Apps/Unsupported/VDProgMesh/Synthesizer/VDPMSynthesizerViewerWidget.cc @@ -0,0 +1,596 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen * + * www.openmesh.org * + * * + *---------------------------------------------------------------------------* + * * + * License * + * * + * This library is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published * + * by the Free Software Foundation, version 2.1. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * * +\*===========================================================================*/ + +//============================================================================= +// +// CLASS newClass - IMPLEMENTATION +// +//============================================================================= + +//== INCLUDES ================================================================= + +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311) +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + + +//== NAMESPACES =============================================================== + + +namespace OpenMesh { + + +//== IMPLEMENTATION ========================================================== + + + +void +VDPMSynthesizerViewerWidget:: +draw_scene(const std::string &_draw_mode) +{ + if (adaptive_mode_ == true) + { + adaptive_refinement(); + } + MeshViewerWidget::draw_scene(_draw_mode); +} + + +void +VDPMSynthesizerViewerWidget:: +adaptive_refinement() +{ + update_viewing_parameters(); + + VDPMMesh::HalfedgeHandle v0v1; + + float fovy = viewing_parameters_.fovy(); + + float tolerance_square = viewing_parameters_.tolerance_square(); + float tan_value = tanf(fovy / 2.0f); + + kappa_square_ = 4.0f * tan_value * tan_value * tolerance_square; + + //assert( !vfront_.end() ); + + for ( vfront_.begin(); !vfront_.end(); ) + { + VHierarchyNodeHandle + node_handle = vfront_.node_handle(), + parent_handle = vhierarchy_.parent_handle(node_handle); + + if (vhierarchy_.is_leaf_node(node_handle) != true && + qrefine(node_handle) == true) + { + force_vsplit(node_handle); + } + else if (vhierarchy_.is_root_node(node_handle) != true && + ecol_legal(parent_handle, v0v1) == true && + qrefine(parent_handle) != true) + { + ecol(parent_handle, v0v1); + } + else + { + vfront_.next(); + } + } + + // free memories tagged as 'deleted' + mesh_.garbage_collection(false, true, true); + mesh_.update_face_normals(); +} + + +bool +VDPMSynthesizerViewerWidget:: +qrefine(VHierarchyNodeHandle _node_handle) +{ + VHierarchyNode &node = vhierarchy_.node(_node_handle); + Vec3f p = mesh_.point(node.vertex_handle()); + Vec3f eye_dir = p - viewing_parameters_.eye_pos();; + + float distance = eye_dir.length(); + float distance2 = distance * distance; + float product_value = dot(eye_dir, node.normal()); + + if (outside_view_frustum(p, node.radius()) == true) + return false; + + if (oriented_away(node.sin_square(), distance2, product_value) == true) + return false; + + if (screen_space_error(node.mue_square(), + node.sigma_square(), + distance2, + product_value) == true) + return false; + + return true; +} + + +void +VDPMSynthesizerViewerWidget:: +force_vsplit(VHierarchyNodeHandle node_handle) +{ + VDPMMesh::VertexHandle vl, vr; + + get_active_cuts(node_handle, vl, vr); + + while (vl == vr) + { + force_vsplit(mesh_.data(vl).vhierarchy_node_handle()); + get_active_cuts(node_handle, vl, vr); + } + + vsplit(node_handle, vl, vr); +} + + + +void +VDPMSynthesizerViewerWidget:: +vsplit(VHierarchyNodeHandle _node_handle, + VDPMMesh::VertexHandle vl, + VDPMMesh::VertexHandle vr) +{ + // refine + VHierarchyNodeHandle + lchild_handle = vhierarchy_.lchild_handle(_node_handle), + rchild_handle = vhierarchy_.rchild_handle(_node_handle); + + VDPMMesh::VertexHandle v0 = vhierarchy_.vertex_handle(lchild_handle); + VDPMMesh::VertexHandle v1 = vhierarchy_.vertex_handle(rchild_handle); + + mesh_.vertex_split(v0, v1, vl, vr); + mesh_.set_normal(v0, vhierarchy_.normal(lchild_handle)); + mesh_.set_normal(v1, vhierarchy_.normal(rchild_handle)); + mesh_.data(v0).set_vhierarchy_node_handle(lchild_handle); + mesh_.data(v1).set_vhierarchy_node_handle(rchild_handle); + mesh_.status(v0).set_deleted(false); + mesh_.status(v1).set_deleted(false); + + vfront_.remove(_node_handle); + vfront_.add(lchild_handle); + vfront_.add(rchild_handle); +} + + +void +VDPMSynthesizerViewerWidget:: +ecol(VHierarchyNodeHandle _node_handle, const VDPMMesh::HalfedgeHandle& v0v1) +{ + VHierarchyNodeHandle + lchild_handle = vhierarchy_.lchild_handle(_node_handle), + rchild_handle = vhierarchy_.rchild_handle(_node_handle); + + VDPMMesh::VertexHandle v0 = vhierarchy_.vertex_handle(lchild_handle); + VDPMMesh::VertexHandle v1 = vhierarchy_.vertex_handle(rchild_handle); + + // coarsen + mesh_.collapse(v0v1); + mesh_.set_normal(v1, vhierarchy_.normal(_node_handle)); + mesh_.data(v0).set_vhierarchy_node_handle(lchild_handle); + mesh_.data(v1).set_vhierarchy_node_handle(_node_handle); + mesh_.status(v0).set_deleted(false); + mesh_.status(v1).set_deleted(false); + + vfront_.add(_node_handle); + vfront_.remove(lchild_handle); + vfront_.remove(rchild_handle); +} + + +bool +VDPMSynthesizerViewerWidget:: +ecol_legal(VHierarchyNodeHandle _parent_handle, VDPMMesh::HalfedgeHandle& v0v1) +{ + VHierarchyNodeHandle + lchild_handle = vhierarchy_.lchild_handle(_parent_handle), + rchild_handle = vhierarchy_.rchild_handle(_parent_handle); + + // test whether lchild & rchild present in the current vfront + if ( vfront_.is_active(lchild_handle) != true || + vfront_.is_active(rchild_handle) != true) + return false; + + VDPMMesh::VertexHandle v0, v1; + + v0 = vhierarchy_.vertex_handle(lchild_handle); + v1 = vhierarchy_.vertex_handle(rchild_handle); + + v0v1 = mesh_.find_halfedge(v0, v1); + + return mesh_.is_collapse_ok(v0v1); +} + +void +VDPMSynthesizerViewerWidget:: +get_active_cuts(const VHierarchyNodeHandle _node_handle, + VDPMMesh::VertexHandle &vl, VDPMMesh::VertexHandle &vr) +{ + VDPMMesh::VertexVertexIter vv_it; + VHierarchyNodeHandle nnode_handle; + + VHierarchyNodeIndex + nnode_index, + fund_lcut_index = vhierarchy_.fund_lcut_index(_node_handle), + fund_rcut_index = vhierarchy_.fund_rcut_index(_node_handle); + + vl = VDPMMesh::InvalidVertexHandle; + vr = VDPMMesh::InvalidVertexHandle; + + for (vv_it=mesh_.vv_iter(vhierarchy_.vertex_handle(_node_handle)); + vv_it; ++vv_it) + { + nnode_handle = mesh_.data(vv_it.handle()).vhierarchy_node_handle(); + nnode_index = vhierarchy_.node_index(nnode_handle); + + if (vl == VDPMMesh::InvalidVertexHandle && + vhierarchy_.is_ancestor(nnode_index, fund_lcut_index) == true) + vl = vv_it.handle(); + + if (vr == VDPMMesh::InvalidVertexHandle && + vhierarchy_.is_ancestor(nnode_index, fund_rcut_index) == true) + vr = vv_it.handle(); + + /*if (vl == VDPMMesh::InvalidVertexHandle && nnode_index.is_ancestor_index(fund_lcut_index) == true) + vl = vv_it.handle(); + if (vr == VDPMMesh::InvalidVertexHandle && nnode_index.is_ancestor_index(fund_rcut_index) == true) + vr = vv_it.handle();*/ + + if (vl != VDPMMesh::InvalidVertexHandle && + vr != VDPMMesh::InvalidVertexHandle) + break; + } +} + + +bool +VDPMSynthesizerViewerWidget:: +outside_view_frustum(const Vec3f &pos, float radius) +{ +#if 0 + return + (frustum_plane_[0].signed_distance(pos) < -radius) || + (frustum_plane_[1].signed_distance(pos) < -radius) || + (frustum_plane_[2].signed_distance(pos) < -radius) || + (frustum_plane_[3].signed_distance(pos) < -radius); +#else + + Plane3d frustum_plane[4]; + + viewing_parameters_.frustum_planes(frustum_plane); + + for (int i = 0; i < 4; i++) { + if (frustum_plane[i].singed_distance(pos) < -radius) + return true; + } + return false; +#endif +} + +bool +VDPMSynthesizerViewerWidget:: +oriented_away(float sin_square, float distance_square, float product_value) +{ +#if 0 + return (product_value > 0) + && ((product_value * product_value) > (distance_square * sin_square)); +#else + if (product_value > 0 && + product_value * product_value > distance_square * sin_square) + return true; + else + return false; +#endif +} + + +bool +VDPMSynthesizerViewerWidget:: +screen_space_error(float mue_square, float sigma_square, + float distance_square, float product_value) +{ +#if 0 + float ks_ds = kappa_square_ * distance_square; + float pv_pv = product_value * product_value; + return (mue_square >= ks_ds) + || (sigma_square*( distance_square - pv_pv) >= ks_ds*distance_square); +#else + if ((mue_square >= kappa_square_ * distance_square) || + (sigma_square * (distance_square - product_value * product_value) >= kappa_square_ * distance_square * distance_square)) + return false; + else + return true; +#endif +} + +void +VDPMSynthesizerViewerWidget:: +open_vd_prog_mesh(const char* _filename) +{ + unsigned int i; + unsigned int value; + unsigned int fvi[3]; + char fileformat[16]; + Vec3f p, normal; + float radius, sin_square, mue_square, sigma_square; + VHierarchyNodeHandleContainer roots; + VertexHandle vertex_handle; + VHierarchyNodeIndex node_index; + VHierarchyNodeIndex lchild_node_index, rchild_node_index; + VHierarchyNodeIndex fund_lcut_index, fund_rcut_index; + VHierarchyNodeHandle node_handle; + VHierarchyNodeHandle lchild_node_handle, rchild_node_handle; + + std::map index2handle_map; + + std::ifstream ifs(_filename, std::ios::binary); + + if (!ifs) + { + std::cerr << "read error\n"; + exit(1); + } + + // + bool swap = Endian::local() != Endian::LSB; + + // read header + ifs.read(fileformat, 10); fileformat[10] = '\0'; + if (std::string(fileformat) != std::string("VDProgMesh")) + { + std::cerr << "Wrong file format.\n"; + ifs.close(); + exit(1); + } + + IO::restore(ifs, n_base_vertices_, swap); + IO::restore(ifs, n_base_faces_, swap); + IO::restore(ifs, n_details_, swap); + + mesh_.clear(); + vfront_.clear(); + vhierarchy_.clear(); + + vhierarchy_.set_num_roots(n_base_vertices_); + + // load base mesh + for (i=0; ikey()) + { + case Key_Home: + updateGL(); + break; + + case Key_End: + updateGL(); + break; + + case Key_Plus: + viewing_parameters_.increase_tolerance(); + std::cout << "Scree-space error tolerance^2 is increased by " + << viewing_parameters_.tolerance_square() << std::endl; + updateGL(); + break; + + case Key_Minus: + viewing_parameters_.decrease_tolerance(); + std::cout << "Screen-space error tolerance^2 is decreased by " + << viewing_parameters_.tolerance_square() << std::endl; + updateGL(); + break; + + case Key_A: + adaptive_mode_ = !(adaptive_mode_); + std::cout << "Adaptive refinement mode is " + << (adaptive_mode_ ? "on" : "off") << std::endl; + updateGL(); + break; + + case Key_O: + qFilename_ = QFileDialog::getOpenFileName(0,"", "", "*.spm"); + open_vd_prog_mesh( qFilename_.toStdString().c_str() ); + break; + + default: + MeshViewerWidget::keyPressEvent( _event ); + } + +} + + + + + +void +VDPMSynthesizerViewerWidget:: +update_viewing_parameters() +{ + viewing_parameters_.set_modelview_matrix(modelview_matrix()); + viewing_parameters_.set_aspect((float) width()/ (float) height()); + viewing_parameters_.set_fovy(fovy()); + + viewing_parameters_.update_viewing_configurations(); +} + + +//============================================================================= +} // namespace OpenMesh +//============================================================================= diff --git a/Apps/Unsupported/VDProgMesh/Synthesizer/VDPMSynthesizerViewerWidget.hh b/Apps/Unsupported/VDProgMesh/Synthesizer/VDPMSynthesizerViewerWidget.hh new file mode 100644 index 0000000000000000000000000000000000000000..67db41a84413cd56c7342607f5c2a076531e2ce3 --- /dev/null +++ b/Apps/Unsupported/VDProgMesh/Synthesizer/VDPMSynthesizerViewerWidget.hh @@ -0,0 +1,181 @@ +/*===========================================================================*\ + * * + * OpenMesh * + * Copyright (C) 2001-2003 by Computer Graphics Group, RWTH Aachen * + * www.openmesh.org * + * * + *---------------------------------------------------------------------------* + * * + * License * + * * + * This library is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published * + * by the Free Software Foundation, version 2.1. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * * +\*===========================================================================*/ + +//============================================================================= +// +// CLASS newClass +// +//============================================================================= + + +#ifndef OPENMESH_VDPROGMESH_VDPMSYNTHESIZERVIEWERWIDGET_HH +#define OPENMESH_VDPROGMESH_VDPMSYNTHESIZERVIEWERWIDGET_HH + + +//== INCLUDES ================================================================= + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +//== FORWARDDECLARATIONS ====================================================== + + +//== NAMESPACES =============================================================== + +namespace OpenMesh { + + +//== CLASS DEFINITION ========================================================= + + +/** \class newClass newClass.hh + + Brief Description. + + A more elaborate description follows. +*/ + + + +typedef TriMesh_ArrayKernelT VDPMMesh; +typedef MeshViewerWidgetT MeshViewerWidget; + + + // using view dependent progressive mesh + + using VDPM::Plane3d; + using VDPM::VFront; + using VDPM::VHierarchy; + using VDPM::VHierarchyNode; + using VDPM::VHierarchyNodeIndex; + using VDPM::VHierarchyNodeHandle; + using VDPM::VHierarchyNodeHandleContainer; + using VDPM::ViewingParameters; + + +//== CLASS DEFINITION ========================================================= + + +class VDPMSynthesizerViewerWidget : public MeshViewerWidget +{ +public: + + typedef MeshViewerWidget Base; + +public: + + VDPMSynthesizerViewerWidget(QWidget* _parent=0, const char* _name=0) + : MeshViewerWidget(_parent) + { + adaptive_mode_ = false; + } + + ~VDPMSynthesizerViewerWidget() + { + + } + + /// open view-dependent progressive mesh + void open_vd_prog_mesh(const char* _filename); + + +private: + + QString qFilename_; + VHierarchy vhierarchy_; + VFront vfront_; + ViewingParameters viewing_parameters_; + float kappa_square_; + bool adaptive_mode_; + + unsigned int n_base_vertices_; + unsigned int n_base_edges_; + unsigned int n_base_faces_; + unsigned int n_details_; + + +private: + + bool outside_view_frustum(const OpenMesh::Vec3f &pos, float radius); + + bool oriented_away(float sin_square, + float distance_square, + float product_value); + + bool screen_space_error(float mue_square, + float sigma_square, + float distance_square, + float product_value); + + void update_viewing_parameters(); + + virtual void keyPressEvent(QKeyEvent* _event); + +protected: + + /// inherited drawing method + virtual void draw_scene(const std::string& _draw_mode); + +public: + + void adaptive_refinement(); + + bool qrefine(VHierarchyNodeHandle _node_handle); + + void force_vsplit(VHierarchyNodeHandle _node_handle); + + bool ecol_legal(VHierarchyNodeHandle _parent_handle, + VDPMMesh::HalfedgeHandle& v0v1); + + void get_active_cuts(VHierarchyNodeHandle _node_handle, + VDPMMesh::VertexHandle &vl, VDPMMesh::VertexHandle &vr); + + void vsplit(VHierarchyNodeHandle _node_handle, + VDPMMesh::VertexHandle vl, VDPMMesh::VertexHandle vr); + + void ecol(VHierarchyNodeHandle _parent_handle, + const VDPMMesh::HalfedgeHandle& v0v1); + + void init_vfront(); + +}; + + +//============================================================================= +} // namespace OpenMesh +//============================================================================= +#endif // OPENMESHAPPS_VDPMSYNTHESIZERVIEWERWIDGET_HH defined +//============================================================================= diff --git a/Apps/Unsupported/VDProgMesh/Synthesizer/vdpmsynthesizer.cc b/Apps/Unsupported/VDProgMesh/Synthesizer/vdpmsynthesizer.cc new file mode 100644 index 0000000000000000000000000000000000000000..9b6ce9266e640430b1dbe3969fef25d01bce904e --- /dev/null +++ b/Apps/Unsupported/VDProgMesh/Synthesizer/vdpmsynthesizer.cc @@ -0,0 +1,53 @@ +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311) +#endif + +#include + +#include +#include + +#include "VDPMSynthesizerViewerWidget.hh" + +#include + + +int main(int argc, char **argv) +{ + // OpenGL check + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication app(argc,argv); + + glutInit(&argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + std::cerr << "This system has no OpenGL support.\n"; + return 1; + } + + // create widget + VDPMSynthesizerViewerWidget* + w = new VDPMSynthesizerViewerWidget(0, "VDPMSynthesizerViewer"); + + w->resize(400, 400); + w->show(); + + // load scene + if (argc==2) + w->open_vd_prog_mesh(argv[1]); + else + { + std::cerr << "Usage: vdpmsynthesizer \n"; + return 1; + } + + // print usage info + std::cout << "\n\n" + << "Press Minus : Coarsen mesh\n" + << " Plus : Refine mesh\n" + << " Home : Coarsen down to base mesh\n" + << " End : Refine up to finest mesh\n" + << "\n"; + + return app.exec(); +} diff --git a/Apps/Unsupported/VDProgMesh/mkbalancedpm/mkbalancedpm.cc b/Apps/Unsupported/VDProgMesh/mkbalancedpm/mkbalancedpm.cc new file mode 100644 index 0000000000000000000000000000000000000000..0a694817a9aac8a489474a9037721f6902d3d3a2 --- /dev/null +++ b/Apps/Unsupported/VDProgMesh/mkbalancedpm/mkbalancedpm.cc @@ -0,0 +1,320 @@ +// -------------------- STL +#include +#include +#include +// -------------------- OpenMesh +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef OpenMesh::TriMesh_ArrayKernelT<> Mesh; +typedef OpenMesh::Decimater::DecimaterT Decimater; +typedef OpenMesh::Decimater::ModNormalFlippingT ModNormalFlipping; +typedef OpenMesh::Decimater::ModQuadricT ModQuadric; +typedef OpenMesh::Decimater::ModProgMeshT ModProgMesh; +typedef OpenMesh::Decimater::ModIndependentSetsT ModIndependentSets; + +// ---------------------------------------------------------------------------- + +using namespace OpenMesh::Decimater; + +template +class ModBalancerT : public OpenMesh::Decimater::ModQuadricT +{ +public: + + typedef OpenMesh::Decimater::ModQuadricT BaseModQ; + + DECIMATING_MODULE( ModBalancerT, D, Balancer ); + +public: + + typedef size_t level_t; + +public: + + /// Constructor + ModBalancerT( D &_dec ) + : BaseModQ( _dec ), + max_level_(0), n_vertices_(0) + { + BaseModQ::mesh().add_property( level_ ); + } + + + /// Destructor + virtual ~ModBalancerT() + { + BaseModQ::mesh().remove_property( level_ ); + } + +public: + + static level_t calc_bits_for_roots( size_t _n_vertices ) + { + return level_t(std::ceil(std::log((double)_n_vertices)*inv_log2_)); + } + +public: // inherited + + void initialize(void) + { + BaseModQ::initialize(); + n_vertices_ = BaseModQ::mesh().n_vertices(); + n_roots_ = calc_bits_for_roots(n_vertices_); + } + + virtual float collapse_priority(const CollapseInfo& _ci) + { + level_t newlevel = std::max( BaseModQ::mesh().property( level_, _ci.v0 ), + BaseModQ::mesh().property( level_, _ci.v1 ) )+1; + level_t newroots = calc_bits_for_roots(n_vertices_-1); + + if ( (newroots + newlevel) < 32 ) + { + double err = BaseModQ::collapse_priority( _ci ); + + if (err!=BaseModQ::ILLEGAL_COLLAPSE) + { + return float(newlevel + err/(err+1.0)); + } + + + } + return BaseModQ::ILLEGAL_COLLAPSE; + } + + /// post-process halfedge collapse (accumulate quadrics) + void postprocess_collapse(const CollapseInfo& _ci) + { + BaseModQ::postprocess_collapse( _ci ); + + BaseModQ::mesh().property( level_, _ci.v1 ) = + std::max( BaseModQ::mesh().property( level_, _ci.v0 ), + BaseModQ::mesh().property( level_, _ci.v1 ) ) + 1; + + max_level_ = std::max( BaseModQ::mesh().property( level_, _ci.v1 ), max_level_ ); + n_roots_ = calc_bits_for_roots(--n_vertices_); + } + +public: + + level_t max_level(void) const { return max_level_; } + level_t bits_for_roots(void) const { return n_roots_; } + +private: + + /// hide this method + void set_binary(bool _b) {} + + OpenMesh::VPropHandleT level_; + + level_t max_level_; // maximum level reached + level_t n_roots_; // minimum bits for root nodes + size_t n_vertices_;// number of potential root nodes + + static const double inv_log2_; + +}; + +template +const double ModBalancerT::inv_log2_ = 1.0/std::log(2.0); + +typedef ModBalancerT ModBalancer; + + +// ---------------------------------------------------------------------------- + +inline +std::string& +replace_extension( std::string& _s, const std::string& _e ) +{ + std::string::size_type dot = _s.rfind("."); + if (dot == std::string::npos) + { _s += "." + _e; } + else + { _s = _s.substr(0,dot+1)+_e; } + return _s; +} + +inline +std::string +basename(const std::string& _f) +{ + std::string::size_type dot = _f.rfind("/"); + if (dot == std::string::npos) + return _f; + return _f.substr(dot+1, _f.length()-(dot+1)); +} + +// ---------------------------------------------------------------------------- + +void usage_and_exit(int xcode) +{ + using namespace std; + + cout << endl + << "Usage: mkbalancedpm [-n ] [-o ] " + << "\n" + << endl + << " Create a balanced progressive mesh from an input file.\n" + << " By default decimate as much as possible and write the result\n" + << " to .pm\n" + << endl + << "Options:\n" + << endl + << " -n \n" + << "\tDetermines the maximum number of decimation steps.\n" + << "\tDecimate as much as possible if the value is equal zero\n" + << "\tDefault value: 0\n" + << endl + << " -o \n" + << "\tWrite resulting progressive mesh to the file named \n" + << endl + << " -N\n" + << "\tEnable Normal Flipping\n" + << endl + << " -I\n" + << "\tEnable Independent Sets\n" + << endl; + exit(xcode); +} + +// ---------------------------------------------------------------------------- + +int main(int argc, char **argv) +{ + Mesh mesh; + + int c; + std::string ifname, ofname; + size_t decstep=0; + bool enable_modNF = false; + bool enable_modIS = false; + + while ((c=getopt(argc, argv, "n:o:NIh"))!=-1) + { + switch (c) + { + case 'o': ofname = optarg; break; + case 'n': { std::stringstream str; str << optarg; str >> decstep; } break; + case 'N': enable_modNF = true; break; + case 'I': enable_modIS = true; break; + case 'h': + usage_and_exit(0); + default: + usage_and_exit(1); + } + } + + if (optind >= argc) + usage_and_exit(1); + + ifname = argv[optind]; + + if (!OpenMesh::IO::read_mesh(mesh, ifname)) + { + std::cerr << "Error loading mesh from file '" << ifname << "'!\n"; + return 1; + } + + { + OpenMesh::Utils::Timer t; + + Decimater decimater(mesh); + + ModProgMesh::Handle modPM; + ModBalancer::Handle modB; + ModNormalFlipping::Handle modNF; + ModIndependentSets::Handle modIS; + + + decimater.add(modPM); + std::cout << "w/ progressive mesh module\n"; + decimater.add(modB); + std::cout << "w/ balancer module\n"; + + if ( enable_modNF ) + decimater.add(modNF); + std::cout << "w/" << (modNF.is_valid() ? ' ' : 'o') + << " normal flipping module\n"; + + if ( enable_modIS ) + decimater.add(modIS); + std::cout << "w/" << (modIS.is_valid() ? ' ' : 'o') + << " independent sets module\n"; + + std::cout << "Initialize decimater\n"; + t.start(); + if ( !decimater.initialize() ) + { + std::cerr << " Initialization failed!\n"; + return 1; + } + t.stop(); + std::cout << " done [" << t.as_string() << "]\n"; + t.reset(); + + int rc; + size_t nv = mesh.n_vertices(); + + std::cout << "Begin decimation (#V " << nv << ")\n"; + t.start(); + do + { + if (modIS.is_valid()) + { + Mesh::VertexIter v_it; + Mesh::FaceIter f_it; + + for (f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it) + if ( !mesh.status(f_it).deleted() ) + mesh.update_normal(f_it); + + for (v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it) + if ( !mesh.status(v_it).deleted() ) + { + mesh.status(v_it).set_locked(false); + mesh.update_normal(v_it); + } + + } + + rc = decimater.decimate(decstep); + t.stop(); + std::cout << '\r' + << (nv-=rc) << " (-" << rc << ") " << std::flush; + t.cont(); + } while (rc > 0); + t.stop(); + + std::cout << "\n done [" << t.as_string() << "]\n"; + + std::cout << "Bits for : <" + << decimater.module(modB).bits_for_roots() << ", " + << decimater.module(modB).max_level() << ">" + << std::endl; + + std::cout << "Maximum level reached: " + << decimater.module(modB).max_level() << std::endl; + + if (ofname == "." || ofname == ".." ) + ofname += "/" + basename(ifname); + std::string pmfname = ofname.empty() ? ifname : ofname; + replace_extension(pmfname, "pm"); + + std::cout << "Write progressive mesh data to file " + << pmfname << std::endl; + decimater.module(modPM).write( pmfname ); + } + + + return 0; +} diff --git a/Apps/Unsupported/VDProgMesh/mkbalancedpm/mkbalancedpm.pro b/Apps/Unsupported/VDProgMesh/mkbalancedpm/mkbalancedpm.pro new file mode 100644 index 0000000000000000000000000000000000000000..26505412dea92e385907026931bacd935c1b6bfc --- /dev/null +++ b/Apps/Unsupported/VDProgMesh/mkbalancedpm/mkbalancedpm.pro @@ -0,0 +1,30 @@ +################################################################################ +# +################################################################################ + +contains( OPENFLIPPER , OpenFlipper ){ + include( $$TOPDIR/qmake/all.include ) +} else { + include( $$TOPDIR/OpenMesh/qmake/all.include ) +} + +INCLUDEPATH += ../../../.. + +CONFIG += glew glut + +Application() + +LIBS += -Wl,-rpath=$${TOPDIR}/OpenMesh/Core/lib/$${BUILDDIRECTORY} -lCore +LIBS += -Wl,-rpath=$${TOPDIR}/OpenMesh/Tools/lib/$${BUILDDIRECTORY} -lTools +LIBS += -lglut +QMAKE_LIBDIR += $${TOPDIR}/OpenMesh/Core/lib/$${BUILDDIRECTORY} +QMAKE_LIBDIR += $${TOPDIR}/OpenMesh/Tools/lib/$${BUILDDIRECTORY} + +DIRECTORIES = . + +# Input +HEADERS += $$getFilesFromDir($$DIRECTORIES,*.hh) +SOURCES += $$getFilesFromDir($$DIRECTORIES,*.cc) +FORMS += $$getFilesFromDir($$DIRECTORIES,*.ui) + +################################################################################