From 97f515985d99d6d5e1e2c08b19154e5dc1916b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20M=C3=B6bius?= Date: Fri, 6 Feb 2009 13:37:46 +0000 Subject: [PATCH] First checkin for OpenMesh 2.0 git-svn-id: http://www.openmesh.org/svnrepo/OpenMesh/trunk@2 fdac6126-5c0c-442c-9429-916003d36597 --- Apps/Decimating/CmdOption.hh | 56 + Apps/Decimating/DecimaterViewerWidget.cc | 111 + Apps/Decimating/DecimaterViewerWidget.hh | 172 + Apps/Decimating/Decimating.pro | 25 + .../OpenMesh_Apps_Decimating.vcproj | 199 + Apps/Decimating/decimater.cc | 499 +++ Apps/Decimating/decimaterviewer.cc | 126 + Apps/Deprecated/IvViewer/ACGMakefile | 37 + Apps/Deprecated/IvViewer/SoOpenMeshNodeT.cc | 370 ++ Apps/Deprecated/IvViewer/SoOpenMeshNodeT.hh | 117 + Apps/Deprecated/IvViewer/SoOpenMeshSupport.hh | 111 + Apps/Deprecated/IvViewer/ivviewer.cc | 140 + Apps/Deprecated/OsgViewer/ACGMakefile | 21 + Apps/Deprecated/OsgViewer/README | 11 + Apps/Deprecated/OsgViewer/meshviewer.cc | 134 + Apps/Deprecated/OsgViewer/osgviewer.cc | 481 +++ Apps/Deprecated/ProgViewer/ACGMakefile | 18 + .../OpenMesh_Apps_ProgViewer.vcproj | 274 ++ .../Deprecated/ProgViewer/ProgViewerWidget.cc | 321 ++ .../Deprecated/ProgViewer/ProgViewerWidget.hh | 137 + Apps/Deprecated/ProgViewer/progviewer.cc | 78 + Apps/Deprecated/Streaming-qt4/ACGMakefile | 16 + .../Streaming-qt4/Client/ACGMakefile | 19 + .../Streaming-qt4/Client/MeshViewerWidgetT.cc | 603 +++ .../Streaming-qt4/Client/MeshViewerWidgetT.hh | 163 + .../Deprecated/Streaming-qt4/Client/MyMesh.hh | 23 + .../Streaming-qt4/Client/QGLViewerWidget.cc | 621 +++ .../Streaming-qt4/Client/QGLViewerWidget.hh | 164 + .../Client/VDPMClientViewerWidget.cc | 1351 +++++++ .../Client/VDPMClientViewerWidget.hh | 320 ++ .../Client/VDPMStreamingClient.cc | 72 + .../Streaming-qt4/Client/camera.cmr | 4 + .../Streaming-qt4/Server/ACGMakefile | 18 + .../Streaming-qt4/Server/ServerSideVDPM.cc | 225 ++ .../Streaming-qt4/Server/ServerSideVDPM.hh | 88 + .../Streaming-qt4/Server/VDPMServerSession.cc | 475 +++ .../Streaming-qt4/Server/VDPMServerSession.hh | 148 + .../Streaming-qt4/Server/VDPMServerSocket.hh | 51 + .../Server/VDPMServerViewerWidget.cc | 81 + .../Server/VDPMServerViewerWidget.hh | 72 + .../Server/VDPMStreamingServer.cc | 34 + .../Server/VDPMStreamingServer.hh | 6 + Apps/Deprecated/Streaming-qt4/Server/bunny.pm | Bin 0 -> 840200 bytes .../Deprecated/Streaming-qt4/Server/bunny.spm | Bin 0 -> 2781190 bytes .../Streaming-qt4/Server/rockerArm.pm | Bin 0 -> 732068 bytes Apps/Deprecated/Streaming/ACGMakefile | 16 + Apps/Deprecated/Streaming/Client/ACGMakefile | 19 + .../Streaming/Client/MeshViewerWidgetT.cc | 602 +++ .../Streaming/Client/MeshViewerWidgetT.hh | 163 + Apps/Deprecated/Streaming/Client/MyMesh.hh | 23 + .../Streaming/Client/QGLViewerWidget.cc | 621 +++ .../Streaming/Client/QGLViewerWidget.hh | 163 + .../Client/VDPMClientViewerWidget.cc | 1340 +++++++ .../Client/VDPMClientViewerWidget.hh | 320 ++ .../Streaming/Client/VDPMStreamingClient.cc | 73 + Apps/Deprecated/Streaming/Server/ACGMakefile | 18 + .../Streaming/Server/ServerSideVDPM.cc | 225 ++ .../Streaming/Server/ServerSideVDPM.hh | 87 + .../Streaming/Server/VDPMServerSession.cc | 467 +++ .../Streaming/Server/VDPMServerSession.hh | 146 + .../Streaming/Server/VDPMServerSocket.hh | 47 + .../Server/VDPMServerViewerWidget.cc | 80 + .../Server/VDPMServerViewerWidget.hh | 70 + .../Streaming/Server/VDPMStreamingServer.cc | 34 + .../Streaming/Server/VDPMStreamingServer.hh | 6 + Apps/QtViewer/MeshViewerWidget.hh | 131 + Apps/QtViewer/MeshViewerWidgetT.cc | 782 ++++ Apps/QtViewer/MeshViewerWidgetT.hh | 187 + Apps/QtViewer/QGLViewerWidget.cc | 849 ++++ Apps/QtViewer/QGLViewerWidget.hh | 189 + Apps/QtViewer/QtViewer.pro | 25 + Apps/QtViewer/meshviewer.cc | 135 + Apps/Smoothing/Smoothing.pro | 25 + Apps/Smoothing/smooth.cc | 182 + Apps/Subdivider/MeshViewerWidget.cc | 63 + Apps/Subdivider/MeshViewerWidget.hh | 84 + Apps/Subdivider/SubdivideWidget.cc | 373 ++ Apps/Subdivider/SubdivideWidget.hh | 94 + Apps/Subdivider/Subdivider.pro | 26 + Apps/Subdivider/adaptive_subdivider.cc | 467 +++ Apps/Subdivider/qtsubdivider.cc | 72 + Apps/Subdivider/subdivider.cc | 288 ++ Apps/VDProgMesh/Analyzer/Analyzer.pro | 30 + Apps/VDProgMesh/Analyzer/vdpmanalyzer.cc | 1161 ++++++ Apps/VDProgMesh/Synthesizer/Synthesizer.pro | 31 + .../VDPMSynthesizerViewerWidget.cc | 596 +++ .../VDPMSynthesizerViewerWidget.hh | 181 + .../VDProgMesh/Synthesizer/vdpmsynthesizer.cc | 53 + Apps/VDProgMesh/mkbalancedpm/mkbalancedpm.cc | 320 ++ Apps/VDProgMesh/mkbalancedpm/mkbalancedpm.pro | 30 + Apps/mconvert/mconvert.cc | 378 ++ Apps/mconvert/mconvert.pro | 25 + CHANGES | 50 + Core/ACGMakefile | 19 + Core/Core.pro | 32 + Core/Geometry/ACGMakefile | 17 + Core/Geometry/Config.hh | 56 + Core/Geometry/LoopSchemeMaskT.hh | 172 + Core/Geometry/MathDefs.hh | 148 + Core/Geometry/Plane3d.hh | 99 + Core/Geometry/QuadricT.hh | 260 ++ Core/Geometry/VectorT.hh | 329 ++ Core/Geometry/VectorT_inc.hh | 541 +++ Core/IO/ACGMakefile | 17 + Core/IO/BinaryHelper.cc | 179 + Core/IO/BinaryHelper.hh | 115 + Core/IO/IOInstances.hh | 91 + Core/IO/IOManager.cc | 243 ++ Core/IO/IOManager.hh | 224 ++ Core/IO/MeshIO.hh | 134 + Core/IO/OFFFormat.hh | 76 + Core/IO/OMFormat.cc | 231 ++ Core/IO/OMFormat.hh | 715 ++++ Core/IO/OMFormatT.cc | 224 ++ Core/IO/Options.hh | 220 ++ Core/IO/SR_binary.hh | 118 + Core/IO/SR_binary_spec.hh | 277 ++ Core/IO/SR_binary_vector_of_bool.inl | 99 + Core/IO/SR_binary_vector_of_fundamentals.inl | 53 + Core/IO/SR_binary_vector_of_string.inl | 39 + Core/IO/SR_rbo.hh | 247 ++ Core/IO/SR_store.hh | 54 + Core/IO/SR_types.hh | 94 + Core/IO/StoreRestore.hh | 98 + Core/IO/exporter/ACGMakefile | 17 + Core/IO/exporter/BaseExporter.hh | 114 + Core/IO/exporter/ExporterT.hh | 183 + Core/IO/importer/ACGMakefile | 17 + Core/IO/importer/BaseImporter.hh | 130 + Core/IO/importer/ImporterT.hh | 235 ++ Core/IO/reader/ACGMakefile | 17 + Core/IO/reader/BaseReader.cc | 113 + Core/IO/reader/BaseReader.hh | 113 + Core/IO/reader/OBJReader.cc | 472 +++ Core/IO/reader/OBJReader.hh | 159 + Core/IO/reader/OFFReader.cc | 597 +++ Core/IO/reader/OFFReader.hh | 150 + Core/IO/reader/OMReader.cc | 628 +++ Core/IO/reader/OMReader.hh | 150 + Core/IO/reader/PLYReader.cc | 683 ++++ Core/IO/reader/PLYReader.hh | 154 + Core/IO/reader/STLReader.cc | 369 ++ Core/IO/reader/STLReader.hh | 124 + Core/IO/writer/ACGMakefile | 17 + Core/IO/writer/BaseWriter.cc | 88 + Core/IO/writer/BaseWriter.hh | 108 + Core/IO/writer/OBJWriter.cc | 303 ++ Core/IO/writer/OBJWriter.hh | 108 + Core/IO/writer/OFFWriter.cc | 432 ++ Core/IO/writer/OFFWriter.hh | 113 + Core/IO/writer/OMWriter.cc | 504 +++ Core/IO/writer/OMWriter.hh | 119 + Core/IO/writer/PLYWriter.cc | 476 +++ Core/IO/writer/PLYWriter.hh | 116 + Core/IO/writer/STLWriter.cc | 278 ++ Core/IO/writer/STLWriter.hh | 100 + Core/Mesh/ACGMakefile | 17 + Core/Mesh/ArrayItems.hh | 112 + Core/Mesh/ArrayKernel.cc | 297 ++ Core/Mesh/ArrayKernel.hh | 786 ++++ Core/Mesh/AttribKernelT.hh | 651 +++ Core/Mesh/Attributes.hh | 85 + Core/Mesh/BaseKernel.cc | 67 + Core/Mesh/BaseKernel.hh | 568 +++ Core/Mesh/BaseMesh.hh | 79 + Core/Mesh/Casts.hh | 54 + Core/Mesh/CirculatorsT.hh | 3499 +++++++++++++++++ Core/Mesh/FinalMeshItemsT.hh | 121 + Core/Mesh/Handles.hh | 134 + Core/Mesh/IteratorsT.hh | 1364 +++++++ Core/Mesh/PolyConnectivity.cc | 838 ++++ Core/Mesh/PolyConnectivity.hh | 513 +++ Core/Mesh/PolyMeshT.cc | 265 ++ Core/Mesh/PolyMeshT.hh | 434 ++ Core/Mesh/PolyMesh_ArrayKernelT.hh | 89 + Core/Mesh/Status.hh | 158 + Core/Mesh/Traits.hh | 227 ++ Core/Mesh/TriConnectivity.cc | 448 +++ Core/Mesh/TriConnectivity.hh | 130 + Core/Mesh/TriMeshT.cc | 60 + Core/Mesh/TriMeshT.hh | 195 + Core/Mesh/TriMesh_ArrayKernelT.hh | 89 + Core/Mesh/gen/circulators_header.hh | 73 + Core/Mesh/gen/circulators_template.hh | 190 + Core/Mesh/gen/footer.hh | 6 + Core/Mesh/gen/generate.sh | 175 + Core/Mesh/gen/iterators_header.hh | 62 + Core/Mesh/gen/iterators_template.hh | 162 + Core/OpenMesh_Core.vcproj | 578 +++ Core/System/ACGMakefile | 17 + Core/System/compiler.hh | 161 + Core/System/config.h | 60 + Core/System/config.hh | 1 + Core/System/mostream.hh | 282 ++ Core/System/omstream.cc | 74 + Core/System/omstream.hh | 61 + Core/Templates/newClass.cc | 53 + Core/Templates/newClass.hh | 85 + Core/Templates/newClass.sh | 9 + Core/Templates/newClassT.cc | 54 + Core/Templates/newClassT.hh | 92 + Core/Templates/newClassT.sh | 9 + Core/Utils/ACGMakefile | 17 + Core/Utils/AutoPropertyHandleT.hh | 115 + Core/Utils/BaseProperty.cc | 37 + Core/Utils/BaseProperty.hh | 159 + Core/Utils/Endian.cc | 70 + Core/Utils/Endian.hh | 86 + Core/Utils/GenProg.hh | 147 + Core/Utils/Noncopyable.hh | 76 + Core/Utils/Property.hh | 512 +++ Core/Utils/PropertyContainer.hh | 263 ++ Core/Utils/SingletonT.cc | 62 + Core/Utils/SingletonT.hh | 132 + Core/Utils/color_cast.hh | 235 ++ Core/Utils/vector_cast.hh | 172 + Core/Utils/vector_traits.hh | 97 + Doc/ACGMakefile | 28 + Doc/Concepts/MeshItems.hh | 188 + Doc/Concepts/MeshKernel.hh | 510 +++ Doc/Doxyfile | 1417 +++++++ Doc/Examples/BaseExporter.hh | 22 + Doc/Examples/BaseImporter.hh | 9 + Doc/Examples/BaseReader.hh | 13 + Doc/Examples/adasub.cc | 50 + Doc/Examples/build-trimesh.cc | 8 + Doc/Examples/circulators.cc | 11 + Doc/Examples/decimater.cc | 30 + Doc/Examples/draw_normals.cc | 14 + Doc/Examples/iterators.cc | 18 + Doc/Examples/mesh_io.cc | 17 + Doc/Examples/mymesh.cc | 51 + Doc/Examples/traits0.cc | 17 + Doc/Examples/traits1.cc | 4 + Doc/Examples/traits2.cc | 7 + Doc/Examples/traits3.cc | 7 + Doc/Examples/traits4.cc | 8 + Doc/Examples/traits5.cc | 7 + Doc/Tutorial/01-build_cube/ACGMakefile | 24 + Doc/Tutorial/01-build_cube/build_cube.cc | 127 + Doc/Tutorial/02-iterators/ACGMakefile | 24 + Doc/Tutorial/02-iterators/smooth.cc | 76 + Doc/Tutorial/03-properties/ACGMakefile | 24 + Doc/Tutorial/03-properties/smooth.cc | 74 + Doc/Tutorial/04-stl_algorithms/ACGMakefile | 24 + Doc/Tutorial/04-stl_algorithms/smooth.cc | 59 + Doc/Tutorial/04-stl_algorithms/smooth_algo.hh | 106 + Doc/Tutorial/05-std_properties/ACGMakefile | 24 + Doc/Tutorial/05-std_properties/properties.cc | 71 + Doc/Tutorial/06-attributes/ACGMakefile | 24 + Doc/Tutorial/06-attributes/attributes.cc | 94 + Doc/Tutorial/07-traits/ACGMakefile | 24 + Doc/Tutorial/07-traits/smooth.cc | 132 + Doc/Tutorial/08-io_options/ACGMakefile | 24 + Doc/Tutorial/08-io_options/io_options.cc | 297 ++ Doc/Tutorial/09-persistence/ACGMakefile | 24 + Doc/Tutorial/09-persistence/fill_props.hh | 123 + Doc/Tutorial/09-persistence/generate_cube.hh | 70 + Doc/Tutorial/09-persistence/int2roman.cc | 45 + Doc/Tutorial/09-persistence/int2roman.hh | 8 + Doc/Tutorial/09-persistence/persistence.cc | 347 ++ Doc/Tutorial/09-persistence/stats.hh | 20 + Doc/Tutorial/ACGMakefile | 17 + Doc/decimater.docu | 89 + Doc/history.docu | 509 +++ Doc/html/acg_footer.html | 16 + Doc/html/acg_header.html | 7 + Doc/html/acg_icon.gif | Bin 0 -> 2372 bytes Doc/html/acg_style.css | 367 ++ Doc/html/acg_tab_b.gif | Bin 0 -> 35 bytes Doc/html/acg_tab_l.gif | Bin 0 -> 215 bytes Doc/html/acg_tab_r.gif | Bin 0 -> 1037 bytes Doc/html/acg_tabs.css | 107 + Doc/images/class-hierarchy.png | Bin 0 -> 80622 bytes Doc/images/class-hierarchy2.png | Bin 0 -> 53110 bytes Doc/images/collapse_info.png | Bin 0 -> 21068 bytes Doc/images/diagrams.sxi | Bin 0 -> 12565 bytes Doc/images/halfedge_structure.gif | Bin 0 -> 3049 bytes Doc/images/halfedge_structure2.png | Bin 0 -> 5315 bytes Doc/images/halfedge_structure3.png | Bin 0 -> 7967 bytes Doc/images/inheritance-simple.png | Bin 0 -> 10045 bytes Doc/images/inheritance-simple.scaled.png | Bin 0 -> 7201 bytes Doc/images/inheritance.fig | 24 + Doc/images/inheritance.gif | Bin 0 -> 1266 bytes Doc/images/iomanager.gif | Bin 0 -> 27756 bytes Doc/images/om-format.png | Bin 0 -> 30456 bytes Doc/mainpage.docu | 10 + Doc/mesh.docu | 877 +++++ Doc/misc.docu | 93 + Doc/namespaces.docu | 82 + Doc/subdivider.docu | 17 + Doc/tools.docu | 13 + Doc/tutorial_01.docu | 64 + Doc/tutorial_02.docu | 62 + Doc/tutorial_03.docu | 54 + Doc/tutorial_04.docu | 50 + Doc/tutorial_05.docu | 136 + Doc/tutorial_06.docu | 74 + Doc/tutorial_07.docu | 46 + Doc/tutorial_08.docu | 121 + Doc/tutorial_09.docu | 186 + Doc/tutorial_main.docu | 42 + Doc/vdpm.docu | 18 + LICENSE | 504 +++ OpenMesh.kdevelop | 135 + OpenMesh.kdevelop.filelist | 839 ++++ OpenMesh.pro | 32 + OpenMesh.sln | 41 + README | 22 + Tools/ACGMakefile | 19 + Tools/Decimater/ACGMakefile | 17 + Tools/Decimater/CollapseInfoT.hh | 168 + Tools/Decimater/DecimaterT.cc | 489 +++ Tools/Decimater/DecimaterT.hh | 282 ++ Tools/Decimater/ModBaseT.hh | 266 ++ Tools/Decimater/ModIndependentSetsT.hh | 97 + Tools/Decimater/ModNormalFlippingT.hh | 175 + Tools/Decimater/ModProgMeshT.cc | 173 + Tools/Decimater/ModProgMeshT.hh | 180 + Tools/Decimater/ModQuadricT.cc | 125 + Tools/Decimater/ModQuadricT.hh | 178 + Tools/Decimater/ModRoundnessT.hh | 291 ++ Tools/Decimater/calc-roundness.m | 21 + Tools/Decimater/roundness.m | 46 + Tools/Decimater/roundness.sh | 8 + Tools/Kernel_OSG/ACGMakefile | 17 + Tools/Kernel_OSG/ArrayKernelT.hh | 209 + Tools/Kernel_OSG/AttribKernelT.hh | 638 +++ Tools/Kernel_OSG/PropertyKernel.hh | 249 ++ Tools/Kernel_OSG/PropertyT.hh | 393 ++ Tools/Kernel_OSG/Traits.hh | 87 + Tools/Kernel_OSG/TriMesh_OSGArrayKernelT.hh | 99 + Tools/Kernel_OSG/VectorAdapter.hh | 182 + Tools/Kernel_OSG/bindT.hh | 301 ++ Tools/Kernel_OSG/color_cast.hh | 43 + Tools/OpenMesh_Tools.vcproj | 444 +++ Tools/Smoother/JacobiLaplaceSmootherT.cc | 183 + Tools/Smoother/JacobiLaplaceSmootherT.hh | 99 + Tools/Smoother/LaplaceSmootherT.cc | 209 + Tools/Smoother/LaplaceSmootherT.hh | 113 + Tools/Smoother/SmootherT.cc | 394 ++ Tools/Smoother/SmootherT.hh | 188 + Tools/Smoother/smooth_mesh.hh | 92 + Tools/Subdivider/ACGMakefile | 17 + Tools/Subdivider/Adaptive/ACGMakefile | 17 + .../Subdivider/Adaptive/Composite/ACGMakefile | 17 + .../Adaptive/Composite/CompositeT.cc | 307 ++ .../Adaptive/Composite/CompositeT.hh | 298 ++ .../Adaptive/Composite/CompositeTraits.hh | 247 ++ .../Adaptive/Composite/RuleInterfaceT.hh | 389 ++ Tools/Subdivider/Adaptive/Composite/RulesT.cc | 2015 ++++++++++ Tools/Subdivider/Adaptive/Composite/RulesT.hh | 525 +++ Tools/Subdivider/Adaptive/Composite/Traits.hh | 237 ++ Tools/Subdivider/Uniform/ACGMakefile | 17 + .../Subdivider/Uniform/Composite/ACGMakefile | 17 + .../Uniform/Composite/CompositeT.cc | 1310 ++++++ .../Uniform/Composite/CompositeT.hh | 233 ++ .../Uniform/Composite/CompositeTraits.hh | 150 + Tools/Subdivider/Uniform/CompositeLoopT.hh | 139 + Tools/Subdivider/Uniform/CompositeSqrt3T.hh | 135 + Tools/Subdivider/Uniform/LoopT.hh | 451 +++ Tools/Subdivider/Uniform/Sqrt3T.hh | 507 +++ Tools/Subdivider/Uniform/SubdividerT.hh | 179 + Tools/Tools.pro | 31 + Tools/Utils/ACGMakefile | 17 + Tools/Utils/Config.hh | 57 + Tools/Utils/GLConstAsString.hh | 80 + Tools/Utils/Gnuplot.cc | 498 +++ Tools/Utils/Gnuplot.hh | 184 + Tools/Utils/HeapT.hh | 353 ++ Tools/Utils/MeshCheckerT.cc | 222 ++ Tools/Utils/MeshCheckerT.hh | 114 + Tools/Utils/NumLimitsT.hh | 136 + Tools/Utils/StripifierT.cc | 253 ++ Tools/Utils/StripifierT.hh | 141 + Tools/Utils/TestingFramework.hh | 330 ++ Tools/Utils/Timer.cc | 397 ++ Tools/Utils/Timer.hh | 169 + Tools/Utils/conio.cc | 183 + Tools/Utils/conio.hh | 37 + Tools/Utils/getopt.c | 116 + Tools/Utils/getopt.h | 26 + Tools/VDPM/ACGMakefile | 18 + Tools/VDPM/MeshTraits.hh | 102 + Tools/VDPM/StreamingDef.hh | 72 + Tools/VDPM/VFront.cc | 95 + Tools/VDPM/VFront.hh | 91 + Tools/VDPM/VHierarchy.cc | 156 + Tools/VDPM/VHierarchy.hh | 170 + Tools/VDPM/VHierarchyNode.hh | 176 + Tools/VDPM/VHierarchyNodeIndex.cc | 55 + Tools/VDPM/VHierarchyNodeIndex.hh | 110 + Tools/VDPM/VHierarchyWindow.cc | 188 + Tools/VDPM/VHierarchyWindow.hh | 201 + Tools/VDPM/ViewingParameters.cc | 142 + Tools/VDPM/ViewingParameters.hh | 124 + Tools/VDPM/xpm/fileopen.xpm | 22 + Tools/VDPM/xpm/fileprint.xpm | 24 + Tools/VDPM/xpm/filesave.xpm | 22 + VERSION | 2 + migrate.sh | 209 + openmesh/templates/cpp_template | 25 + openmesh/templates/header_template | 24 + porting.txt | 45 + qmake/all.include | 167 + qmake/architecture.include | 86 + qmake/compiler.include | 18 + qmake/functions.include | 76 + qmake/packages/packages.Darwin | 30 + qmake/packages/packages.Linux | 62 + qmake/packages/packages.Windows | 41 + qmake/targets.include | 126 + release.howto | 13 + templates/cc | 25 + templates/cpp | 25 + templates/h | 24 + templates/hh | 24 + 417 files changed, 76182 insertions(+) create mode 100644 Apps/Decimating/CmdOption.hh create mode 100644 Apps/Decimating/DecimaterViewerWidget.cc create mode 100644 Apps/Decimating/DecimaterViewerWidget.hh create mode 100644 Apps/Decimating/Decimating.pro create mode 100644 Apps/Decimating/OpenMesh_Apps_Decimating.vcproj create mode 100644 Apps/Decimating/decimater.cc create mode 100644 Apps/Decimating/decimaterviewer.cc create mode 100644 Apps/Deprecated/IvViewer/ACGMakefile create mode 100644 Apps/Deprecated/IvViewer/SoOpenMeshNodeT.cc create mode 100644 Apps/Deprecated/IvViewer/SoOpenMeshNodeT.hh create mode 100644 Apps/Deprecated/IvViewer/SoOpenMeshSupport.hh create mode 100644 Apps/Deprecated/IvViewer/ivviewer.cc create mode 100644 Apps/Deprecated/OsgViewer/ACGMakefile create mode 100644 Apps/Deprecated/OsgViewer/README create mode 100644 Apps/Deprecated/OsgViewer/meshviewer.cc create mode 100644 Apps/Deprecated/OsgViewer/osgviewer.cc create mode 100644 Apps/Deprecated/ProgViewer/ACGMakefile create mode 100644 Apps/Deprecated/ProgViewer/OpenMesh_Apps_ProgViewer.vcproj create mode 100644 Apps/Deprecated/ProgViewer/ProgViewerWidget.cc create mode 100644 Apps/Deprecated/ProgViewer/ProgViewerWidget.hh create mode 100644 Apps/Deprecated/ProgViewer/progviewer.cc create mode 100644 Apps/Deprecated/Streaming-qt4/ACGMakefile create mode 100644 Apps/Deprecated/Streaming-qt4/Client/ACGMakefile create mode 100644 Apps/Deprecated/Streaming-qt4/Client/MeshViewerWidgetT.cc create mode 100644 Apps/Deprecated/Streaming-qt4/Client/MeshViewerWidgetT.hh create mode 100644 Apps/Deprecated/Streaming-qt4/Client/MyMesh.hh create mode 100644 Apps/Deprecated/Streaming-qt4/Client/QGLViewerWidget.cc create mode 100644 Apps/Deprecated/Streaming-qt4/Client/QGLViewerWidget.hh create mode 100644 Apps/Deprecated/Streaming-qt4/Client/VDPMClientViewerWidget.cc create mode 100644 Apps/Deprecated/Streaming-qt4/Client/VDPMClientViewerWidget.hh create mode 100644 Apps/Deprecated/Streaming-qt4/Client/VDPMStreamingClient.cc create mode 100644 Apps/Deprecated/Streaming-qt4/Client/camera.cmr create mode 100644 Apps/Deprecated/Streaming-qt4/Server/ACGMakefile create mode 100644 Apps/Deprecated/Streaming-qt4/Server/ServerSideVDPM.cc create mode 100644 Apps/Deprecated/Streaming-qt4/Server/ServerSideVDPM.hh create mode 100644 Apps/Deprecated/Streaming-qt4/Server/VDPMServerSession.cc create mode 100644 Apps/Deprecated/Streaming-qt4/Server/VDPMServerSession.hh create mode 100644 Apps/Deprecated/Streaming-qt4/Server/VDPMServerSocket.hh create mode 100644 Apps/Deprecated/Streaming-qt4/Server/VDPMServerViewerWidget.cc create mode 100644 Apps/Deprecated/Streaming-qt4/Server/VDPMServerViewerWidget.hh create mode 100644 Apps/Deprecated/Streaming-qt4/Server/VDPMStreamingServer.cc create mode 100644 Apps/Deprecated/Streaming-qt4/Server/VDPMStreamingServer.hh create mode 100755 Apps/Deprecated/Streaming-qt4/Server/bunny.pm create mode 100644 Apps/Deprecated/Streaming-qt4/Server/bunny.spm create mode 100755 Apps/Deprecated/Streaming-qt4/Server/rockerArm.pm create mode 100644 Apps/Deprecated/Streaming/ACGMakefile create mode 100644 Apps/Deprecated/Streaming/Client/ACGMakefile create mode 100644 Apps/Deprecated/Streaming/Client/MeshViewerWidgetT.cc create mode 100644 Apps/Deprecated/Streaming/Client/MeshViewerWidgetT.hh create mode 100644 Apps/Deprecated/Streaming/Client/MyMesh.hh create mode 100644 Apps/Deprecated/Streaming/Client/QGLViewerWidget.cc create mode 100644 Apps/Deprecated/Streaming/Client/QGLViewerWidget.hh create mode 100644 Apps/Deprecated/Streaming/Client/VDPMClientViewerWidget.cc create mode 100644 Apps/Deprecated/Streaming/Client/VDPMClientViewerWidget.hh create mode 100644 Apps/Deprecated/Streaming/Client/VDPMStreamingClient.cc create mode 100644 Apps/Deprecated/Streaming/Server/ACGMakefile create mode 100644 Apps/Deprecated/Streaming/Server/ServerSideVDPM.cc create mode 100644 Apps/Deprecated/Streaming/Server/ServerSideVDPM.hh create mode 100644 Apps/Deprecated/Streaming/Server/VDPMServerSession.cc create mode 100644 Apps/Deprecated/Streaming/Server/VDPMServerSession.hh create mode 100644 Apps/Deprecated/Streaming/Server/VDPMServerSocket.hh create mode 100644 Apps/Deprecated/Streaming/Server/VDPMServerViewerWidget.cc create mode 100644 Apps/Deprecated/Streaming/Server/VDPMServerViewerWidget.hh create mode 100644 Apps/Deprecated/Streaming/Server/VDPMStreamingServer.cc create mode 100644 Apps/Deprecated/Streaming/Server/VDPMStreamingServer.hh create mode 100644 Apps/QtViewer/MeshViewerWidget.hh create mode 100644 Apps/QtViewer/MeshViewerWidgetT.cc create mode 100644 Apps/QtViewer/MeshViewerWidgetT.hh create mode 100644 Apps/QtViewer/QGLViewerWidget.cc create mode 100644 Apps/QtViewer/QGLViewerWidget.hh create mode 100644 Apps/QtViewer/QtViewer.pro create mode 100644 Apps/QtViewer/meshviewer.cc create mode 100644 Apps/Smoothing/Smoothing.pro create mode 100644 Apps/Smoothing/smooth.cc create mode 100644 Apps/Subdivider/MeshViewerWidget.cc create mode 100644 Apps/Subdivider/MeshViewerWidget.hh create mode 100644 Apps/Subdivider/SubdivideWidget.cc create mode 100644 Apps/Subdivider/SubdivideWidget.hh create mode 100644 Apps/Subdivider/Subdivider.pro create mode 100644 Apps/Subdivider/adaptive_subdivider.cc create mode 100644 Apps/Subdivider/qtsubdivider.cc create mode 100644 Apps/Subdivider/subdivider.cc create mode 100644 Apps/VDProgMesh/Analyzer/Analyzer.pro create mode 100644 Apps/VDProgMesh/Analyzer/vdpmanalyzer.cc create mode 100644 Apps/VDProgMesh/Synthesizer/Synthesizer.pro create mode 100644 Apps/VDProgMesh/Synthesizer/VDPMSynthesizerViewerWidget.cc create mode 100644 Apps/VDProgMesh/Synthesizer/VDPMSynthesizerViewerWidget.hh create mode 100644 Apps/VDProgMesh/Synthesizer/vdpmsynthesizer.cc create mode 100644 Apps/VDProgMesh/mkbalancedpm/mkbalancedpm.cc create mode 100644 Apps/VDProgMesh/mkbalancedpm/mkbalancedpm.pro create mode 100644 Apps/mconvert/mconvert.cc create mode 100644 Apps/mconvert/mconvert.pro create mode 100644 CHANGES create mode 100644 Core/ACGMakefile create mode 100644 Core/Core.pro create mode 100644 Core/Geometry/ACGMakefile create mode 100644 Core/Geometry/Config.hh create mode 100644 Core/Geometry/LoopSchemeMaskT.hh create mode 100644 Core/Geometry/MathDefs.hh create mode 100644 Core/Geometry/Plane3d.hh create mode 100644 Core/Geometry/QuadricT.hh create mode 100644 Core/Geometry/VectorT.hh create mode 100644 Core/Geometry/VectorT_inc.hh create mode 100644 Core/IO/ACGMakefile create mode 100644 Core/IO/BinaryHelper.cc create mode 100644 Core/IO/BinaryHelper.hh create mode 100644 Core/IO/IOInstances.hh create mode 100644 Core/IO/IOManager.cc create mode 100644 Core/IO/IOManager.hh create mode 100644 Core/IO/MeshIO.hh create mode 100644 Core/IO/OFFFormat.hh create mode 100644 Core/IO/OMFormat.cc create mode 100644 Core/IO/OMFormat.hh create mode 100644 Core/IO/OMFormatT.cc create mode 100644 Core/IO/Options.hh create mode 100644 Core/IO/SR_binary.hh create mode 100644 Core/IO/SR_binary_spec.hh create mode 100644 Core/IO/SR_binary_vector_of_bool.inl create mode 100644 Core/IO/SR_binary_vector_of_fundamentals.inl create mode 100644 Core/IO/SR_binary_vector_of_string.inl create mode 100644 Core/IO/SR_rbo.hh create mode 100644 Core/IO/SR_store.hh create mode 100644 Core/IO/SR_types.hh create mode 100644 Core/IO/StoreRestore.hh create mode 100644 Core/IO/exporter/ACGMakefile create mode 100644 Core/IO/exporter/BaseExporter.hh create mode 100644 Core/IO/exporter/ExporterT.hh create mode 100644 Core/IO/importer/ACGMakefile create mode 100644 Core/IO/importer/BaseImporter.hh create mode 100644 Core/IO/importer/ImporterT.hh create mode 100644 Core/IO/reader/ACGMakefile create mode 100644 Core/IO/reader/BaseReader.cc create mode 100644 Core/IO/reader/BaseReader.hh create mode 100644 Core/IO/reader/OBJReader.cc create mode 100644 Core/IO/reader/OBJReader.hh create mode 100644 Core/IO/reader/OFFReader.cc create mode 100644 Core/IO/reader/OFFReader.hh create mode 100644 Core/IO/reader/OMReader.cc create mode 100644 Core/IO/reader/OMReader.hh create mode 100644 Core/IO/reader/PLYReader.cc create mode 100644 Core/IO/reader/PLYReader.hh create mode 100644 Core/IO/reader/STLReader.cc create mode 100644 Core/IO/reader/STLReader.hh create mode 100644 Core/IO/writer/ACGMakefile create mode 100644 Core/IO/writer/BaseWriter.cc create mode 100644 Core/IO/writer/BaseWriter.hh create mode 100644 Core/IO/writer/OBJWriter.cc create mode 100644 Core/IO/writer/OBJWriter.hh create mode 100644 Core/IO/writer/OFFWriter.cc create mode 100644 Core/IO/writer/OFFWriter.hh create mode 100644 Core/IO/writer/OMWriter.cc create mode 100644 Core/IO/writer/OMWriter.hh create mode 100644 Core/IO/writer/PLYWriter.cc create mode 100644 Core/IO/writer/PLYWriter.hh create mode 100644 Core/IO/writer/STLWriter.cc create mode 100644 Core/IO/writer/STLWriter.hh create mode 100644 Core/Mesh/ACGMakefile create mode 100644 Core/Mesh/ArrayItems.hh create mode 100644 Core/Mesh/ArrayKernel.cc create mode 100644 Core/Mesh/ArrayKernel.hh create mode 100644 Core/Mesh/AttribKernelT.hh create mode 100644 Core/Mesh/Attributes.hh create mode 100644 Core/Mesh/BaseKernel.cc create mode 100644 Core/Mesh/BaseKernel.hh create mode 100644 Core/Mesh/BaseMesh.hh create mode 100644 Core/Mesh/Casts.hh create mode 100644 Core/Mesh/CirculatorsT.hh create mode 100644 Core/Mesh/FinalMeshItemsT.hh create mode 100644 Core/Mesh/Handles.hh create mode 100644 Core/Mesh/IteratorsT.hh create mode 100644 Core/Mesh/PolyConnectivity.cc create mode 100644 Core/Mesh/PolyConnectivity.hh create mode 100644 Core/Mesh/PolyMeshT.cc create mode 100644 Core/Mesh/PolyMeshT.hh create mode 100644 Core/Mesh/PolyMesh_ArrayKernelT.hh create mode 100644 Core/Mesh/Status.hh create mode 100644 Core/Mesh/Traits.hh create mode 100644 Core/Mesh/TriConnectivity.cc create mode 100644 Core/Mesh/TriConnectivity.hh create mode 100644 Core/Mesh/TriMeshT.cc create mode 100644 Core/Mesh/TriMeshT.hh create mode 100644 Core/Mesh/TriMesh_ArrayKernelT.hh create mode 100644 Core/Mesh/gen/circulators_header.hh create mode 100644 Core/Mesh/gen/circulators_template.hh create mode 100644 Core/Mesh/gen/footer.hh create mode 100644 Core/Mesh/gen/generate.sh create mode 100644 Core/Mesh/gen/iterators_header.hh create mode 100644 Core/Mesh/gen/iterators_template.hh create mode 100755 Core/OpenMesh_Core.vcproj create mode 100644 Core/System/ACGMakefile create mode 100644 Core/System/compiler.hh create mode 100644 Core/System/config.h create mode 100644 Core/System/config.hh create mode 100644 Core/System/mostream.hh create mode 100644 Core/System/omstream.cc create mode 100644 Core/System/omstream.hh create mode 100644 Core/Templates/newClass.cc create mode 100644 Core/Templates/newClass.hh create mode 100644 Core/Templates/newClass.sh create mode 100644 Core/Templates/newClassT.cc create mode 100644 Core/Templates/newClassT.hh create mode 100644 Core/Templates/newClassT.sh create mode 100644 Core/Utils/ACGMakefile create mode 100644 Core/Utils/AutoPropertyHandleT.hh create mode 100644 Core/Utils/BaseProperty.cc create mode 100644 Core/Utils/BaseProperty.hh create mode 100644 Core/Utils/Endian.cc create mode 100644 Core/Utils/Endian.hh create mode 100644 Core/Utils/GenProg.hh create mode 100644 Core/Utils/Noncopyable.hh create mode 100644 Core/Utils/Property.hh create mode 100644 Core/Utils/PropertyContainer.hh create mode 100644 Core/Utils/SingletonT.cc create mode 100644 Core/Utils/SingletonT.hh create mode 100644 Core/Utils/color_cast.hh create mode 100644 Core/Utils/vector_cast.hh create mode 100644 Core/Utils/vector_traits.hh create mode 100644 Doc/ACGMakefile create mode 100644 Doc/Concepts/MeshItems.hh create mode 100644 Doc/Concepts/MeshKernel.hh create mode 100644 Doc/Doxyfile create mode 100644 Doc/Examples/BaseExporter.hh create mode 100644 Doc/Examples/BaseImporter.hh create mode 100644 Doc/Examples/BaseReader.hh create mode 100644 Doc/Examples/adasub.cc create mode 100644 Doc/Examples/build-trimesh.cc create mode 100644 Doc/Examples/circulators.cc create mode 100644 Doc/Examples/decimater.cc create mode 100644 Doc/Examples/draw_normals.cc create mode 100644 Doc/Examples/iterators.cc create mode 100644 Doc/Examples/mesh_io.cc create mode 100644 Doc/Examples/mymesh.cc create mode 100644 Doc/Examples/traits0.cc create mode 100644 Doc/Examples/traits1.cc create mode 100644 Doc/Examples/traits2.cc create mode 100644 Doc/Examples/traits3.cc create mode 100644 Doc/Examples/traits4.cc create mode 100644 Doc/Examples/traits5.cc create mode 100644 Doc/Tutorial/01-build_cube/ACGMakefile create mode 100644 Doc/Tutorial/01-build_cube/build_cube.cc create mode 100644 Doc/Tutorial/02-iterators/ACGMakefile create mode 100644 Doc/Tutorial/02-iterators/smooth.cc create mode 100644 Doc/Tutorial/03-properties/ACGMakefile create mode 100644 Doc/Tutorial/03-properties/smooth.cc create mode 100644 Doc/Tutorial/04-stl_algorithms/ACGMakefile create mode 100644 Doc/Tutorial/04-stl_algorithms/smooth.cc create mode 100644 Doc/Tutorial/04-stl_algorithms/smooth_algo.hh create mode 100644 Doc/Tutorial/05-std_properties/ACGMakefile create mode 100644 Doc/Tutorial/05-std_properties/properties.cc create mode 100644 Doc/Tutorial/06-attributes/ACGMakefile create mode 100644 Doc/Tutorial/06-attributes/attributes.cc create mode 100644 Doc/Tutorial/07-traits/ACGMakefile create mode 100644 Doc/Tutorial/07-traits/smooth.cc create mode 100644 Doc/Tutorial/08-io_options/ACGMakefile create mode 100644 Doc/Tutorial/08-io_options/io_options.cc create mode 100644 Doc/Tutorial/09-persistence/ACGMakefile create mode 100644 Doc/Tutorial/09-persistence/fill_props.hh create mode 100644 Doc/Tutorial/09-persistence/generate_cube.hh create mode 100644 Doc/Tutorial/09-persistence/int2roman.cc create mode 100644 Doc/Tutorial/09-persistence/int2roman.hh create mode 100644 Doc/Tutorial/09-persistence/persistence.cc create mode 100644 Doc/Tutorial/09-persistence/stats.hh create mode 100644 Doc/Tutorial/ACGMakefile create mode 100644 Doc/decimater.docu create mode 100644 Doc/history.docu create mode 100644 Doc/html/acg_footer.html create mode 100644 Doc/html/acg_header.html create mode 100644 Doc/html/acg_icon.gif create mode 100644 Doc/html/acg_style.css create mode 100644 Doc/html/acg_tab_b.gif create mode 100644 Doc/html/acg_tab_l.gif create mode 100644 Doc/html/acg_tab_r.gif create mode 100644 Doc/html/acg_tabs.css create mode 100644 Doc/images/class-hierarchy.png create mode 100644 Doc/images/class-hierarchy2.png create mode 100644 Doc/images/collapse_info.png create mode 100644 Doc/images/diagrams.sxi create mode 100644 Doc/images/halfedge_structure.gif create mode 100644 Doc/images/halfedge_structure2.png create mode 100644 Doc/images/halfedge_structure3.png create mode 100644 Doc/images/inheritance-simple.png create mode 100644 Doc/images/inheritance-simple.scaled.png create mode 100644 Doc/images/inheritance.fig create mode 100644 Doc/images/inheritance.gif create mode 100644 Doc/images/iomanager.gif create mode 100644 Doc/images/om-format.png create mode 100644 Doc/mainpage.docu create mode 100644 Doc/mesh.docu create mode 100644 Doc/misc.docu create mode 100644 Doc/namespaces.docu create mode 100644 Doc/subdivider.docu create mode 100644 Doc/tools.docu create mode 100644 Doc/tutorial_01.docu create mode 100644 Doc/tutorial_02.docu create mode 100644 Doc/tutorial_03.docu create mode 100644 Doc/tutorial_04.docu create mode 100644 Doc/tutorial_05.docu create mode 100644 Doc/tutorial_06.docu create mode 100644 Doc/tutorial_07.docu create mode 100644 Doc/tutorial_08.docu create mode 100644 Doc/tutorial_09.docu create mode 100644 Doc/tutorial_main.docu create mode 100644 Doc/vdpm.docu create mode 100644 LICENSE create mode 100644 OpenMesh.kdevelop create mode 100644 OpenMesh.kdevelop.filelist create mode 100644 OpenMesh.pro create mode 100644 OpenMesh.sln create mode 100644 README create mode 100644 Tools/ACGMakefile create mode 100644 Tools/Decimater/ACGMakefile create mode 100644 Tools/Decimater/CollapseInfoT.hh create mode 100644 Tools/Decimater/DecimaterT.cc create mode 100644 Tools/Decimater/DecimaterT.hh create mode 100644 Tools/Decimater/ModBaseT.hh create mode 100644 Tools/Decimater/ModIndependentSetsT.hh create mode 100644 Tools/Decimater/ModNormalFlippingT.hh create mode 100644 Tools/Decimater/ModProgMeshT.cc create mode 100644 Tools/Decimater/ModProgMeshT.hh create mode 100644 Tools/Decimater/ModQuadricT.cc create mode 100644 Tools/Decimater/ModQuadricT.hh create mode 100644 Tools/Decimater/ModRoundnessT.hh create mode 100644 Tools/Decimater/calc-roundness.m create mode 100644 Tools/Decimater/roundness.m create mode 100644 Tools/Decimater/roundness.sh create mode 100644 Tools/Kernel_OSG/ACGMakefile create mode 100644 Tools/Kernel_OSG/ArrayKernelT.hh create mode 100644 Tools/Kernel_OSG/AttribKernelT.hh create mode 100644 Tools/Kernel_OSG/PropertyKernel.hh create mode 100644 Tools/Kernel_OSG/PropertyT.hh create mode 100644 Tools/Kernel_OSG/Traits.hh create mode 100644 Tools/Kernel_OSG/TriMesh_OSGArrayKernelT.hh create mode 100644 Tools/Kernel_OSG/VectorAdapter.hh create mode 100644 Tools/Kernel_OSG/bindT.hh create mode 100644 Tools/Kernel_OSG/color_cast.hh create mode 100755 Tools/OpenMesh_Tools.vcproj create mode 100644 Tools/Smoother/JacobiLaplaceSmootherT.cc create mode 100644 Tools/Smoother/JacobiLaplaceSmootherT.hh create mode 100644 Tools/Smoother/LaplaceSmootherT.cc create mode 100644 Tools/Smoother/LaplaceSmootherT.hh create mode 100644 Tools/Smoother/SmootherT.cc create mode 100644 Tools/Smoother/SmootherT.hh create mode 100644 Tools/Smoother/smooth_mesh.hh create mode 100644 Tools/Subdivider/ACGMakefile create mode 100644 Tools/Subdivider/Adaptive/ACGMakefile create mode 100644 Tools/Subdivider/Adaptive/Composite/ACGMakefile create mode 100644 Tools/Subdivider/Adaptive/Composite/CompositeT.cc create mode 100644 Tools/Subdivider/Adaptive/Composite/CompositeT.hh create mode 100644 Tools/Subdivider/Adaptive/Composite/CompositeTraits.hh create mode 100644 Tools/Subdivider/Adaptive/Composite/RuleInterfaceT.hh create mode 100644 Tools/Subdivider/Adaptive/Composite/RulesT.cc create mode 100644 Tools/Subdivider/Adaptive/Composite/RulesT.hh create mode 100644 Tools/Subdivider/Adaptive/Composite/Traits.hh create mode 100644 Tools/Subdivider/Uniform/ACGMakefile create mode 100644 Tools/Subdivider/Uniform/Composite/ACGMakefile create mode 100644 Tools/Subdivider/Uniform/Composite/CompositeT.cc create mode 100644 Tools/Subdivider/Uniform/Composite/CompositeT.hh create mode 100644 Tools/Subdivider/Uniform/Composite/CompositeTraits.hh create mode 100644 Tools/Subdivider/Uniform/CompositeLoopT.hh create mode 100644 Tools/Subdivider/Uniform/CompositeSqrt3T.hh create mode 100644 Tools/Subdivider/Uniform/LoopT.hh create mode 100644 Tools/Subdivider/Uniform/Sqrt3T.hh create mode 100644 Tools/Subdivider/Uniform/SubdividerT.hh create mode 100644 Tools/Tools.pro create mode 100644 Tools/Utils/ACGMakefile create mode 100644 Tools/Utils/Config.hh create mode 100644 Tools/Utils/GLConstAsString.hh create mode 100644 Tools/Utils/Gnuplot.cc create mode 100644 Tools/Utils/Gnuplot.hh create mode 100644 Tools/Utils/HeapT.hh create mode 100644 Tools/Utils/MeshCheckerT.cc create mode 100644 Tools/Utils/MeshCheckerT.hh create mode 100644 Tools/Utils/NumLimitsT.hh create mode 100644 Tools/Utils/StripifierT.cc create mode 100644 Tools/Utils/StripifierT.hh create mode 100644 Tools/Utils/TestingFramework.hh create mode 100644 Tools/Utils/Timer.cc create mode 100644 Tools/Utils/Timer.hh create mode 100644 Tools/Utils/conio.cc create mode 100644 Tools/Utils/conio.hh create mode 100644 Tools/Utils/getopt.c create mode 100644 Tools/Utils/getopt.h create mode 100644 Tools/VDPM/ACGMakefile create mode 100644 Tools/VDPM/MeshTraits.hh create mode 100644 Tools/VDPM/StreamingDef.hh create mode 100644 Tools/VDPM/VFront.cc create mode 100644 Tools/VDPM/VFront.hh create mode 100644 Tools/VDPM/VHierarchy.cc create mode 100644 Tools/VDPM/VHierarchy.hh create mode 100644 Tools/VDPM/VHierarchyNode.hh create mode 100644 Tools/VDPM/VHierarchyNodeIndex.cc create mode 100644 Tools/VDPM/VHierarchyNodeIndex.hh create mode 100644 Tools/VDPM/VHierarchyWindow.cc create mode 100644 Tools/VDPM/VHierarchyWindow.hh create mode 100644 Tools/VDPM/ViewingParameters.cc create mode 100644 Tools/VDPM/ViewingParameters.hh create mode 100644 Tools/VDPM/xpm/fileopen.xpm create mode 100644 Tools/VDPM/xpm/fileprint.xpm create mode 100644 Tools/VDPM/xpm/filesave.xpm create mode 100644 VERSION create mode 100644 migrate.sh create mode 100644 openmesh/templates/cpp_template create mode 100644 openmesh/templates/header_template create mode 100644 porting.txt create mode 100644 qmake/all.include create mode 100644 qmake/architecture.include create mode 100644 qmake/compiler.include create mode 100644 qmake/functions.include create mode 100644 qmake/packages/packages.Darwin create mode 100644 qmake/packages/packages.Linux create mode 100644 qmake/packages/packages.Windows create mode 100644 qmake/targets.include create mode 100644 release.howto create mode 100644 templates/cc create mode 100644 templates/cpp create mode 100644 templates/h create mode 100644 templates/hh diff --git a/Apps/Decimating/CmdOption.hh b/Apps/Decimating/CmdOption.hh new file mode 100644 index 00000000..aa09937f --- /dev/null +++ b/Apps/Decimating/CmdOption.hh @@ -0,0 +1,56 @@ +#ifndef CMDOPTION +#define CMDOPTION + +template +class CmdOption +{ +public: + + typedef T value_type; + + CmdOption(const T& _val) : val_(_val), valid_(true) { } + CmdOption() : valid_(false), enabled_(false) { } + + // has been set and has a value + bool is_valid(void) const { return valid_; } + bool has_value(void) const { return is_valid(); } + + // has been set and may have an value (check with is_valid()) + bool is_enabled() const { return enabled_; } + + void enable() { enabled_ = true; } + + CmdOption& operator = ( const T& _val ) + { + val_ = _val; + valid_=true; + enable(); + return *this; + } + + operator T () { return val_; } + // operator const T& () const { return val_; } + + operator T* () { return is_valid() ? &val_ : NULL; } + +private: + + T val_; + bool valid_; + bool enabled_; + +private: // non-copyable + + CmdOption(const CmdOption&); + CmdOption& operator = ( const CmdOption& ); + +}; + +template < typename T > +std::ostream& operator << ( std::ostream& _os, CmdOption& _opt ) +{ + _os << (T&)_opt; + return _os; +} + +#endif diff --git a/Apps/Decimating/DecimaterViewerWidget.cc b/Apps/Decimating/DecimaterViewerWidget.cc new file mode 100644 index 00000000..f1cb3651 --- /dev/null +++ b/Apps/Decimating/DecimaterViewerWidget.cc @@ -0,0 +1,111 @@ +//============================================================================= +// +// 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: 1.2 $ +// $Date: 2007-05-18 15:17:21 $ +// +//============================================================================= + + +//== INCLUDES ================================================================= + +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311) +#endif + +#include +#include + +#include +#include + +#include +#include + +#include + + +//== IMPLEMENTATION ========================================================== + + +//----------------------------------------------------------------------------- + +void DecimaterViewerWidget::keyPressEvent(QKeyEvent* _event) +{ + switch (_event->key()) + { + case Key_D: + { + int rc; + if ( (rc=decimater_->decimate(steps_)) ) + { + decimater_->mesh().garbage_collection(); + std::cout << rc << " vertices removed!\n"; + updateGL(); + } + else + std::cout << "Decimation failed\n"; + break; + } + + case Key_Plus: + steps_ = std::min( ++steps_, (size_t)(mesh_.n_vertices() * 0.1) ); + updateGL(); + std::cout << "# decimating steps increased to " << steps_ << std::endl; + break; + + case Key_Minus: + steps_ = std::max( --steps_, size_t(1) ); + updateGL(); + std::cout << "# decimating steps increased to " << steps_ << std::endl; + break; + + case Key_S: + { + OpenMesh::IO::Options opt; + + opt += OpenMesh::IO::Options::Binary; + + if (OpenMesh::IO::write_mesh( mesh(), "result.off", opt )) + std::cout << "mesh saved in 'result.off'\n"; + } + break; + + case Key_Q: + case Key_Escape: + qApp->quit(); + + default: + this->inherited_t::keyPressEvent(_event); + } +} + +void DecimaterViewerWidget::animate( void ) +{ +// updateGL(); +// timer_->start(300, true); +} + +//============================================================================= diff --git a/Apps/Decimating/DecimaterViewerWidget.hh b/Apps/Decimating/DecimaterViewerWidget.hh new file mode 100644 index 00000000..f18c5a0c --- /dev/null +++ b/Apps/Decimating/DecimaterViewerWidget.hh @@ -0,0 +1,172 @@ +//============================================================================= +// +// 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: 1.3 $ +// $Date: 2008-03-11 09:18:01 $ +// +//============================================================================= + + +#ifndef OPENMESHAPPS_DECIMATERVIEWERWIDGET_HH +#define OPENMESHAPPS_DECIMATERVIEWERWIDGET_HH + + +//== INCLUDES ================================================================= + +#if !defined(OM_USE_OSG) +# define OM_USE_OSG 0 +#endif + + +#include +#include +#include + +//-------------------- +#include +//-------------------- +#if OM_USE_OSG +# include +# define DEFAULT_TRAITS Kernel_OSG::Traits +# define TRIMESH_KERNEL Kernel_OSG::TriMesh_OSGArrayKernelT +#else +//-------------------- +# include +# include +# define DEFAULT_TRAITS DefaultTraits +# define TRIMESH_KERNEL TriMesh_ArrayKernelT +#endif + +#include + +#include +#include +#include + + +//== CLASS DEFINITION ========================================================= + + +using namespace OpenMesh; + +struct MyTraits : public DEFAULT_TRAITS +{ + VertexAttributes ( Attributes::Normal ); + FaceAttributes ( Attributes::Normal ); +}; + +typedef TRIMESH_KERNEL mesh_t; +typedef MeshViewerWidgetT MeshViewerWidget; + +//== CLASS DEFINITION ========================================================= + + +class DecimaterViewerWidget : public MeshViewerWidget +{ + Q_OBJECT + +public: + + typedef MeshViewerWidget inherited_t; + + typedef Decimater::DecimaterT decimater_t; + typedef Decimater::ModQuadricT< decimater_t > mod_quadric_t; + typedef Decimater::ModNormalFlippingT< decimater_t > mod_nf_t; + + // object types + typedef std::auto_ptr< decimater_t > decimater_o; + typedef std::auto_ptr< mod_quadric_t > mod_quadric_o; + typedef std::auto_ptr< mod_nf_t > mod_nf_o; + + /// default constructor + DecimaterViewerWidget(QWidget* _parent=0, const char* _name=0) + : MeshViewerWidget(_parent), steps_(1) + { + timer_ = new QTimer(this); + + connect( timer_, SIGNAL(timeout()), SLOT(animate()) ); + } + + /// destructor + ~DecimaterViewerWidget() + { + delete timer_; + } + +public: // inherited + + bool open_mesh(const char* _filename, OpenMesh::IO::Options _opt) + { + bool rc; + + if ( (rc = inherited_t::open_mesh( _filename, _opt )) ) + { + std::cout << "prepare decimater" << std::endl; + + // to be compatible with gcc 2.95.3 + { + decimater_o tmp( new decimater_t ( mesh() ) ); + decimater_ = tmp; + } + { + mod_quadric_o tmp( new mod_quadric_t( *decimater_ ) ); + mod_quadric_ = tmp; + } + { + mod_nf_o tmp( new mod_nf_t ( *decimater_ ) ); + mod_nf_ = tmp; + } + + decimater_->initialize(); + } + return rc; + } + +protected slots: + + void animate( void ); + +protected: + + virtual void keyPressEvent(QKeyEvent* _event); + + +private: + + bool animate_; + QTimer *timer_; + + decimater_o decimater_; + mod_quadric_o mod_quadric_; + mod_nf_o mod_nf_; + + size_t steps_; +}; + + +//============================================================================= +#endif // OPENMESHAPPS_DECIMATERVIEWERWIDGET_HH defined +//============================================================================= + diff --git a/Apps/Decimating/Decimating.pro b/Apps/Decimating/Decimating.pro new file mode 100644 index 00000000..50cc991a --- /dev/null +++ b/Apps/Decimating/Decimating.pro @@ -0,0 +1,25 @@ +################################################################################ +# +################################################################################ + +contains( OPENFLIPPER , OpenFlipper ){ + include( $$TOPDIR/qmake/all.include ) +} else { + include( $$TOPDIR/OpenMesh/qmake/all.include ) +} + +INCLUDEPATH += ../../.. + +Application() +glew() +glut() +openmesh() + +DIRECTORIES = . ../QtViewer + +# Input +HEADERS += $$getFilesFromDir($$DIRECTORIES,*.hh) +SOURCES += $$getFilesFromDir($$DIRECTORIES,*.cc) +FORMS += $$getFilesFromDir($$DIRECTORIES,*.ui) + +################################################################################ diff --git a/Apps/Decimating/OpenMesh_Apps_Decimating.vcproj b/Apps/Decimating/OpenMesh_Apps_Decimating.vcproj new file mode 100644 index 00000000..3dcc7e2b --- /dev/null +++ b/Apps/Decimating/OpenMesh_Apps_Decimating.vcproj @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Apps/Decimating/decimater.cc b/Apps/Decimating/decimater.cc new file mode 100644 index 00000000..34074d6e --- /dev/null +++ b/Apps/Decimating/decimater.cc @@ -0,0 +1,499 @@ +//============================================================================= +// +// 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: 1.2 $ +// $Date: 2007-05-18 15:17:22 $ +// +//============================================================================= + +#if !defined(OM_USE_OSG) +# define OM_USE_OSG 0 +#endif + +// ---------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +//-------------------- +#include +//-------------------- +#if OM_USE_OSG +# include +#else +# include +#endif +#include +//-------------------- +#include +#include +#include +#include +#include +#include +#include +#include + +//----------------------------------------------------------------- traits ---- + +#if OM_USE_OSG +typedef OpenMesh::Kernel_OSG::Traits MyTraits; +#else +typedef OpenMesh::DefaultTraits MyTraits; +#endif + +//------------------------------------------------------------------- mesh ---- + +#if OM_USE_OSG +typedef OpenMesh::Kernel_OSG::TriMesh_OSGArrayKernelT ArrayTriMesh; +#else +typedef OpenMesh::TriMesh_ArrayKernelT ArrayTriMesh; +#endif + + +//-------------------------------------------------------------- decimator ---- + +typedef OpenMesh::Decimater::DecimaterT Decimater; + + +//---------------------------------------------------------------- globals ---- + +int gverbose = 0; +int gdebug = 0; + + +//--------------------------------------------------------------- forwards ---- + +void usage_and_exit(int xcode); + + +//--------------------------------------------------- decimater arguments ---- + +#include "CmdOption.hh" + + +struct DecOptions +{ + DecOptions() + : n_collapses(0) + { } + + CmdOption decorate_name; + CmdOption n_collapses; + CmdOption Q; // Quadrics + CmdOption NF; // Normal Flipping + CmdOption IS; // Independent Sets + CmdOption PM; // Progressive Mesh + CmdOption R; // Roundness + + + template + bool init( CmdOption& _o, const std::string& _val ) + { + if ( _val.empty() ) + _o.enable(); + else + { + std::istringstream istr( _val ); + + T v; + + if ( (istr >> v).fail() ) + return false; + + _o = v; + } + return true; + } + + + bool parse_argument( const std::string& arg ) + { + std::string::size_type pos = arg.find(':'); + + std::string name; + std::string value; + + if (pos == std::string::npos) + name = arg; + else + { + name = arg.substr(0, pos); + value = arg.substr(pos+1, arg.size()); + } + strip(name); + strip(value); + + if (name == "Q") return init(Q, value); + if (name == "NF") return init(NF, value); + if (name == "PM") return init(PM, value); + if (name == "IS") return init(IS, value); + if (name == "R") return init(R, value); + return false; + } + + + std::string& strip(std::string & line) + { + std::string::size_type pos = 0; + + pos = line.find_last_not_of(" \t"); + + if ( pos!=0 && pos!=std::string::npos ) + { + ++pos; + line.erase( pos, line.length()-pos ); + } + + pos = line.find_first_not_of(" \t"); + if ( pos!=0 && pos!=std::string::npos ) + { + line.erase(0,pos); + } + + return line; + } + +}; + +//----------------------------------------------------- decimater wrapper ---- +// +template +bool +decimate(const std::string &_ifname, + const std::string &_ofname, + DecOptions &_opt) +{ + using namespace std; + + Mesh mesh; + OpenMesh::IO::Options opt; + OpenMesh::Utils::Timer timer; + + // ---------------------------------------- read source mesh + { + if (gverbose) + clog << "source mesh: "; + bool rc; + + if (gverbose) + clog << _ifname << endl; + if ( !(rc = OpenMesh::IO::read_mesh(mesh, _ifname, opt)) ) + { + cerr << " ERROR: read failed!" << endl; + return rc; + } + } + + // ---------------------------------------- do some decimation + { + // ---- 0 - For module NormalFlipping one needs face normals + + if ( !opt.check( OpenMesh::IO::Options::FaceNormal ) ) + { + if ( !mesh.has_face_normals() ) + mesh.request_face_normals(); + + if (gverbose) + clog << " updating face normals" << endl; + mesh.update_face_normals(); + } + + // ---- 1 - create decimater instance + Decimater decimater( mesh ); + + // ---- 2 - registrate modules + if (gverbose) + clog << " registrate modules" << endl; + + + typename OpenMesh::Decimater::ModQuadricT::Handle modQ; + + if (_opt.Q.is_enabled()) + { + decimater.add(modQ); + if (_opt.Q.has_value()) + decimater.module( modQ ).set_max_err( _opt.Q ); + } + + typename OpenMesh::Decimater::ModNormalFlippingT::Handle modNF; + + if (_opt.NF.is_enabled()) + { + decimater.add(modNF); + if (_opt.NF.has_value()) + decimater.module( modNF ).set_normal_deviation( _opt.NF ); + } + + typename OpenMesh::Decimater::ModProgMeshT::Handle modPM; + + if ( _opt.PM.is_enabled() ) + decimater.add(modPM); + + + typename OpenMesh::Decimater::ModIndependentSetsT::Handle modIS; + + if ( _opt.IS.is_enabled() ) + decimater.add(modIS); + + + typename OpenMesh::Decimater::ModRoundnessT::Handle modR; + + if ( _opt.R.is_enabled() ) + { + decimater.add( modR ); + if ( _opt.R.has_value() ) + decimater.module( modR ).set_min_angle( _opt.R, + !modQ.is_valid() || + !decimater.module(modQ).is_binary()); + } + + // ---- 3 - initialize decimater + + if (gverbose) + clog << "initializing mesh" << endl; + + { + bool rc; + timer.start(); + rc = decimater.initialize(); + timer.stop(); + if (!rc) + { + std::cerr << " initializing failed!" << std::endl; + return false; + } + } + if (gverbose) + std::clog << " Elapsed time: " << timer.as_string() << std::endl; + + if (gverbose) + decimater.info( clog ); + + // ---- 4 - do it + + if (gverbose) + { + std::clog << "decimating" << std::endl; + std::clog << " # vertices: " << mesh.n_vertices() << std::endl; + } + + float nv_before = float(mesh.n_vertices()); + + timer.start(); + int rc = 0; + if (_opt.n_collapses < 0.0) + rc = decimater.decimate_to( size_t(-_opt.n_collapses) ); + else if (_opt.n_collapses >= 1.0 || _opt.n_collapses == 0.0) + rc = decimater.decimate( size_t(_opt.n_collapses) ); + else if (_opt.n_collapses > 0.0f) + rc = decimater.decimate_to(size_t(mesh.n_vertices()*_opt.n_collapses)); + timer.stop(); + + // ---- 5 - write progmesh file for progviewer (before garbage collection!) + + if ( _opt.PM.has_value() ) + decimater.module(modPM).write( _opt.PM ); + + // ---- 6 - throw away all tagged edges + + mesh.garbage_collection(); + + if (gverbose) + { + std::clog << " # executed collapses: " << rc << std::endl; + std::clog << " # vertices: " << mesh.n_vertices() << ", " + << ( 100.0*mesh.n_vertices()/nv_before ) << "%\n"; + std::clog << " Elapsed time: " << timer.as_string() << std::endl; + std::clog << " collapses/s : " << rc/timer.seconds() << std::endl; + } + + } + + // write resulting mesh + if ( ! _ofname.empty() ) + { + std::string ofname(_ofname); + + std::string::size_type pos = ofname.rfind('.'); + if (pos == std::string::npos) + { + ofname += ".off"; + pos = ofname.rfind('.'); + } + + if ( _opt.decorate_name.is_enabled() ) + { + std::stringstream s; s << mesh.n_vertices(); + std::string n; s >> n; + ofname.insert( pos, "-"); + ofname.insert(++pos, n ); + } + + OpenMesh::IO::Options opt; + + //opt += OpenMesh::IO::Options::Binary; + + if ( !OpenMesh::IO::write_mesh(mesh, ofname, opt ) ) + { + std::cerr << " Cannot write decimated mesh to file '" + << ofname << "'\n"; + return false; + } + std::clog << " Exported decimated mesh to file '" << ofname << "'\n"; + } + + return true; +} + +//------------------------------------------------------------------ main ----- + +int main(int argc, char* argv[]) +{ + std::string ifname, ofname; + + DecOptions opt; + + // +#if OM_USE_OSG + osg::osgInit( argc, argv ); +#endif + + //---------------------------------------- parse command line + { + int c; + + while ( (c=getopt( argc, argv, "dDhi:M:n:o:v")) != -1 ) + { + switch (c) + { + case 'D': opt.decorate_name = true; break; + case 'd': gdebug = true; break; + case 'h': usage_and_exit(0); + case 'i': ifname = optarg; break; + case 'M': opt.parse_argument( optarg ); break; + case 'n': opt.n_collapses = float(atof(optarg)); break; + case 'o': ofname = optarg; break; + case 'v': gverbose = true; break; + case '?': + default: + std::cerr << "FATAL: cannot process command line option!" + << std::endl; + exit(-1); + } + } + } + + //---------------------------------------- + + if ( (-1.0f < opt.n_collapses) && (opt.n_collapses < 0.0f) ) + { + std::cerr << "Error: Option -n: invalid value argument!" << std::endl; + usage_and_exit(2); + } + + //---------------------------------------- + + if (gverbose) + { + std::clog << " Input file: " << ifname << std::endl; + std::clog << " Output file: " << ofname << std::endl; + std::clog << " #collapses: " << opt.n_collapses << std::endl; + } + + + //---------------------------------------- + + + + if (gverbose) + { + std::clog << "Begin decimation" << std::endl; + } + + bool rc = decimate( ifname, ofname, opt ); + + if (gverbose) + { + if (!rc) + std::clog << "Decimation failed!" << std::endl; + else + std::clog << "Decimation done." << std::endl; + } + + //---------------------------------------- + return 0; +} + + +//----------------------------------------------------------------------------- + +void usage_and_exit(int xcode) +{ + std::string errmsg; + + switch(xcode) + { + case 1: errmsg = "Option not supported!"; break; + case 2: errmsg = "Invalid output file format!"; break; + } + + std::cerr << std::endl; + if (xcode) + { + std::cerr << "Error " << xcode << ": " << errmsg << std::endl << std::endl; + } + std::cerr << "Usage: decimator [Options] -i input-file -o output-file\n" + << " Decimating a mesh using quadrics and normal flipping.\n" + << std::endl; + std::cerr << "Options\n" + << std::endl; + std::cerr << " -M \"{Module-Name}[:Value]}\"\n" + << " Use named module with eventually given parameterization\n" + << std::endl; + std::cerr << " -n \n" + << " N >= 1: do N halfedge collapses.\n" + << " N <=-1: decimate down to |N| vertices.\n" + << " 0 < N < 1: decimate down to N%.\n" + << std::endl; + std::cerr << std::endl; + std::cerr << "Modules:\n\n"; + std::cerr << " IS - ModIndependentSets\n"; + std::cerr << " NF[:angle] - ModNormalFlipping\n"; + std::cerr << " PM[:file name] - ModProgMesh\n"; + std::cerr << " Q[:error] - ModQuadric\n"; + std::cerr << " R[:angle] - ModRoundness\n"; + std::cerr << " 0 < angle < 60\n"; + + exit( xcode ); +} + + + +// end of file +//============================================================================= diff --git a/Apps/Decimating/decimaterviewer.cc b/Apps/Decimating/decimaterviewer.cc new file mode 100644 index 00000000..a23072a6 --- /dev/null +++ b/Apps/Decimating/decimaterviewer.cc @@ -0,0 +1,126 @@ +//============================================================================= +// +// 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: 1.3 $ +// $Date: 2008-03-11 09:18:01 $ +// +//============================================================================= +#ifdef _MSC_VER +# pragma warning(disable: 4267 4311) +#endif + +#include +#include +#include +#include +#include + +#include "DecimaterViewerWidget.hh" + +#include + + +void usage_and_exit(int xcode); + + +int main(int argc, char **argv) +{ +#if defined(OM_USE_OSG) && OM_USE_OSG + osg::osgInit(argc, argv); +#endif + + // OpenGL check + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication app(argc,argv); + + glutInit(&argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + QString msg = "System has no OpenGL support!"; + QMessageBox::critical( NULL, "OpenGL", msg + argv[1] ); + 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 + DecimaterViewerWidget w(0, "Viewer"); +// app.setMainWidget(&w); + + 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.windowTitle(), msg ); + 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.windowTitle(), msg ); + } + } + + return app.exec(); +} + +void usage_and_exit(int xcode) +{ + std::cout << "Usage: decimaterviewer [-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/Deprecated/IvViewer/ACGMakefile b/Apps/Deprecated/IvViewer/ACGMakefile new file mode 100644 index 00000000..0b7543d8 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/IvViewer/SoOpenMeshNodeT.cc b/Apps/Deprecated/IvViewer/SoOpenMeshNodeT.cc new file mode 100644 index 00000000..00986e53 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/IvViewer/SoOpenMeshNodeT.hh b/Apps/Deprecated/IvViewer/SoOpenMeshNodeT.hh new file mode 100644 index 00000000..53940b27 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/IvViewer/SoOpenMeshSupport.hh b/Apps/Deprecated/IvViewer/SoOpenMeshSupport.hh new file mode 100644 index 00000000..3f51d1ec --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/IvViewer/ivviewer.cc b/Apps/Deprecated/IvViewer/ivviewer.cc new file mode 100644 index 00000000..d08640c5 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/OsgViewer/ACGMakefile b/Apps/Deprecated/OsgViewer/ACGMakefile new file mode 100644 index 00000000..8c47783a --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/OsgViewer/README b/Apps/Deprecated/OsgViewer/README new file mode 100644 index 00000000..34dfe021 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/OsgViewer/meshviewer.cc b/Apps/Deprecated/OsgViewer/meshviewer.cc new file mode 100644 index 00000000..0f60038f --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/OsgViewer/osgviewer.cc b/Apps/Deprecated/OsgViewer/osgviewer.cc new file mode 100644 index 00000000..d4dfafcb --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/ProgViewer/ACGMakefile b/Apps/Deprecated/ProgViewer/ACGMakefile new file mode 100644 index 00000000..dd5b34d0 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/ProgViewer/OpenMesh_Apps_ProgViewer.vcproj b/Apps/Deprecated/ProgViewer/OpenMesh_Apps_ProgViewer.vcproj new file mode 100644 index 00000000..0ae89add --- /dev/null +++ b/Apps/Deprecated/ProgViewer/OpenMesh_Apps_ProgViewer.vcproj @@ -0,0 +1,274 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Apps/Deprecated/ProgViewer/ProgViewerWidget.cc b/Apps/Deprecated/ProgViewer/ProgViewerWidget.cc new file mode 100644 index 00000000..f4b8b6cf --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/ProgViewer/ProgViewerWidget.hh b/Apps/Deprecated/ProgViewer/ProgViewerWidget.hh new file mode 100644 index 00000000..8f451d4f --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/ProgViewer/progviewer.cc b/Apps/Deprecated/ProgViewer/progviewer.cc new file mode 100644 index 00000000..d19f61e1 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/ACGMakefile b/Apps/Deprecated/Streaming-qt4/ACGMakefile new file mode 100644 index 00000000..3e506776 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Client/ACGMakefile b/Apps/Deprecated/Streaming-qt4/Client/ACGMakefile new file mode 100644 index 00000000..7be85569 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Client/MeshViewerWidgetT.cc b/Apps/Deprecated/Streaming-qt4/Client/MeshViewerWidgetT.cc new file mode 100644 index 00000000..b25f11da --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Client/MeshViewerWidgetT.hh b/Apps/Deprecated/Streaming-qt4/Client/MeshViewerWidgetT.hh new file mode 100644 index 00000000..6ee85808 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Client/MyMesh.hh b/Apps/Deprecated/Streaming-qt4/Client/MyMesh.hh new file mode 100644 index 00000000..b6dfdb2e --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Client/QGLViewerWidget.cc b/Apps/Deprecated/Streaming-qt4/Client/QGLViewerWidget.cc new file mode 100644 index 00000000..d729c478 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Client/VDPMClientViewerWidget.cc b/Apps/Deprecated/Streaming-qt4/Client/VDPMClientViewerWidget.cc new file mode 100644 index 00000000..ff8ff068 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Client/VDPMClientViewerWidget.hh b/Apps/Deprecated/Streaming-qt4/Client/VDPMClientViewerWidget.hh new file mode 100644 index 00000000..04a0741d --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Client/VDPMStreamingClient.cc b/Apps/Deprecated/Streaming-qt4/Client/VDPMStreamingClient.cc new file mode 100644 index 00000000..04d87370 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Client/camera.cmr b/Apps/Deprecated/Streaming-qt4/Client/camera.cmr new file mode 100644 index 00000000..7e58ad92 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Server/ACGMakefile b/Apps/Deprecated/Streaming-qt4/Server/ACGMakefile new file mode 100644 index 00000000..4be1fea8 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Server/ServerSideVDPM.cc b/Apps/Deprecated/Streaming-qt4/Server/ServerSideVDPM.cc new file mode 100644 index 00000000..12e4b975 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Server/VDPMServerSession.cc b/Apps/Deprecated/Streaming-qt4/Server/VDPMServerSession.cc new file mode 100644 index 00000000..2b8ba9e2 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Server/VDPMServerSession.hh b/Apps/Deprecated/Streaming-qt4/Server/VDPMServerSession.hh new file mode 100644 index 00000000..4723da31 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Server/VDPMServerSocket.hh b/Apps/Deprecated/Streaming-qt4/Server/VDPMServerSocket.hh new file mode 100644 index 00000000..ab66fb6a --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Server/VDPMServerViewerWidget.cc b/Apps/Deprecated/Streaming-qt4/Server/VDPMServerViewerWidget.cc new file mode 100644 index 00000000..7bc1e4d9 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Server/VDPMServerViewerWidget.hh b/Apps/Deprecated/Streaming-qt4/Server/VDPMServerViewerWidget.hh new file mode 100644 index 00000000..fa6780e3 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Server/VDPMStreamingServer.cc b/Apps/Deprecated/Streaming-qt4/Server/VDPMStreamingServer.cc new file mode 100644 index 00000000..15bc7df4 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Server/VDPMStreamingServer.hh b/Apps/Deprecated/Streaming-qt4/Server/VDPMStreamingServer.hh new file mode 100644 index 00000000..119b5939 --- /dev/null +++ b/Apps/Deprecated/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/Deprecated/Streaming-qt4/Server/bunny.pm b/Apps/Deprecated/Streaming-qt4/Server/bunny.pm new file mode 100755 index 0000000000000000000000000000000000000000..3e049810a15b51ec1efb62e26041a8d2deac2d1b GIT binary patch literal 840200 zcmX_}1zc6l*2YmVC>6v21r$`oRuq-9*9N=A?(XjH1Op2d!R{_BkTZkbuif2&9oY3f z&-w8ByZ?9XwPwwlo;`b?!?_Ix_3vJ<>);-3)7jbWOAjLK?3U(sS3S;Vm2S5KrI)_1 zV)AE^-|nTQgLzYp6<>MwERQs9-OCd9F~6t+S;VfH*yJwXuVpgsE(+2MN@bT0a~usL+|V8)-Q|O8 z24kXsI%CBd5830BY&qq#$}%9#SxT19X&gFv#567hiv?G8ShE z9uj2CJ>;Y>j=CY4Mr~Bb56{((O?=JVFLzp;icL^ctAv^Z2OUu9?k4E3^Q;oNzK=09 zV|Bgox|1B~-dokKQcpi?<0M0+p*mf9zkYPu(|oYJyU~7RHq~fvaWik5Bqi6s8qJEQ zh**CaIW``%HW-}VoVDn!aU|PFZMc^-d!8Jj!*VC;Aqmdr)@?0}@K%X>(~Zn#n8$yX zvu!5m=Iy=B$cPMj|Lk~uw&i{4u&tG`D80KbGo+8)?_XBM)gG_=CA&$n5?R!#xofoF z=D8AVh|%>)AARgmf;9Emp(brvsx$3&GzX?{EbG3F&_6nrH1kXusgG5BsjkM?7U$T5 z%Iim@PS~B*EIKWnI?%a-d>R@jeWR9zWGpsPH(XiLoK$g?4qMeu8;5+%;QtyJ-=wwX}IwRxFP#QuN?($s0Ca zW-ZNN)cqT6U0?O1yxrw1PTlItq%DSYTAsu5uy93LS~^OSBhMHccF)%nI(nKF9SiEZ z1750L_5X<9&y~jVf;H8DoywT|Ry|VA1*YkCb$3gL`Q^m>^abTT_o!HA1j*aXk$RBF z1IcvJOJ4q`jU$t+l6!a+aau7;EBn0WmJ4C}*OMN4aQAM~=0u`p+UE#ey<;x3XN9Ng zecc}7V&6>mecfa!kmaWG>Xj z>1FOcoT@fgjnhdzPRhITt(3WX2nIF^xOIV){?=qW8t;eYrmRHjl~m)=t;fBhDX^0aeS( znD%#6Xg^=G!Sq*F``wlG?o6#@QKMWkZh)zG7mAUKQdIioa1gtPYozJ-<*G|quzt1a zs;qV{BB6s`sZ4KjNKETivLI&(9a%qIjt$8#&oY(JM=NiWGfPWI*3lF7z`5DXvY(z< zYgZbsyFLh$!qsz1?p>pFx9~FN>Vy&c=QeL$cv1zKGOmyeUhS<*SvSawgJoof-3Fu4 zvMll|_-K+>-yGU{Em^WUmy_L<-SqD}rOfSDcJIHKFN6Nr_O#4ZL9$bJ8%L^p%8Kp% ztl3)sP?nj?rACv&GI7^*{p)^y)4zL19d0~V9a>g2qmt7rhYDl$x&DRC)bIiN?#M@~ zR%*0F9uAPZZwu;Vmpkn5#UPDx^x);>wpb+zT zX?OL;xv(CxuasH;Lj`NEyAis3H4h2#^Of6EpIJ9#I4?yT24kO{t8ZUQ=iQX-_Ky!bj+P55+Jf)})soz42Ha*J+@%d?VlxqdzUVR?2l z_wdOft8R5r>zxXj>26n2J&)E^*P2$6q{yn0cVQm2y6^=FEnimDxr~<6UKz~2e`3nd zD*Q$zo=FzJe&^JKo6A+xp9ReKt9MuzHJPOYV}44Z$1S8}|N2s^M5yF{nQY|S>!{C~ z;j*uGDV3pLTUGLFMH6d9O?8@WXs?xGU!avFmzb;rQ{2o|*L|h?rxE&YwQsWgLQ$E2 z{DsQoT;9C$?yz;%n0C6}Y9A?Evyxv|crAm(yiSxl!-~mUhtc|M>vD4Q{3B!H z4z%lH5i@JGbn0@CGSYI|Z0UCAigC+Ft6tNJ$ixwCrO@UCV{@%iGIm}AHLP)MRiv?D zzK*=1ECcErtBM&Cu(q7E*j86p4fitVcCBRCJAF1jwW=jenq`-K@2;vN@AI3TzD-M- zcOj?J$AZjLDX&!1b=y?UqaJcJe{0D-%0cGO9wfCZ`^oeXuZ&CUi^$#_KaFN?C3Nu% zKIV#n4=t~!mr&3A1I_2nrYXm}1$E4uD)MP_eKkCJh4Ce}rhLm?Oa`s<(W~3#Gn1xn zw?w}vsHLjE=|8oMWy`Mq>OytX+&%WBD&KFQF5J~!N<6a2mv^Hqn-2I$a;Z4$j{E>#jX^`I{f#*0eNlv(%{2qolN28n3dHZm08B?JWyyt~Ro)Y_FsC_m+WMRvJsZ z10}MNRd60sp_U1H_d6$9=$u1k$k9|!yx3Kyzlt^PdB+flkdgCwXwE^w6gX!W}L{N8{8ix9S77?%PZN- zy6&T-%oecVn-6Xb)^Q(K8RD8-YVH4NjnWDF@jy3oQQogcl|g0X-K;}0belGII=E~9 zTG^y?+#hu^(=y%WxVKrV>w^j{AM}b0Qsv}#wdceZ?OOJ}%(`&iIQeR#eo(KxIW}~t-kE2Z9yh~Z z+TM*fTpU*EF=NV@rUdJ$g;(fP-ofU`jP>-njr;YNi=O6_Yio@KYgX!!1xlE+x3mF>*RVWy=~%`&=2WqVW4h%)v!4$&D(XA{?r3F_Q5cinK^dRhN&uR3&UpAk6x zuf#VxWDMK9RHr1p7o%iTaUHnTINi|BJiFsrNQmDG{bXuc^La=;UAO;u{it~{Ni>Uz z!7)>%2{{BGHZ_t z*|}5~`QvMz7@to0PVKE1rVfxHf!mEAmm~DYMLA_?%6;R*_((nBQZ{K>_qEY6=Pfn; zTp3yA_FBCUo})9LC?*-Ezp>PP6s4Kn-YHTHomCA{DRRQt!^h z>Hj`>nPu#*sJ1!hs|FjC^xWdE_x35Sx)@H9>Fq(4QMt&qr%j}*=OgQp>T&vTvbS06 z%3{^=x365d(pxHy+h`3=3D$vavdVnVlJcYKa@5J!3>+~-)oGbg>nG#o#F8;8bNVOB zF}#Ag`~6T=anCe;ww03{d-m8mEo&dO&T26m9(t&n$A2@Poxd)-U$s-g_DglO61mL@ z&SlipO!bVn3%|>s>lKyXw86%Wt4GCt_hD7OY*#(yS{3Q|XpVKs>DBt>u2?ZtcWahx zTlKzfXQa``Ue=j8SL(gxbDIh84eRL7@p|o_AGZDvX}MX~82m(z2X6}5w<1axY*j`Q zc9*oc*vDA!UV16d!saN)nND&c>to4YeYf?~iL&zBBT{hxO*}p`gBti>db5T@XX}v_ z6ZQ4AdCVzAS0-g$I#}&+db_5FU1G9V?lipVp-D4N4V@-8kTJ6;wuJn~r>@yMvca*V1ud3;V*BhH%XUo%s7ix6GT%AXI$&R+IlD<^wqr0wilzV1T z6+Uu^&gC*&^1bb)vUVI}WSCh+c2qvCYQL|pZ|*W=(i3krw)FsA@QkDQXDg|UZXI;r zzv!<$Rn>HtEg|8pCrj@*7d?4hQpNh?>d3AuKh)vmW!BrlTk#C#rBkj>P?LPzuJHO42)*;CGPpn7ygj|@Mo zC$9TQY3IJ`-LpWWj4#&3GFKTlJ6zW}Gfk$R&ne?eB7r9%r-=6)?=bgG#}zHPW-6wSTRI-sMsU~e)i?TgY+ ztB#hF@t-ZrrjFHFmt?l}`S7^S8;Z-7d%7hhgBS9)qxAjuU{5Dr>T={ zTeDduO)a5kY;h91jgKs!X1!3g-{p~@-_dHtz>fNf?j`$5%`_bB?Ck78BfM|G>jpb3 z$O&pf=Rc;=hdQrmrsO~RQ)ixkX|y>57vP#EGeBkm83C^|0Y^X|`qGve{Ih37Q0h!` z0`#R1CGDgceE#_}jj^(VY``t;+C5Fr4p|@m)Cv7)^8jpXt~5zK2Y3pq0t1`{N5Dzo z1){)S;0+AK%nRuc^5Z%YvK;Wibs%IgI0k&d63_-b11rFFFdv)&FF{f82s8&{0n4us z@`LGs>GbmfS3o|LQ3|pr@B=eJJO}_GfOe+O1%tt;H2S64${~LUC;~kIl5NGSCcB!z z9(pQd7l2ELN1AK} z$#Dq+8v$c5RtwM>aJ*PH<2D7ez-Ykys{sAN0Q0fkLBJ0%56ff>wrL7ryEwiN0mrx- zpbzU;8nAqhO)(GxN&)&X2K{(V-;SU%5D*90rrv;d!fW~-0tM6A*_DOd0~niS1j056 z@)_s_-hzKICaV7%J!&ty^8wZ$wEyxd;hyH|lBLIEI1Nuz`j57gT0Y2b1xB&WqWq|&S z$2r0B>I0U~_+fx$a6WQ;CV>gy185Dx0R5Sd^N}{D9ReKZl7R6Un{^`eqffnb*h7Gs zW@r1DHUW$QtUGnKeHPdN=)Vh+uwQ7)0UO7L`$rfg*8uAr4W@&N;CkBi>@>-=Ibb>9 zoaNlz4mJUn5eiukoCEaxmyhd+dAT2PuVh@NRR9Y?U9cH&e(wg`0PD)Ql#I=5#%Ti> zi|t?{p|Z7h#|%n*jTNGKd1J0qtwRO29n%z)DaLgo3Le5flRVz)Fx0u&ffG0w@T$?y3N;J&p<6 z#&*32954ED4*VN`&R_Ng`(_B>dL0B)#Em4J0(IZWf+pw4Ud`AWd@ST}PfALsX#-yD#_7U4lIT>)A*iV(f zT)_Gb2BlD6+6DmD^)Fx=%V+)jfioZx)P}DgxMBHYY49a%V7F4kenu|vki>Ne2jYyEC(E0#^E`G zvHsPA<#0`Njd0GM0K9*)jRQa*z?ke`mdpNT9ScCRp2xwz^4b2?fOF~&U_HtLrdyDQ z^{WOH;FxnRuK-H`>lX@GU(O}2Mb4)grr6Y-D}foH34GZ86p#<_nqx>k3NRn@v#fu0VSdgH#-ktod3LN1$$GIp zEQfvf1iS+Dqt7JBr635fuAC2y%Qn%r1gr(0K^MTe!12Ec@&lF;2H5vw0sDUfXboBd zmdUbNw>sb~I0+5_uHSEvET8pg2L1vsz&)oJB-<4Nx&r!lfMi`bUR*27Kn>Vig7LWi z0N#Q2U>K+h`!UGiG@A!>FYp!mKrj^0pXCezEQ@hj-eSOX&X0ewYv7vs_JcEkW9*N3 z6~HH4zf7}pAFht;KOh6H<01LH835TG@C;G{lI`dPSmpt61hAdV$NZ^)aesqfX|O!n zn2+^jUbcGzr~w$0b!Pf^&>a3hAlVn}lM#UaYzN!Uc#K^hJOS(*j@gwoNqsb6EXL^o zT7iFKLfH|puh>tF$^K#Aa2@mj%>M>l1We<)<2bGbtS|j&V;a{e+t0SMUYs+m8|Mo9 zrfFJz*(Vmj{-uApG@bs;$29shLptv#cAzlC6wm;$t}S4@4Cw&LG2t^H$0Y*f!8M7?fsv1nG#hhiQ`fYrr#B6-ee|I`jUEL7hHK zZAjNI%6>I zR4@^6UNPQ#Pysv#je!gN7~dJNj68tj!0|``*+4kb7?bf_A&W!)1kBI5#X7M*%+EM{ zMxmr1uUA1n0IY9&FbQxT2O^DWn0LEg>Q-EX0Hsl4Y2e0D+ z>&g7gOW&D*{*3z=_yGDcKmCsao--OjvP||5^D+)4+r_){|Bu2~<>O`a`S7shAbG7r}=)9F_>O{bl4 zSRQ>@C-xJ|>Hz8h`ZFf$J_2Y^05Bit7t3ZnS>FIq4mMj~L6(Qkyk{V}ra3l@&$vvZ zWIC@Im+^Uj41qikxYpP|Jgb$&HS2GJ!no#|D+ahec~&|B+hR}<*GzkbYvyIYGXGu3 zN|5Zc^x!gd&cCZ*IhX;MkNFSbdJ9lsJzy-B!~NhE2nCEg7BmM<0R4}FYJg)#{{m?Y zhmHNix!N6)ZR9&HFI?{htP|G{$1*P@>&iTg&pu#ZdG3I(?pRt`R=MHqXhkeVwqNGkAme2aL9G3SKI@`p)VE(_5QGjh= zy;&FLxeeGpPe|^i%v&08Y)1jE1Nzd&G@G85&N7(iS(>CyA4kYszzSG4`-k;sUY5_k zw9P+A);SAcUFgR;vpuwP%sKWBfa`K?=K^H_=NRFAk#m%5j(Z>Hd_71$ zk8utp0q*02AbF0bjcJ^7yrzxk0>)unwz~-IET3hwy|i&ppp9uPgX@cBvY)wUj0B9! zvMYg|U@`~>%>OT58R)!kaL#a@rvo8i2=qaK>7~I6un`OZtRrJ{Z{+%Y0UPshKVZGs z=bT6EPx@Z~%)|M$4%Ze)&H?7**m9n84wM93vy2%4J8hf?wDUQX`9lHwnd`bDVEY+| zc_b~3c9szan1_=2c+K*dhkZbwWLz_ydAS}KoAqXST>tC?j#nnYdBJ(axpEw2#dVc5 z7>71W+8C4h8HZ)Fery~2n0>@Lu+Qkj^vY?H`FK4H>FgJ_oi@g#oqG)DFZThiTh^EL z4uRxYaU3}(X}5!X1JM<<0;~heXSq!0{Ng-gAG17`#n>#PS{lb7tHPEZunuf9=LpA| zaoATJYqs+fBpLnjcE^{GylK5toKjojKOrq84I0r{t@_>#&Q^+>GWed{n($y0rS(h zCS-lk1X!VG2HXc4Lvp`x!F4#uiR;#o^eYOOkCOj*y$rGsVE?eMD6>K~g0zQZ45nuX zwAY314p}G7&UMAuEUyK44xPTVv3`uhavWgeUe9=}59=+Ar&0sH?q z?6o29LE1y6rb+6FfRgE3A=iQ~pfO-ST?VW(>&tn-_O`?|=TAL=|JnXk!hcx@w&w?E zj_c8o34rxxK3=o_)aT)PA6T3wIlt*22r?kO93<<+`c}j>d6{O5g=`8M0G7EOl4HWW zoX-sa$Bq4;9&t7d0ruY~&<5A^XWnQ?)`|6_ zALBD0)9J^UO##c`HOGbZU>*LAD|PNQEGui8o#~t(>{yN;%dZ2KF@aDq0#I)p>A9^4ykdu^Iz-Xehg$9|jv=>h1&a=5Rs4DJQAF^zdLq)FYR^^#~94Z_!$B7F+b-S@BQ?n57ROM`V#suK7F{)&@T(p8He@#2FWrxjvO1V2aY%W zazL_d`qS41lJjCZ;Cy8|{kUeC?h2hgEbluc%cqTL&S{eIa)E!k6RsJ9b>lo?Ovd9J zXMXNoY{S2`#B0ti&VTyg(zaH&Lb4pjW=u-Qv}?|tBY^Xa@cLjH2h!}6?2CUsyk?)w zK37rVA0*@ZHZLt@VY>tlfz!G6Sd$JU$&)%gq&4)Gpebm6uAO#WpUxcg+iLxH4(bj& zzRRwD|Hv-|D*FrT&VOvjw3^#=xmR1o^ebfL`sEtqy?00cL|x16yX?Adku%V_U+jm> zx+gvU7T~+=%l5=t0=B2H1wh86Bl~uKivaoKxjs z<9J&JoU`4RTF$dpVNuUZRS{87Z*k1Ft|U>l@3)L5t=1J!f4W zemqy)h5hs7Bum~Z2W6MlPE+pH^M%&Aknm zDNpGC0ruO9`R$B^w-GWsT}z3DJ_{@YN6&}q#;>%LnjEiqJ}8&gh8J~q=q@|m&C#o0 zS@OZgvGhTD|H)puMgIj-tJWMv-(esC_Fsp4>#mJ`%WXB z7rkQ)19}9=4~jJPQwIWznbF(hR21~pU_Ho|evop08(`M?FG$h02Qa;D;|{uctM&4x z;|^5>I?Lt!%+biy_};NOK615{wFC42GU;ylWy{vk9!594Q zmQe^c-ru{x-uBx>J-n#1Jn|cE{M%o1!R}qLks4>WOZI7RT?snRPFcW^U01Bp1?Nli zQGJDVYzNzT$VTn=Y0F7xbHTc6#zpA`zQbz3m(Nce2Yk=ZsCoFF zT+W$G^1-hK;2tq`#1!ojR$4API0^S^o&mmt^6Ly^L8;5qzl13<&}#v%z2_At={Bdb z$cmJL!aa`rI`_Xh>vrgxxt~e!j+X}8%6l@~oyT>8cI)qIPWH?$v!PE1^TFXS*^Lp4 zT_pBMKeY@x@88EEt(AQx^skmz{T*c`^fh2Q(hQHOYF+YcnXo)UaUUrFxUW=P`dzIt zcFV+3K{61&Tt|Jut0N&&C|wZ=3!iLoOt?0#LcST7LnlpnEVrVvOMmF~0r!Zl6|Pz` zB`lQr&ASWdKHEDKd5(O1u5t{>DlL09;;q~E&x-$M%$i;N`tO&O8z!nl&^v*NaM;l* zF6pxS8L2xXT-aY@0Q;|1k^V9=ey-qq=td~?bKn{%{`P?SP_&u&%q%W%q4xqq!P(Fs zR>vlxQhD@eRRwW5ACh7Bc(d8))%S;Fj{a)fuefIN0k_RptjqV_mLJv2%0%c>K^R!H zxvUYq@Tq*+7pFL1*>9Y`(Px`#&(n_bFeazdK5d$^i#47sOrU)kQ}gr%8EXD;t_)tU!>jL-dZ!-52S_wtleI6q2*&cMD(GhMCQTS;&nu4roy zawE^w-Fc*bLX=!=g}+~e&T(`{+Pk@{_5C$I=Bls9joYwsujC$j?m>T}V7!Alu9>I7 zc1C~{a6V#;`kv$>r*p4RJSXss!1ICcw^&^~HdZnZbyK`=a!*PJ`DU4$9(t;Rcs{zJ ze!_Mc6bGv-e^vut2ANH#EU|KbvgtM@1=R$8uAi4$FL$u`qoIXVt}&FHH$hy0LxFCH5`U~dE4GmyIJvHJ8p zk95wG-pC0(7vTB9_5Nyo)bF_Tdyqvq7kH1q2N^PdpAq0ON%lrvQNggS2ONj3zO8kP z-+pmxR9@OaPX*n;tEiGvWZqhtSz(#AB=pVjZwtIzj?_1*9+<Vr~0>BcySh@6_0? zKX%M$wo9rd`(f(@+hFizVWfT^Y7hBz z$s6Nir8&}XRZ-jhaS?3XC#G}^(_7j*ns?hZGJ>FQ1bva`yRN4TyiI5NZOS0*ANCFV z=-kl-dgIevW?YRwY9Vwlq*Z{#-)0&ur@G3>Gfj=`(6fU2%=aojABQN|&d(4Br1Hg95M*>eXGJNL?$ds|8Cq z^p2o9xM*prZ~8ZpVUIoq+x7aMlZ1J^mMfhGSh#k%cW@oAnsh|HN_Sb}3Lm!hKlfXn5wl*|q_f3f{#1;! z=7&G~Y#?OpH-F0;*KyJ|M-SV1U_5N>>r+j)>b}jq&3-*<8$R%T46cAEw@tcA^G6cW zvWVEj?+oC&3w?B5eW?CS;v;6-%H^1|>>fLk^?*Vd&89P!8UD~&ZY0tgxsEov4)75C z4Vi^=llN0{5bo0kUERt2H+JXsfHsya#)tX?{UxLKCrXtBvsigY&KjoS8?3AhB@|5%dUrb#AcBk##9TR8|%QAZOET~ zyB-s(rCITwR^Fc)A&vK|8cpZx-3!Z`D;ssyuc1EzWx&1s$CCDL%qp=F`8oY;&v&f< zo6jY5p;_~!-uJoxJNK4_eSQ1YIyHQ*Og=Kx2!wwF*vdh^=y_1J4i!0iv8k+uJ_URR zy{4EtdR~yMTT#k({%l1X=-gqMu2$=Xj2#hU^+ODdrO%P3zm@mOY5O8}PmqA$?Vku-`Hv!A|N!?+>bi^GO+HO6|O|wDGBg0noV? z`#|RH5TWz8oFMvlMJw-r><9MGiy!0k-0MN+oz(8O=eXUlbq9T3@6va^Xt~>Zo`vJF z2DXmib;AlqDA4LF?y@8vB`v>#$-p_Vaa=mXUVR0}=hTSys zL+4(?GhCZ_xszTs&LY#?4lAA=s(@{vUH2pEdeBihyYr&rzHke+EFdUyir)DmM%=t7 zsSxPf!B{ZlWo_egmf_N1eM8~Cz-OCSQ09z}F4Szj82AGt?(yr={AV<^4~e$)k%ZXx zw&$R;uyapIUYSA0bXq2HNkwHP^49`fW6ysE>I}grWKjKL(it}1n-{=7pxsjI*xjy@ zc}}o!J#2-&DCF7b33`@ufVs8&OZ6XY+#`m-?%>lx&mZ_&9`1D(-WRXH#(0Ii3RqLu zZk231dJCU*B0y`{r`4>dn>KVYe^m9c^o6ZBI1C!OT6Kw`@8#FS=SCv@Cc}0Ha&bU& znd(1HBIeyQ;-KFI%R%4GCG@Kk-K5R}QG7m{2I66lyw^$NZ$?f3+uw~9(C33C;9G^p z#`x9g&5`r(8%yDv0vpGyThH#gX8#+KAvi#4!p8GS*7W$idZxcPh8LDk%}?5%J0`)G z_oQt-eI!fxdBONwx&L$T=Q+IXk41XL>FKg)P;v<82*;88#ICvrj6cP`$gDSet-M#< zgq`Q>JT(^?^S!OIxms1>n9PKY=a8pwrs>A<7xDMJ6BYM`AlQ#W?i#<`I-yIF@b?lb z!N$46bu;wrT5WBg!3_DYx$XS`_uA?3|FY<=8d10#qsybOERagUN5f6Nr? zUKbq-TV=pK;=jxLtzScWO6AO%HTR7rfa!SeW7N(2UG|qtv9SJIVPhLS&h^u^E0vd$ z5oP2J?E63uaG~H*b^7}x$!s4k2xE%@VwdqX&ph~TGx$XIqoN1(#0hWZZg5j>xB{LT6ua-&-{Eo3+{X z{4(u>m+gJmYuHYKu$vybT5(tY{i0YAHz&vpzMd6HoL^H?+DBWtx1EFS8|1W_uF_}N z6!~-}pKODTHwT`B{OcL&MD>HRv3zISe2#@L=X7xMdaBLwdNOxKJ>lMO0=9Q$`GtCX zPdC{)__F0U^j}~K{BJla zu4G95uI$ z8SZKhn`tLp4>@2vg0$9Shw4fRUnNKL9I8EZuE*|3pK#U97&qj!Tu$Dv^1{{!Oaz01 z+v?(bvYU?&PfQAg&T}>WeM^Uk@2w4TIJcXnBy{epcOdcilWI}A4f0`WUtxb`L%Ez6 zb$=VirQ;uDe}j?AwjN+#jr7LnE9CuNa$nJ4L!t>t^*sLH!aCb|Okv_7$OAS>6 z`Zkb&^!am^>B0NcnVgS2=W+d(fW24WRyy=iCNsq)%J!a?eeH%ig_gT#Sl@1wR@cO~ z4{#4y30Bx|(N#{ZmHl2fZTGLY@VA41!n=6gU{->>&3MuH15+MQ6ZX;p8+G9BhqCJP zd)s@P{qUa!?sQ*hl=!nx8i(Cdcj3#i#E)?GTj z*9Dn(<*=O}>;(cs*>UcfFF2HPCE?f_R-)`6rfcNW{ z=$$?RX4&jf>Iv)~u-$+RZM?(q_NgpZr%j6MgwLGGuxBl*bm2~J=AgR^Z0FvKunkAr z+mR;D!-dReKuyL)FfPHT5d3u*?F>_yX zP0jObCZxRrd&@jjPpgIb@E__`f@f!mA?1(&4 zW5{{MxI18DIh))@8JW(-$+@PV6x(zcwqKAhrZiCYZ?eeUc9(4DqI_sm22e9RUhmxe zM+}c@(g}W_Kr;Bbu)eC1w~TD+bHn!DYzb_ZW9;;Cuzudu+YI0N*Wi5ST)quDC!9AH&08$DdsmV}@O4IAVqrhK zqno9(^D24n)y?)f3-_yzpiag18t=%YWvSA(_ZU3ma345)?`Vj9rGv7#bw`_j4D8HP z%GF*T7V0cPIXcO6J*TEZhf8*wewjAzqYy!DDjV(_RmU zo%=S=3c)*@>Jf!J%mP(r8{Gd7!^V3+#U-;VPCooVEDzV&-Yc$zeL2`2noUlBKP>$k zHB^V-zX&!@`1d$dQRPXhXwE$LPAS;egWO2#l{;BEJPkG*r)*HvN5VHJx77BQd2-+}H zfB))XOXzTZMOGgMbTcS%hgpXQ-GiOr|VbiW%#v+Z8L~?ltq1M6Cw9bxY?f9+Q2^* z>HJNb$nTe=QMJ-C5q`WEO$CilZ_%f=d76648dAp%o5Dw-uQ*$F(0A zida?GjMle~`_#ST^H+?+4GpIFO*SU zu;l}ME>HLCvT}&FGh6nVZ+Qy8>#*@&h~F*HEw;Hx#L&k^Gw7L+)*P~5nHhTgopI8l z=?jXK)SliZ`*!k#<8G|EPNmz=#^r5kM57#sF7+Y{C3 z)L_%MS8KHsHtz8wf#E(!r}myHUwz}O+hGp@KHzuc0(~XW*Npw1MK^>W_qHmKA1{x< zd&VI$rA`god;V*%)dLQ8HFVWnO=L%=?26AEWq|>17Azu}+Rc&&*Y4WhXY$>%0;9?| z)8l5=mrGmH3Eu&906Zr@n6OVj`I^(*>lt7Sho3)e(@_7xpZ&F6d1o2o^if@gtp(D! z1~Pa~RAruglb_M9iqF3H!5{F$d8|(UoX$K`ytwT>*cI5gj=I>VsBSr8q-H-?+vk;> zC%-|=#mqYOz*0Hb?xEsyHErvF_Z&~1lGsWnzVx+ye!>3d`-<-EIpO{tZ?>Qr{4`=<~bA3Me@B1{?Xi@&2 z?AcaGT0mclSTlj!-%>L9)(-j8;eqiSI-ix-AU)?=PaU1vRbtvl*ghBFT5C@USRJ| zoxhEn8GgEe?fo|Iflq;_eQ)WpW1I{-e8yM~|EpjC?8AOc)Sp)@ltU--+1|VITv`kC zowvtGy}M10W~^iT{HqV*^ZwQM`Dk6+DX$rNa#uy(8$A(+=l3lyc4)71_a%N~X2TD< zFW_0Ne-U@h-*VcXSV2BQKLPe3jptH_zdz-gS8dq?o%?oo#E(4mOXYPwEpEZe_I`tN zDkJP|X7$mh%PyA8Cl}e?Z)Ae49MZlgCtB-$%V56RQq&j)o%{K9$oAEa8|A8;mXR$s zDxRS{L0(Y3eI*?uj?!a(73BfnRJ3{6k?xr_=Eo%-K zon8%wo)h-DkobK=z5SzysgLwc8U}q5IEb`OLBm6?ch4d*GTo>H-5qw`OUz8obVSP@ z^10g;;|Odg!Cu&}mwji9D*IW=q&r~rg6@yH#6z~K7OJm?PLpF%1JoPn0q|#gOVyZT ze0||6P3G(|>O*IIKCe9-(@Sy;ZXk;W^e{NK^I?lctYTDTyOZB!zZOJ>$+C0>gp|13*R?7 zKt~9>BKQxUfApH@A2R<*MYRd`@~~}$teIzn?o=yI4sDuai_h3Bqv4ut@}$^S`MCT4 z-@kEhNQXSVl56Y1%QZ`e zp6z0Lf6lf>fPzC7sX0wT&HSgfDle4Bv&dh_ZYy^w=ke>Me|KM94L0tFJZ~>K9xTZ} z67e~5<0S4?A+VK&zx$Nl+OEPrx&9?sIH&r-ejYNR-DUN4emtL-HDg4=_Zrgnd-l_J zcTJWy(e~05cHRs3z&_>Ua=mxGr`clDN^2B!FW5bRQ!zVr?#L(S{i>3XThKl{t328h#p7Sz{LO)N)jtezxpX296T5F`$Zo5m}zhBCHn5nz%dlX~f zyAWxOTWm_|w(7TxxRP7(oRkOf+%zfu936N0n8duCqJL?A=DolWZ|MI4oHVdJ_Oi&$sVzfsLY_lb2}I?cYE4jcCl{9dKe^MtFo zt5xba>`!6m^Fo8)la+b)lw@-_Y5QE8XP+-fuMsj?O>?~_{GC$j^AO_}cqEy0wN91g z)RrLO{xfzQ2@$8Dfmd@a10E1@d*-OUhwT zE!iD--S%F(3T!-|VqBG3FhBx&rP$uH{e-O>;`E!k)6(yDd6_riqS^r8C4g;U-1DjF z&4VK%Y@hpc-{85W>!#0^`jzg<>}>&Z6~0`jEfK5GlPbDmqJtT*`o3`lwl=UW0d2OM zdVQ5#=Gk=VjUCW8f@YxWktE$ZQ!cZ_=3~ZV=sY_L$w%a~eN`j61f!(IFMxmp5W&PMsw$CYw z!p429$IHEX_StjNFrtXD20HugC#1EVmp*+s!1jG1-ltcCW{CCR%Ub;=aTPw-_+fBw z;NHgf7zvlJS-f(8m#{lcl>wd4BAmPN)BiK_z8o$q2A8+(d)p9)&ujc0(OVVV%?fTJ zgW*>cwtC37JCm2(jvOP$@|99tKZ{`-03MgyVK^_1l75lZZJ+=0{x}rrzV6Gl`-LpBVnZhNn8!p3(B2Wnm3f9&KX`S7u~y_5-dz$y>}=l)nt?n~!2kOU?fBrCobGFpf$-&Xs6FgS-JRv$j^vrbJaRMt1+^P6qU zWHC55IY;?Ca;{vIE^ZbyOINF?cvjj0U!Fxi4SZvy6rCoADy~sUuos5?H0&Q!;`Q!} zH)X8vY@-2e92d^7y}!a#w(Tor>4Q9)`*_HibIyy^ z`K5{PMkzebMJ__$2H)af{k74$NQj@=yHh${5dMu|W1cJHV|3Bv(&pQO^=zLTzJkpW zM7M6NKfcXvR_Z#&_W8mv__JLHGcPtWcD*GX|IDyGM|0lt{E|7OmCjP9iv0O_%D4di z2>h3jSqt^4q5kG=kF2^U?CoH4gB&nomCjXolics+ZF}Ay4EsyiM?LTt9ei6V)qZV> zhkglV_JS-ux~1~3gWo$nGDuB^Z7TeCLWVyrD~0jCV&$D++vlp!;kyf@jE~c6`$bCG z175bzF}>i=`+xVn2aUUxUgNWE7u$JwI&52!miqgOH8ygq^z`g$d+%+5jqf+km3^pg zxLlCMPNi+{oob-W_OP!Q>MB)#=9bMxSJ=MCm>afZh~?bYF=_qYK)Jjw)b<{G3jCkI z-u``{uH7L>zE3G8@1ZY-ozF>;UKw=JH6LW_iQfj#&T|oG0n(d1X&{##1WVH776#8s zm%t4Amz|*p1$zsg`;6bvo5B7Ia^}I@I$Qem=1Ir-w(oQHfSu>eYk$sJ?!Fu;bEo{a zy&w1t+XR$>--9*0rtg&QE4*O>(#LHh7==3;!WV+xd9BzVQdbmpfy$+pke>caj2>G2!1UbFD0)Uf|%&~^sC zj6c2VME#_eyY#NM#P+;zfqe@6_kHcDGkEop0?xTZ(m^i^*dOy;3mCqovP#(r<<%V6 zc;ByzIC(o1(l}%@Qs7~o_(PzGQ>33&Yo@i z{_S4acs?AI!&x2s>n(NCUolQ0hCS?jE)Qx{QsbSMWZwSK$P63bYt04)YOd40rf!no zC9hjM!jF5BJ?wqn{5E3mPnUE*3k&yCzDMP~`S^iwwP{UfdGg6gr^2@~;2FrLUk#nP zwToG?a)fahdJue{fhI?m>&!lXW%cN0w(qlzL7Y8EZy)nT9avVt#QSh{5c&xC4g;HR zZO3nd+ncH7>Ik1d_XCc>h%2%B=!GKY&;0vTW7v+v#?K8tcb;!)dAo_kmuY4Dd^`wg zoLgDy#p!!poE@ZX{vpG&}V z>pm;{l4o%CtN+wpI>6(R@O#ueLuE&OCd2+RzOVG&7cKZ+zi|_Gj%^(5k7p;S^q(3? zz^byc82T&3E(n6kx7VdJ#)#{z0NeWkK8x`ArD0C&N1qnUc^zroL5xSRuYs&}eXGtI zyFq^UNVL6gVI6CM`1NJf$guD7uu_m(4xRf6-#x`G->EvK=9ST9{w5_t&w&^@L7&%+ z^cm}Baq3=PSY8Lz-wN6BSfH_JYi%hK{LJ=w&3nY*o?9kb8*_edmFIabsyeXch3zil z{7zn>KTq;CEA(7!Y=P}IY0D@+s3ytVsMNW2g`a86MvQt$n{hfqh4s)fv~?$$0Q+m$N&xvqg;%EQ@&n6A z*{|6Qo)3Nlf7o}`C~Q0&KU2mO`>lRK=UE^>=&~b0U;p_=rd=;*`~KA@r13uKT_Hf< zDV8jDv$f*05%1aGAiuQVpdIqZNtNUN79ZGnzT!UF?!y8dTQ0wudbhakd!9V|UP0N* ztM#|Oh-@fdF8@`WPa8l3w5#Lv8rs)mf%Gdo!S+40H}JP2t#Z3L_-*{Hl5nZF?ejtQ z=Lf{W_g;*j+kQ*vOc;yc^`E>zrLK%~lkZ(a?J%#z4@)zLQ?N z*-_@+S!_FR@T|f6PEWfz`p>fB=C#?6Z0}c_!`BUUJ$PoT-jVW9W*+wvo{2av+`Dz& zV4Zp|QASTLX?q{&f*1!t)pc&Va9}AZ7nY)Sz?aYIjRAfy*mz|5V7t%WguNi}hyN(A zovM7f3$o#LS&4)`5x#ss@Ty{px>4PbS5NB7JNWXQ!e^vyE>>H|75OH4>e}1B2gP${ zR`@53TdXI~cq!(daNB*2_cY$yj9ZDSS)iEjr`A$@Ka~^qI;g+np9B@R!eU-oYN(O0 z^Ip9acK17(rOWeea%y;>@E)5Jw&DPv?dX*1H)L`HA6bAH<&egA83X5Z)h?mA&Egl{ zCY6N!5bRv5!&NQ4v@!m_ORfZ2M!|0!Z2cfx7@w^bYSxq`XX@FWA9+6K`Ri%GRm1zB=!|-XCx&UwZj~hJW1;qm3zK+?t>;j)+Xs{##u)yaP!mvB z>$&oB;VbHLGEme+x(;;kSm8z2<#N>dbmBGs+rS$FFNSMm+(+S9;H^)IZKV9(+u?qB z4YE{WEsNvCL7*DazAbX0+?1m0|5Z&|B(X?<_k$C@+n z+Mspdb;ka_0X0hM*Y2D(^4ui=R2^kpiufd6Zr(vPGiuW^VQV?Du-*_ z-`9bji=bcU1LWjW)9FRA&Vp^UPLQ1lzHMZ>%y@E-HXp2_{FZr6!tehN`y(_*BTd-E>km ziRdctwE|$HL9rm$CDUZT;y0-5wFEUU<9B=y*q`WU*4ct%10}F!w3&{&* zgQ++Rsa{z%FX#k(B4|e7N6qT;c{*0chl)Tx6|$W{Ax+k3+uPgGtTEQaW&QxKDXusV zjK+0*OQWA0)lLGd3mt5?S#)NC+$lEFi%EgR-);nSu~Su9nn2TX(PcHnE1Q{}KLK6>Xf_k|PE z-+;fs^;(OTa^vyNG&6jTb_Uo4)aL}QE*Ac@-Siw;kLZ|v4C#r`wFz`!?lbhA@w;y$N4^7I9r+t`@$AI_u9_qR1i;G?0R$LHHS{}z)+ zTT{|-AA$;#mG}p?$)&A}<@o`NXvm=d)=l_(YzJOi;}|(Rsy4YyEkpB==I>$<=x<5` zIo;5V_P%mg{SNmzy@6--PnLUDKBXnjzm5EEa$8vrbh5`9S@QK2s#B+u@~2g8H|i4= zVJAb&Thh8>>kXxmeGmN3pv!@p2m*|Bd%jV@NhBN_izLay}FRj%}!N*$UKL* z13dhyCKn9x);skmF1VlNKK3YRu=@?o=lcMhSyoN?kw&0Q9%pSRe@KQz|E0`*b(FtT zd*Ezy@v2yx+I(A2TMA!i3*--l{s$oTpGg^9Ltn7ItdaYcOvrP;{k&hK)})vXd@8Mo z-!n5{wIFX37bh>&x1*4-(;D}s>5%UPe)Voya>IpEdfOXjYJE8ivbo?-etJlL8E&s1 zT=7t??-W9QHss@rFO>DtEGVe)+w9Uvw*he_@9;GHdMPnpGtzW>Tm{=j}H(+;?k zS%f^9>#Ud5TPZs>&ndrvcca2VIrOuwzGu%MEd}WbkoADBhtFD4J?A>)wCsYRKGM;U zzX~4CM+uFoUqC~Bz33*=JU(9oGIh3*7stob;=Iv<+u5zqbrE@D5?$q}uDfV(UQOaL z@={;}aDCi=mavJnp|e|?k~L(_fp^CB&%JoLuXPRm-R-9GC-k(3>>gZQ-R%rZqj!_< zODpLCIbJiU54slTFPDw`PERwN32sLoLeD7B>BhZf?@o@i?yOGxp~De8?vEbyX(zE3 zLYva6tNp^(c;Q+>es`&Lh8AQ+;bB`vG3Y-9SzF|}vgeNI-?kyS{=KIBxZZ=834DUn zORe7VB?Mn~!Q-9?t})vfZnf9@S&!?K_zzz6Q%CbF!{QlFre%FekN_$5$a zwWC_<=2CQV^qp+(ONT?2$CSNK*Cm|cL312-Xbq5l4m=n1I_a}ywbQ0 zNCvhR6g6+Qtm*2Zx7@TY)D`JP&~qAPOsj82e`I?alUiKOv-n-y0e(vB5{H%*FGqda zJN(aIy)Agop6jwtMS0Tc88L?_YiSm&JR+?b5PKCNvcL)X<)&eG^=6BJw1Kzcqe7<4IlnwpM=BJcjc?p7t4w zV2_$jZ6j}Ki-EO+`~_V3T#_%tD(P=t9W-=An%l(cpnZQk%E2LC`jy53%Kno9%olo| z_$<=SRd=N_?E;mbJl7=;x+?DYF7}1{=?(V0HKsxK5%4XbVuLr!!ammelDm!QFyuUe zaa&pYT(%7B=c2!_G*Ru#<8S^M^0nxgqur_SkH-H_RO`9i$A1FNcyvVLJ(O9ErC{4( zd(cSG@GUdtg4?C_QbR5Zo*PvJ^#vZ~7(fRabf)mcVl)!va-Yd<)~e;PTK3F?rh}lpzB=35Lx9r)Y|8FG+fbL~p(h!9-hM22EuKS`zxTtS0QWI6u8*BQD%1k8C;po+Bmj5a8YveHGSJ)=xkh*3b3l2>H~aBH zk!E=W>w4jokMuI&Jiqqs5h~}{eWUIjpQ!!FJin_7dedN-99F?Xzv$^mJQv|IPJm|q z*d~`hJV5lhK>5Qr1Md*<>A`2TP8BMV?S2;(&w<;19+SOWnA=@|A0M* zJmweL%-OH$W_nq*{?23e0#MT$+q4}u9I5cVty(XrkGk;l`#s-FYf(3bem3c)_GhgC zRs!AC{0aO`OSJKp#AM6We%3Fox^X=dVTH!1DT*z}lgO!1h1~zqj4>EO|Wz=b&v& z)*b-ozGx82SXOVQtaiMDzWC=*IT~0E&=K&xD%Zi8s&!~_tzfk-(+;=+@*M)V3U{w0 z%D(e|{bUvcM?3|YGUVelGfr z9)E7A_Pz3)uODb_gD5$Di>Iz7A5qWq{bqxEXD|M`-`JQoZpuSUG*G9JKVH9sOAOk1lv@IL^RV(Val0jj z-HI1Gk>3gOUBKtFKX2x}rVfEsl>b0+$kqeT`_&wo|1*asEuAZ#K;9h`34#y12{@t~3Ycm~ZsD-{o{_D`g^9YxE6Xl;41r*+=qViX_h3qJh{o+P) zcj;S=zfm6l^Y{2<`cVj5Ew4~OpY(3Nm< zndbfCDmiuEuKYQ9tWXB{r>2_tmzhl=wgV{u*f?N4SkIddbJaECAW8N zfo0>qQWtiYCrVoD=`SB-^Ka4+di=qk8J;0?imaozTaRk|ZbkzCjqA$H^M;~VGN@`R zOSMnAJ218_a(s-jl{ZkAdrry^@D6ZG;8$!8$`+;;`pt#kG@eI22Jt*=*Sc}7y-Z_X;q5BT7wV+7* zhP1R7d@&~7R{L9r0&_tg(^ARs}QqcdEapKrH{-jlz91)x3k-Xe;R9_akW18~PK!R*VMr2gGxL^6Q7oz`pZn;}e|G z4y*$(w#Bs1*(=Yi$|c)1Yc)sctpuz!`29z=muHq=CYLFh%0KoyFt){Dje;(OY1GLw z#^{H1eaHtw7tRq3?bailLeF+o>&|S`vIKwfi8a#yLOFe6WJmE0viywi0iWAwz1aJ_ zJ9QdwDjOpIdtm%57G3%wiX1vgncl%P9P&I~8i8xa13!gXW=EWMtKBhk8M-I_k;qgx;eEH5W?jz5$`Gwh6=a-=sjV~xae|OY{ z{R;*-wV=0);wdsFGrJPfV<0~m`d3!!uk2kFySdYK;M|w+`#-Xtm7En?R__y3D*GDn ztIl)me#_Pfqvy8W@1^56RlSySX$X_g_T`VnEDlUkSIwrxN1eZ+aw53(Hfv}A?khNg577_Z^H#nmd&nU1+FBikmWl|Mr+WFw$|acvv%$@)1p zxSB3fflYw?1jrBTK11#vTv0DMAwY5)vj;pL(;v-hYnXGZn11Nte$5Q{Bk0(TYy025 zWXyyb6c)QhGeGV!=prb-*aV#G?L$-6n~2It&wxBZ*Yg{Pd0e}3XLNKVpGxKY5{~I|F@4aIx4_9sn5Fjj@!ZZ7bfwX4F?;hc zI+I&g`C}{t_8w(?{bDZ@cYLLY;x$BHt|RaaT$jk6qVb+(zh5v^d>!Sb>P4E78t*~?wKa?c-$xQvT7r^E{{;|H(Z~3))u*)O!WM_4~^B44uT%G zlg!)YEo~e7>8I`osr|F-fn|dJCY7S)4=2#%cJ?$FY5rc^P@g9&Gv&6rX|$lArP{xI z3%pq1tp;KqG2{jPw02bMcgs+hJn-E7o5(LGO6cikjSTiEwAoq2|Nn)+RB>-b(uhaT1uk>MG*+w3S8pD@u8cgR=?SW(E20#$#v zTFWn;PhST+({|vz7QyfT~xW_qNCR!oLmeQ7+GMuY!1u&gR}t8d~5aTp{ZUtQPbg|FubXg?j_W?ayA|5$6}nt=FpSpF8%DZy|pfcs}UewcRqJ%MMEJ*H5j# zbc1Xk@Rzp^mDl&Lr_!nZ)CY2la8LcgyMA-dp_037sdBD^_8M|_;B5jA`&i}Y&IxpR zP*t%LcyW}y5@codUig;qAjheWgrpk#^SI;m=Pq*i5(~tM>aVSXd@=CiaQ)i7; z(U~jN)xLlVkj+QNhZ7cvyQiz@^LAj~0l85qvpnd}_w(Xlr&F}w|C}&~+-&H1jcbD} z6It=>7`l|cNH{~D$6{x}dobmoIJV$5pJhzFAjkT{f%|>#C^H)d5%$n3KiIComV$P> zjFXM`y3@`>8&rQ$1@e!9o3_~{W{pau_^X}Nx@3RUh2O&}OHYd5SZ^vH5H0wdo($|7 z^GYrh<^zKCgJUm<$tc$aJf3^pNjR!~@-@*r@2sPh2hMZ9A;6pd*di0s^XZ^RnA+#X zeZzU+DM!c3`v=PC?MK_tSm+)Koab2^UThO%CzaRTi_I}|U(J1XGnAVjmnhbiYeH8S zgsFLYFXV{>|4a2=@==7fiW{>CI$8l=28y=|kw5Ir^mo@jg${=fe%FuV+I{RYxp3-X zy7#AwS{FV9tTgoZ9v>mkBrc)4!JcY8m&Y@`Sv&Qmc35xJG%uv*P*A>CNpE*$EG^Y`qsQ5dmggft{}dyc7DJm$`*%|ozoBUWkESx zk7@RuY^Z6(Qe{u$Z^jY%W<6ab8;;GOi)ZJHG01-s7{7}HZ)V94PqJ`seK`Za-!D-n z_cJRihRV~;{q#Sv4??+3Wt-(>O#hZDc!g8Q_`F6MQ5_mhNAhexEc| z>te5vXFqsNOLvoFSMMT@!@+Zf%b+8W-*P)iEIE8uy;p2si-ztbKg&kjDhK&B<7(7=Y%1>esb$QHv#)2x*-dwj+V zI=OPK@+;u6^?t}N%U>${oT#Y}w5=rvLicTy+aA=`Hdi$C%%`z$ELFUz%8>m8T_M-Z zwEW|j>Gmp|Sq=GM=;8X5P5dP8e>BqT)wPsgK{n)h{ChdxUiSFgkQVkRM?;V<0QCpO z{wXaNr1|I=qbUD0o@4(*o+;8GyS+I|4-)sNxJhk*#{sW<`m`2QyeVaxX9%9-8c_Bo z=vnLz|B6@s`lJdERlL3qknIG#%j2rlYVB1Td1;P{&+GyGDX4g47ZGTGnS6`aqYpEMp(rn+}3qo8xL$kG2>1%e5+Gq3;@;|`;7&u(cIrxKk z-+3Kiy-?;BP*2%hesEhyPj}QLZcq7Jd4)Q~eVrk_i+SqX-A1VRP7c7>Z>Qag+J;Ys zUIe?4@c_!>@%#+vi%uRPSD!vcaVd3_|I9w%{NAPSa*%ftw-fevD*KEDWO+>@q2p9p zykbdOWcHtbS1>UC-rwvgDsNnNBcIf{YJWQSfdaa6J*vsSy;JE_)H=0~at>s9eaveA zZp0P5jyRvWh69kj1f1t))qah`J2j8vT5HLCpTO%t&%@4Fw3==esQ!UOBimuafH{G@ zrVzP5+e#lgmeP7az7OPYLEoXAsoHvBONEh@sTR^-fL8^7)ymE?yks*v{KJ}70}p}@ zZljZ`$7{>VAqHM}5amHG3mD7y2)ZmX+63#PqY{*zjcsg`pljB$X7Yt@p@$Z~tl}`7 zfNUG!^{UqpF1fY!$-h2}Ns!$JJ={jO^IoehfB22Us}`daq~}5QG0HAAtEtvCJB`|W zF_Bw=^+%ou$m7?jceI9&%e9Ml1La_l%c_I)Y6R113}+oAZk4FRvW$7mWL zhEqnTbIMPW?f<7ilil3psIfO_a@);<=eXyP#|3(i5^p7a?dD7-OEHeS$RPRni9*v=X7fnaBCyk1n6DDX&lY`pL+$jBz`c&~}Ne zy);DkZ`fV68{B3*1${gkt=W9n==;zbYF|}4Fn-?sgL}$)8++03&AW_qkahh!%IS1|7LskrqIf-=BJrZ`(IkeptGYmh`W$ z_D$D1NJk=1UC0l)7byQ8dPOgv#0j=X@VCytSzDh}(I%~; zZW%pFjaxh+&tn&=@>gJwkzS|f~seS zz8OSm?~BTGq-R66E_fw8ddUQrMzr2ofi?oG03Lr|RevYT%d_j~-#oj>r$}>O!sEtH zQ)kL>#BJyq=d1Q@#X!C^@;$#EE{9fyU7~hX;gbL7-wQ;$7hFuw8M8l|=M{}1 ze-*r2fkmbL=!f)n$!axT;`s%SnU1whtWUvODoN# z3>|-=D-G2B)j93Uu$z>Y<*oKl6#;K9aQ2(Iefj5U# zq9OEh`#cc$wQX_;eVNmS61EhfSYQiK#~Pp=n@l7{2kAK`bB#+NHwLr|{J0srWs`B1 zdhX<4wO*NpGTK95<^FA@|5YI`kynL%29=#F?+(fXpFh0jw4H1(lt% zbBcJ<-JMr7wk7lY5q~B=Gs_#d9vnqO5A;y`%6YN6HSkoIJBT~w(FuBZ zu2l~_#91}!d*Wzw&3G1Gs(HVliKIPc31Y_)&f)IzPaUf+mt=Z z|0)Id#Op|Q-B!sl_dN7FZy%_A4ZH@(_rP%{zZ}b=4@K?7Cg?Z@oWH&N!NrB=O*iTv z(oFqc{9BEOt_G9m8IL<$rb~0B+6SEqyaMo1FA`?!GiTjD z!Es-IWqwxiuG!XW2j0$u2Q{oo(goib6|Zs$l^uy~NZcNHl-Vy^o-);^ICNJ2qFkQ}coxft9FY;Pz7qOR?Gmt`kiQHH zc>Y^lsN9i;{3@;DmZU+)D)74;FN4?~o5}3&NRbPSpJ^oYoKIaP>AJc8x#)lK65FAk zfzUI?cCO_8@>hc##VF+Oj(1@L@&t_hA+DNQpg(;lypZk!UJ+2Liz_|2(w-a#+*SM6 zZb45G5RW4xWgGf*CzN=u!!}5+PqNJ#W08Vl`Uw976^~9p*DlD{k2J{dzl!O_GPbCG zhx;7aHk{9 z+GTI%{E+tnm2vGyPF~Gvh1CibUt%8QPlMm%X$f*lEKh5DIT?qep5M8ikSDuCGWhdb zYE<*Gwh)*D%YrX-AcE=(wK>^FzoHX`Wy3eE+e3YuWMoQL4-P|J_`54vw3Muv;7G4$ged=+chFM~_^r6*vb2qpUZhE^iW6=P z+y*qp#zQXrU`3rSJyiSb%%O+pz!_(}Wk>OenyoRR1HgD)mFGwy6;q{o%nI6M9BT9c z&Nhxez(dRRl3C4tsp)Z@*j`Y8GPzw{c-<(c_A9F2uTny-r#Avt2ehw^yV&XANB@>x z7d%fGfP3}i_v-i($-c7{tdg>Wp?d~++#b)Kl@mJAY9qbThWyWez8mnbP9gHxDQEri z?L|X3v>my@)X$PO~t1>srA80!1+CSkChS2<^-W_^hB3(U{eS z;5+7eFN+H5`>F?d{>H|QYeG-6^^+o5bM(K%Rd~udA8zMy2<3IG`bY2L2uR zOyIMlR?2%(4!Ykb6T!dtN9bO`&k26ES+`cxqdJF;1;AHvJ&_M_eYI5$9cWLlI?7L} z8t#?nA8D(n30`;B3Tsklqsx|@T@|wdFT*rJ#lG72dd-21M%724xrV)_$J-)cXUVxe(aeq`1^7W2wlBPqQb>FOx+0~&p511Et?|hTx z-ZT5j;5J(AXFm>{?FNgw6dKm9s70`UsQuuTkf$c}AAMO|EBPv(ydsOrXrwno2lxA- z<(tb#&i4AwPp(=Uq>lq1&+^@^5bu30MYig%{N&Go$8(;LN-g9B_$@5WHC1-zJm6bE zI73N(Jp6{t3td!v4_-Iy1{(eFpEhlI8;Xh#6x?ssfDR4vsS$aCK3}D0t&fPiz_Wq# z7;#qD1hp@COjR=x2J8?p?l(4Ey000hzNHT9O+{DWZXj3SI0r&A9w?%pkFKe0NBR@+ zNR&JN#D0nKm>y?mr~Go+FNnX@P)`rBU}g(ivF5LcLYl`EtC4SPBVCqBKSpb^Yfwq( z=!@TL1@p%gXuFROr}q}i1g}MK{m+3Hy~a(n?yw$qmEkl6a^*oi!0T$)oP2i=rNqS> zjf0WC1X*6Mynbts>{#*^!CtQXRd|k_gnB-=anr*0*Qe~lFyh}y;5Y0DU1fVN5rxx& z>0bIX6{nHw%433WMb~PbJH=DiK`&MO-fZaR-*d|0S+Yb?Tk12fKfe)|wg@ub}*3xy?R}GAdX!(558}psH~l=pydt zEcBcM9saRUv-vTQ1`K;8Iz#plbkqj_;e?jbDeE(Nw2xGAlP*J+=WQ5=$%{ohQ@?T* zm4AK!^6>Zi`P?|Ie2rl=dw2`wzjT+MKXmOJum*94KT(?>w~Rbq`2^kkK0az|L-Vw` z>_@8NpYUMb6nO5kCZghsvoy=BCEZ854D-$b)+s1O}Dh1kRk!Ely??9Wcg{pWdJYMBC zVx;*xxgu;m{joO}?ns|R8R59z%o{9AP&ZodHRbS3Yd zW$6d7dZ^P~@csAhk*)3>p`6j@m0xIU@Yr6m@MEEvebQgAJbi)kznTc$ji6`v$Z`^M zM_T*#mx>pW4;@zEmG5sQoW~ldc<=xAC9z+@RqzfiFv`Ln_IlW$IIRQp1^|DCE02fo z=Hd71y;ShHGYvXc;JWojCpj*!1RW~vA`TDI|IJbJyVt-|fv;#(Ti$GIqE9xl5+xze?M4Rho!9q>X0ystdWE-!QqX%4 z7|#K6UzRtFKXriiTJ4CEbN&_{gj<58N8N|kGxe|Iv(mxqqYVK zZX-*Yqg{f0)f2%QV%*S~sV4F_bPNUc2S41Wi!>=}ug|S?MLP&NXJFhf7t{@r7Y@4W zMQqj^k0G539^03K9cLuL~GrgHzK*)5Y*#>hQ@@=YpH?aLyZ*Wn?*=q}&$A}C3 z%_L$M(h<7?Q3G?E`?Bk)c$@2>V-#rV^eOU~=U?(0SdAES#dBkOOOdLxMSRvs`ueS{ieFk0 zJZ=*sE>@HaHe99N6Dtz;Eq(C}ZUc|*n<*C?g=`+^s$b?v*r+X0WM)Igi- zYfsT(f3+{j-xPHU2h|IA(JbTsP_@mjDz3YRa<7BGz5NwYY+kUQvcX2}YaRm~Yk&`{ z_(jYbSrX%lcokol-`$zW!}}HoyLV9EMH=K*qugr1Z-20$@BebCSMhKaXZsm&2^{C5 zX-;pQ$gjy6wV#yR4S{^EYb_Qve}1C&?Hp(qFkWjq3_Q8XbmRDw-sF6$6tNwIZ9wDk zEbjhwmgWHw^dTfr#i`qk`n&+Y{(zUF?jIlOme`fP0_z9jKHy!!4y;Ew=~2HtC<}7_ z(9dJImj9N?8|AHO`{ey-X#ot;NyU}&1y7A@(zhG?EwiUf?dOOr zU`IeZkmua}6glSh8miH?IQ>Ss{ecw&WyNFvRI!6(Y_eaipB{jGFv?}WuX_&~l1au> z%?;Rk+`|>fM_=D8PCcAYZ!WbXZX0;a#B2EpTVmytO3&zPb60gPNd$PekuTdJMl;ch z=mop3Xgp4OiD&!>c!dusXgB=z@cpKe`*s(8_MkhL)8ta0*Oal~zc?N|7WfYRo?o`h zLQ6NDKl==Az~N^UJEDxThnIuwBj|6NU5h@CKS@uLTN`-2?I~~` zS9}YdD?JAX>fRTI%QKK$j{1B;+5YdY8~b@~q>{yk5zk!=$YTepZqZ3b+Fqp7GyT>2 z<4xq*4u0F@a`bNPRN4{vM;nZE7s$GSH|x2r{I$1-vJ;F_N_Pb^~9oyDtqn@?R*N6-6 zEePilh-Z*xKUgpD^<918Z-0SyMjsd4hra<$Kp8cEO_kf0dyr4_|Sxx?+;@-G|$L)XNr9m>a{S*qwxuM;KTs!F62l~~0xcs$!G~!Ea(HL6{ULUk6 zK|MpMr*SMLA2J~`Iu*z{_$v#vOvkm)~%2 z?V!u+V?B9&wLSgpW2WJ8sqv2mt}o|HS>NAWPndT~?H{iV9ea@PwGZ}bE-9kl$l7OE zi2S!uWv<3^mamA_`SJ%zlvN-(gUL1ml-72D){)9`X3BDC*ArhPS>;^w~`M zch^L519E}T@ekz+uUOfumz)0GZMd;AbUQ<~40P>lTY|bAeowiX{wl8TJ>cJf+ssUs z`Gd;pn2)OcAlAs^1WI0IMy==FRB@qI#fSCmmX_MnJ0IYblU9M!(pbI>yv{G!v! z$-t^kgg6aqouVgn^IC;>Xq+}^=?)s<-%k1U)#SQBzT%sBQR_x|eauZCQ5W~*2|e7- zxo@v4n-?ES!|J+{57NhguScFHUFym{u-m_0Gf&I`W&|$>WM9TqR(ohmD=Pm|am6R0 zj%KKTSkni_=bvzh(qw1JcDh-R?GBpRGD|FNgmYD@xT$!#t)M#vS_h~_}-J% zK6+kf3`4$4|Edb>KkewihyUVF^0Vi8w0VrPT--W=ng;n1zsG-3ZaDOmd0a%k=(dhp zH8)l9$^Sr46zE5*^)h_*ZW>|dujY3=w>ydFW72-9JXxWv9(6>MB_Nj#C>3=I>+3JS z%&tV8k`4zi@XLfbmMB8}a1L`bCBR{9(~ht^Mw=7qOu$cAj?SINFAJ3&kL znah+}b11QGqVoGH4(ubSqgB4<)BGt7ITG~$oDY(ezDIgZE2`I6M#SrOhjDKMq5n+} zP5V>z^av)+iMhJcp(Nf(mW>O@noI0wT0h@DtdR*crgV!nt{jT zYO8lC+NQ(9_?#LQHAn<13KoRp0m2lkt0%^=tY7vv27-o zap<$U+(MpioJvo%6cvwX9G>Mg;4xDzsJ{JMT3M-L=pCdzkS7tezxl50hdVCN0{dnv z?nD>Vh3yTc9Rg{>nuRoC?VIdsz$zinD&Rhj2SnvQmGq~XXN_}!PX*o#^(ox%s_lM2 z)Zxfg@ey)UQ6K&dQvW8%4ymQc^muUhuJZ!_;B3wqh<=_NjDwV{7C^n{{Z-F&{>7g1X8TJT-%)9edg z3~2GTHqtMpA2~mps-1vrcj#a{>a(0Q*|4mYZW9}>_Ni3`kH>-oo30R>8~mnHn?GpZ zAj`gHJPw`z^oBT{;zOfr_n?iC{Q%x}Tt(OS#}MU|(m*Nl+kv42(2{GS_Tc8xRiE8)93&+#pEy@7m2Sx3#WauL04$_69P z`J8aS6+ua}`iPPG3Yt{GL-HC_1Lom6!Px=ro~K^qW)&3==P2-fz$5Ra8JZ2UqPY`? zs&gb?qdxX1-()-DBo3~m|9bJ)$nW4X=$;Aq%7J3CTkZgQbUak>e830TI^@~2f3TdB z9YImfClB%1hsQv3aP3F?41fDipaowdiS2+qx3|Rg!G|lF`{-*_!eo)!4>bii&tGm= zIi`L8{gILe*$FqKbMP#A-ZXzsnsgnLNVjL6)doP8$C>XzJJ+q18C$({KmQG?KjOZq zGx%-+HRSwLU1@b^FLmxDj~`w`&%*bq+V!a&2;&#k4)E_)4EXQTP35=D3-r139+8av z>@(5^yoN;@%eej}_22EPs5p)6D{&ZgT9_C`wvn?bY|SCoEx&pj&69h6gqTgK@ZzK7InKI(haus>G}rc_a%U{@7F-9Ib!@~ zJDU48NyR~Gi03ara{?+;bo31}L`~FovmOw)HQ1j{ryh9G`zyOb*=F_>dWHk9y=|>r zcF9g3cD|n4=gZ$>ebAK~9p$LewtD+hN0k3nb=1=q`khDjmo4j95aLA{)lA4C;U zk9W|OgzLA_o^oG$9#y`zT*ZNz46HfiyF~fYn!ZQrhQ%w5=QKRG8G$_8x=oYqN4V>F zzr-eB)q!0=*%>*#Ma0T%dK_I!{sQiS`r9DiAoHbi+r=65_IEe6?#63wJQlRP8z;v! zKT4TXSBl=yAt4(H{8Qw5xv|3zim2zP&dJ>iUF?r^?n#2d+DhZrzDo;`N%cmc-2Hhu-mv5Rl2{{Mw z&H>M_)mGMP>7ZlZLuf4S#~$)*XG%`#Dm%FRqVKMyX%%GI2D1g%B@s>K+fXN+`}3NR z=QT@ypHqI#mv;FR>5+4Ntu^X71M=RGZ+1IT-pMMfU+iR|&avfpXB6bIzdQ74mj?8= zUrV(P!fPNpbcxq1#mKi&B)nUxc^um(c`oR4lpIY}>0jw;ZoyUE5 zVK&y2T%WrNAJowuMpLW#pw8dG6H)I(Th9 z(4njLw$mzlQ>>RdH-yLXd!gsW@@V7E0yF)i>)cQu)IA9JEa(PlAu}9_W93(cUiOh}g8Jl|&C@1L%%nd7 z`O42K0lck{ub~xcN0-Ntm{bL4H==DrJ^i82Z{P^gX3k^yiER`-mnuZLJnp*CbEW)x z80YpLzGGYooY%&8qKxCEjB;&~vu-;MR?X~am+QHWmbidzq6~C1IRoa7JJM^VkHufEzw;3hALiQ14 z8vw8J$4plKP*ca;*!UT;yMRYQzr%)fS?b#nYIOXYiu>vbygT@asVuu2>?tbUUvL{4 zhG#>ZXK)a;4BA8QFXt#b{8i{+Tl~>W))KZfN}L}|?~s2LjW`P(+<&n@58`_p+KtcV`9AUZat@wzH}J|kE|H061NGc; zZYmzK9rP!Fe`{zcy)Q1P-Q-HjZ`KPK`v-2TG)M6Gs;fMq>A+S)k16om*F$KB%Od)k z>Sf@u9*;LRqfRl!H_H(%@~B;B-|TY0nDj4XB7L!Vvqh+z@rczwzhWki0REmwDdKU)UY!Jva}X0O0M zoqbSyRhUJmhMg4yk#2!!IT?8_ZJsFyg!|}LVc9DFOat&7fR9^pOB7lf^zpy^)HyPf zp!+ED#Jsf>bNc?FZ(}U!Jkmv=zaDrThwa`8531DBoY>!+{mO7L!G31(eak$`UGhoo z&rJo$N-U{+hX}0#>+@6NCoTK6^z5;I|^o_5bCrT_WNvXdI)cF)%zr(oRyBW$J#kQyv$gf+nMl88sMSu9OiQqX+F}zniF5Bd=)=*I2mhQET z&t@Nu&EOqC8LJo7lbiRO>2oiy3FYy9N7R+a`>7jEr2Ra9^0#PBY`10mB#*hMdcfRDWF}#q36KaCc*Zk z$U#9ebh)WMV|JSI<6@i8Ajn76sA3p9`7qV(P)wbVU<+9bP-{15(gyS^tTF zSrg!Ks~3obrzeO~OeEV2%t72QPrx~4lb+wD!-1~U333ut6!?P*vv8i;R&vU!sp7~r zh8pgJ-+G?Z7LBV;-Sa$@Ki(P0hM}B?W}b9$Y&8mse4*BD^H9&}!0Rk%ApNdgrVBn* z=_<-(ds<)UI@+_39Jb3&PwP=k#WA>!=kE($hBC87>aVL*Wn>K%A9W1mc`e!MU0Ko8 zt&V@|Sp;5sR5wLHJZRj=R7R4jo0GSHERJQvT6m+_W16g)JLc>R)n0=^*6 zh^j=91J;qt#dFFJncJ8G+}D1GPx^JDP z){9F*|4P*J*%OK1eLB6nR-L$SXZsu5Ykw9LAKEe5G6~{M*@;hcvkwXT$(0<2F+GpSf z=;;pmBYwk;4y7N{llptqz9F`I*y0{S`W(+LS$86JKi`iCy88kf3TiZ@jBM9)KAoyD zO%#W0A#_Z{vj{rqFWjsH^^sQ|it@l;0n0%d*9I+0t_xl3``-^sP`*A7}dRN8Y z=6)v_^vU?zFzC$<6Su}+i zE$JB2(@A88 zSlQE!t{jM0@w?`O$8)x&RlgdR%q*bL&NIXxU>ax&}geSQ}er^p|=*`BvCc(&B@optYVM!|EM576Bb zxOdS*GP0VJ9`ItI#$!D*$WOrYxog@<4h_3Ui_Vs#(kPGD3Ua~UKhs|B-jq%U_6HKL z@A5j@Q0U3u++JpM>_v6Q9@9=h{sgcq(Bsm>L!O*8k$hS=Qt?qQA`idQIL}K~PjsU7 z0d1)tWCMV$guLzhMfmP^(~-~fRU96kI~n=8-RVU0+jOEbNAGDvp`$nC=OJIh-=6Z` z+yWYy-AVZcRfmrIknb{Qr@Zs-8vQ%JFVq+51E|wZh z@r;*mR@5MzXQ;&>&Gs=KL-^{4h2`4g^tnjB+OPT=dS-*Sqjj9D($-rqHzGu20<%Y+ za*)p%KjGlG^OtDSE29{TG=J|EKpQfnWxF0n=}W6sg6DykP=9{Eo=>f=dHgG;->ox2 z`MK2t?-cR{R;x#d%}p0yXNA^Bc|2G5<9t#6IGZkkEVHGN-?LWuAeTbdY-hx&$nw$c z^HNouH#_LQgmTXZBuS4)0eaPqnsfp70$4uuE!?|TE*Q9rY`z+_4CrB-Q&C(igym_k zOJ1P44tGlH7fQORxcWaJ%X>#d z>#sK6uDXCa3VY?(x(V{$(0}Zi8{Ku!qL*z(DZl+_;Kv~U&8(Sh(9J`SsdU^}4fi?; zWQVfnCJrS3t8uh4;fjhQ>IfZ&fZy8iQG`TKCtve3VmIo+V?(wZM>-~p>~){%&$@={ z{Dr>Y@%#clc&cNeH-cwZ^yogC-<#3PL zR43g*#p4Z!?q8_u_jY|{|JqI24_xiLVSj)@$Y;N(i>%SvTc0_ny^-tQ1oC_zw_NsO zo@J^pE3q&n7UfQW{4~&+tHrfJ-FA>~&;BajJGT)$pJ=!g_M&~msr>DODqiAR=)MWs z^M0Lpo2Th>ukRJSCNmVzU^4Rjd*z0BQ#JJI9_2*|iYkJS><0D-LvI95doaXExh)V;Z|8* zyJJB!H-&}_L3#O*cY^+tm1@YvqnFS@-A~0=nSwg<`iyJYO`1zxYx3>B*w78>Q;>fG zJvZ`?$-Gv7>6iIt6~~6xzm}t%{83gUa(+woe4E+b;8u<e&%alg-&2uOW+zQQ+nBPE{s0|`;MLw)7w6hoP^@Q%(0ag+p?<^fMWxI)gnS4MB;?PM1Y1h=!1xL0TJ*iJaN;eHCd zSx4;?ybT>}CrmuoO{4^R6Q6(b0A(6MRlo}!zeK)Eu1Iw{OfZZF#%mxvUz{8=OszYo z?X5#RF0TOn@wl(dUc1Df0Y!Age^T+Kd9FSP_eHlRh}CYNY1N0`g4>u<(6tu&PgfJh z7<;GK6^qxqgU(PLJeQ1LK70Z##L zKW|6&qaQi+_xg9i^Ph3RlaX(5s6m!{YOeqDa!_{W;gG$GvX>lPCyqPY(U0|QiN|!j zHe!M6gKIZLqv3AU)5fUcN3p-qQsB4lw3aK99dujYS=xB$K8AZ@8^MLEm&B<@D=B4; zPW_SQ_mIc!*uSJ(?Zn6{c}6abAtxUt5I0o466U7f|2bcY$M@$;jeK%^ltSOntpnunkRA}$#X@- zixKrUkE2^H9M!yr=QNWbk9bmAOxKcBShA1cIq_oP+}=2MPL&VO`sk()i@?wB|D)Q5D|?eYBctq;NK{hFmXP{9*9zHtXJurQz4^b- z^ZmVk|JTp!bzgbTJ@CMkYYMiUS(4F^R9w)9B$bBR)`Qfde7oGwdfj{|+tr(HwDtE8Z zP0bti9@srl_UkqgGh%Mj*k^8Pzp6tQ?ps_=vG!yCDfGp{Oz;|!$1)K(Y{$QIaUGqA z{4dTD+i2M?+NSYhnV1s`2sO5GY~(fpVD)$@--fiW2LlAB}1 z>e0HgO|}!|qCNYKTu1S35=rB-m(#=U7u9&_so;GEyhZh*ly4P<6nu09%?3aFXlqa& zeJTm~Y4n_iA8e$?kv2eGG0MA_ONCpqnT%LYN)up2LN1><;XEb{dxX;HN|_dcHUQXj zK@VA7OPp$2pHhQlHU1T^k@!1sNb03ob7>hlj5AcvU5-GTR?xGu%VCji^Of8pt5GQQ z=nh_c)P2*`7HuyhzT(|Y65Du&;rEJTU7ySnJ=WZy$!$H<`F1eqJm*gJ&=Dz@8_O-t z6zy8@v0c;?Sjev+@b0Du_Ni(fqVwR*2YrxjGn#ZPm2T{PC~X1$70~(lns{mg)mRrv zx90?@b}+Vqtq0zv&S~Op&{Eo1azNt@UOwZ+-%adGNrTE=smik7TDF6*Pq7o;V@iC>MWzrsqrl^CxTsU3g!2 zRGmM{=uL-+ha%WE9_LB99Vmd_ ztMMc!gXRkT;UkY6(H&u*sZ`H7>VSR&SdTjSiLa?XbmN>C@i+4&3j5_DKAPA(!a@H0 zXq*~{wiEby{<-Z-x;Qf`iN^?OMHZ7SOAIZ!AzxY)`Q0+&lq(4O^VAGi(mdsFMJYbkm01~sl-Ht3Vk zrq!|>ZPlY!kjKr33~|l2z}eu>|C25HrCz47(rqo~4eII2`b%$1*TMG_I_9I!seP0vKUi0O zdEicQCir*`-V*fN?ehhELm-p)#rRw0 zmhYpQ+9DgV`KL;E(A>a(RR4}L$=aVd$JKk#Qc=lk zlvD4kK?{c4HEVYGqV;&z&Pj&Cn8cnx{QFhpCl+?MVb+ekT} zy##L=) z@{DV!`sqzT9s6Gu*U_Pt?mOsXwI-Af+A`1xSZ0d@C@?09j%-4lEzlMKBO3H^_p(HW z^KbYab))X!FGSrd$Vfb}SS;1`AhX-yQbW*NpbW%wG-m2T;qcdnZsebpazSI8+(ESI z6EHx`{hLPm%bTci4|x8}d&~=mjuCC!CR4gcf}+JZt^~g!{{EUWT>Q{l$~8XzRP8O3 zfprMQr????Xir?e{>g@edc@93NF9Fs8 z|L;;<^OaN@nx#|)-5gl8&@L@tl`{I{e#%N2MrK3fE7-{~mY&)3jodzNNgX*8%AZuAhMa8|r$@97Y^3;!&djiQn0GK);JJ@?@bn zcKS6nT=h;e2mcD_$iJ7zyXjOjauM*??8_B~uH}^X2XPaDVU005KPe2Y-hK{sCPBg(9_ zl(?x-jek`awBM*(c-va)J{bO@u|w!IuGywL1^O7BOcAceE2!7}yAs=IpQA1hb-T4K zY5nL#x}3US;SD}lbE?ZkOtp&CTC!D2X+MNG`~7Yx|fJ9&%UVc`?m!4Fz_Eb-$1-Q zXhKWkZI%9@u?^rbN~$tnvZ#NHJ|Ewt+VlN@r3RgUz!N;Sm=*X_W|`<1_F zqUiM6QO4Ob4cpjeU>pSK9IM-C+(HVsvQ^{I?gDKW>aEWvi1UH&v~K58?L6q=4SwDi z=KObQ{woRbl+^RK>>D@~GKM3*;{BPsNLzoEY8U;C->VAfS9gvPg!k%z!8`v?ezer$ z(KLEcFG_MSka$k*51d%YnSi{OQ4j3ovbxWt4!Dj&-44k8cwmW0xb7+^M*o*zAQ|)! z=(&B9vj|%Cj~@5cQS-~Nza{@J{q|R(ER%+0Yd%fe2-p&^_`aUHG+dN^(3NlIEm8BL z4gfaq-6mDd6vr1KF7e#QEp~yI_sF-PB$X@?w#5zPoGwSzypTHRR}$)fjA%v)>vBo& z$s>vVBzR5!39=VBG^Agxa%t=Szv?_QAJ{zCj2SswY4DchZ)dJ3R**RxI12hu*%bMY z>Sj^Z#cpbTz5T%AebtA@Y6!zrSGh`fq|yV|JAi!+bw4)m6D^dZ6tl6PhS$TqKmH0O zYFtzJcDa&o(~laqdFw;>kC2;jE?F%6;wbw+ic#a(@cU#W==yb!O3R1TAblTqDGGEsKG>AHg&wBU2b?Jr*KHt!=N86|mx*5UeC02qgXjtR5$Mlrm<>smV&vcNv@zkO zR0z47KzoDYx2mMrDk+`D?ix=!Aagh{c&@W!O}rRnTMKy{%+)x_J3!}k_QP{TX4xF{%zdF`PtM^!6b~4SC7DMlusFOgi zdStPfeb9_%mYdNE=wgCC%mTez-NTB*10T7O<#vVVfbBtJdvcMTm$Gb|o_s@J(KH7y z+q#~h{7Q}%(=29FU++>a&ue{w&-NJ3%bDK)4C#+NrMw6IF6g{R^0s)LntzJ(_}m7q z9WeNv*m}%MCD(Z=ZE5XDf6;zCXcHm(opZU;Fz#2Gf%MUE3mutnB;r74|ACc|bH371`VdrA zp0wJ9(kR>uOK%I{|0heVmI-8c2_7HdOb&c7w*} zM33!wru}=BNBuay$D#WvNr%);Cc7oy$Yp4zIgTQZsy7ir7h0py)vhGz`J+E2-J$b$wld)0S<6eVe=1tN5 z0pA$#Uq+d5HCfm+&!9v3ebsoRJa#WpbkaU4aa~%-$m^;Mfh^%GMPrDcz{r$`JLOCi`Uffd2XSt}3xN5-H8rLd_$Dcz4QaI@R ztlveOmIFMg=u~~ec`NmOegwMnJN>i2vuG34h~_D`lp)}o2l`Ra9geLK<%g=1Px(46 z+c??Q$=~eQ%FRk*dmHK+kf`SK>IYgF^bhQ_LTb8jBjuOBRP)%fZJ-mzqV5dHUrj=uICL%@^Gt&Po-?u!S98dX%D$|O%IQie=bNeVtTuq3 z_loQ;)fYO^L=P%fsOM{3AeU{jExwLXT93k6#*3Y(C$8DnXbdd-Nd=-yk-6OOqMI}g z?Oj0M2z}CL%nf$>uqP{3p;Gh4)Dgewrh7i+f47 z!iF9KKN%QZA^YZz)5=zyFR-X=r20#r294KX<@*PU>St@qeMd2H8#ULF0aJxx-U z?p#Z^+YM9WqVQhXV(9fLrbMA@J7`{=fogp3JCIQq{JZX_h&qqbNHlM%#+T-2=oRXI z99|E9#b$E+XIpU_ed6yg{|0rJ?iZ7~e<%2%wd8%o1)$GBIUI+0P4oV8o?@*NFy?`F z33^6OoG79mdDEQ4%UTU^+oLWFI8VLCiokF?xpQY78V$Z5sN;3V)a;+q4TJi0r{KB7 z@0cH`^8(iJ!n)#RLwjl(x>d{TNjvC15&Wwy+^L$hm-bK8Q_sEfyl6G_`fR;d7?;(M z|Gtk`<9I&>KCd^Aot-a^<+;jE^G2%oTX*2|J-6-4VZ8sV$XCZdl>C5k2r`C)zf&83 zWkHXJblzmIvKxGvz&?ojqb}Q}Jiiv|e&|!sg3vF1Kj>Z(Qf|F)%s)LzAAFT4`+ya^ zO^*ydx24gI&ugEcKQ+;Y=ZLz7`!!ESzo(Cpj;h_eEo89mJ3KT;y6%bd0+E$!UKkz+ z_B+;zb)lr(^VD|g18F??&O*n1z*@gGUNZIlN5dAc&|U|wEoh4|Mt%DB(~JphPtkAR zE3HAx1x8D>ne9GHT9X(<#)n@jY*&p1y$t#{v^ysGJ$prMTgz&kA7{uo3HqcXTf`J+ z0~vV{wfucI2R84K^Y7Olaio`fTGI~D#{;`R>Iz4M_{{lKe$&ig{{k8WuZ8%fsRdQHoI-8?6{0J(Y-3dG<{6ZyCOQVrh+ zu8_fVlyAMmM6ZnvDOm|njUW?r)Ql-`2BMX}H&0sMsptAtC4yBsyD zonZTdGiV$~>bUQ6MZb=lTz;uiJ?HfkGIs$B=k{AlUv=drKkuvgGT83N^O~3s{sJd| zf1UUWi%zpHI*M zVD*?fQ+lh-q8}q8X%O__HS;9s|6{>Hk!SUsa(=j|ahuu3z~3tG$z!B_!}R0{7dA;B zz&{k&IVgp5!f1f$YP#VTt%(62uS0(Ur+L9aG1SIXPIn8ITtL%<>-Ru9TsN75 zeXB~$%Qg;PM_+LmPwOVlRnJprN0&X zuh?2ww(O|=-}p->@O#bPR9on-Z6=p0D~rbgyApCQLf64@i^TWizViNn8R8P?w=f2; z!M{{863wnWq87uf)%^7tz-Ig_k@e~R!Ar0|3pKA6Kf}ELa^>tMF~apYd5!6;`Z2OE zRUTw?I}##3w%tI@FC{8`HZdL;Z0k%IyiXw42<&pJQz-GKKuaHeu<)HV9(endS7Q4JWpPT_d6 z?6?0yTc(@@uN&mLfIpzx1`#&ZMeh9NsnQ46ya#Lt8J!n>m!y!IG`i7LHSQ3vO;2Ks z!jEneK`oI7uDFzQ{UK1NNzxEf<*{?Z&+-y-lp^jW~Jw?mk z{V~8E4mqjUFH1)nS|ZoMCG|bO6aC_My z-V*nzCuAm}h+YdsYRFP@n{25BgB}1{3UJ^|Ehe77O7Gq@QsaHSh5oE-!>SWSyYH4% z?HQ?YmP|qa4EkBi{aQIm(CZlE_r;e9vTk744i ziH9ufw^sA|{X^f_pY->(iNfxx2hBN~FFk@9n^D-`mg5EY^|hCI-)$;r2f%Ly`j{kR z<$k*h6!ojE8o!HesO8Yd+-sFEQ;g-r4(+Kac$-0HJm}d^4+w*A7IH;$75WM~+e~>s zz3bL18l$bnWHm=$@S2kSY5D%dx;hI-UMDa4@_UWovlP5W=?(n(`7*)Bf|{oV zNo;r947w-y*B>qv*{AemtLaVX1L#XYZ->9pfrV0ycU@@7387emkI&qAqwJk53lZZ% zZ8CzDYv7Y0`!4iC{w-0@+FVAweeH0_Yl6}Mb&IQ>Qz9}qQGub2dY(NK7@ff%yu?uR zILVC9jglL#iy#AVRqnebitLr|=u5D!nn&^jFxa2LD!U|9GS|6`qYussHCXYW~5|pqB#Q+hLLT+1^O5+F4IwyR9$A zIS@GKO_~bdraJPIe=F5<%74KB0A_y)r#2$QrnbY`Wg z#CzudK;wO)1*L^bVOuL|lOCn!`^yG@E6_DN^vPjG2^kbmRpYYqe4_!zI^6t@vPFJL zh?7CJpbx);c^{+t?jmKLZzQGG{G@Ec^*bJa;It@<6enKHpt(CAsd@SyfHnv?6K0Q< z8b1C^CwtXY^D%8hzm@`Pg;Bop(7G|=m%dimj;{l`mmp{Pr$SNmubTY!vo0+HekN!Z zz&T}Iq8T#PKu(>1R&yNfw}ZYIeSlw+6jRHQl7H^|Klx`1+FUgPsHWODq=fq3zTZW@!PXhJW9t| zw_}ghc&c7-j>rPPZvGqTa%BZIDl;S}^yd+<640jmp>*-{pp$(5O0*g`V*+@yP17`j|$-BFJi=fZG+6^*)YKzy$yqS!(< z;<5!Ci`hfbMx#~#OnzUnkLKQ9Z#6gsI@<`mPX&o@y=xHXv9|#K2GICy#_tKM14cD9r47kC67MU& zMBO*waJ&w-BlY#go;38B34Nl$pKa@mxSigzIIg3x@8?ne4e=W^yE0HzOua+{d*!L| zczI7Q6~!a4j@WK$MtABppwj=5xdH7?7ler5uv+ABqKiVnutOccC(7F-3B5H=a?`<% zVja^#OMyPq8gEvnOmBg6E{hcQOL>U033bQ%4A4|@_&^^%Bq)x;!9u1s(4Wh)-R!eD6u9cdPW*}prbgFhx#1B71{~U9rEf@p#PhO996Ow0( zC8NKPu#Yff{d(?VoF)59}{W#guF^eBX$kg0=(tvwiht`xRoE)X&4aTvs%d969>qDx=5ObV!;xZNaUD7BDe_2ywgb9! zhYa=`gMTKCG29~YJ0lczjnD_rgGK_rfpof>hZ+Z98SvQ#I#AD4G4ZHPh6g*TaoS_h zW)R9|?LuK;HixR6>l45}6kX9LFUW988=_P{Z%h}L=Bel0BY?3FGDa9Q6QcA7%?P+9 z5%>$iKLW)iQ-@Z*N=6=;`s#V}Fz}v0n~&>Kq<1dM!Un=`HEW~Pxxqsuq1`u$X{b{3S6<%qNQ(Qqos9k# zDr-PL37k2obl(5TiW-qMcZ@hWrK>eXH~&UQ9%7C@)U zhd37CU`y4XZ;;NSzx+-;1Dw&G<;twP$0)0?g_>7Ai2IB-qiZFK@8c|F>BnRx4cE~a z1KwvDb$F?mxy?#mKf0D!51G4B7Yh1-w)*65`<^DQ2-DmF?kd!cMOnXOxiCA9L$_c!FS9b@8-SYde4 zT1Gq>Ezj{ifUyyM7+ZC-@+YeuHFtfd#uMf_2hS4{=S#w)dPCW2TAZc*${ zpZ5i=Pi>-u!8U3f`$%AI2Yth(RH3)sQSLTOS9=}fvI6|y@ONI8wR(Gr`-+5`M=11fG6t*{>i~FoRT6~-G>+DzkYj{oY(a7MyzrV*AIZd4One^2>5!LiIkjJLe>Uoww z(4{)$PF>bo)B0B}>b`!Oas>Q=kkJk}jU!@(M`JsAQ>H2Ld%rViY#;R~-mUbA%A}q; zgXt=;*~jNI^u2eh4ZS@WLZ0nEO3QH_3G8+FU2wKuvwiMKis=|m&4IlIGUD;K&awfT zCDt}{ZPaNs?$asAhy%UNhI~!_LksHJ{FuVD8o&}L#vgs8BcDuYW9?z;dCV8k#S${g ze!f)lv+Zb@cO(q~|3+X$fR4G6;$XR!5Z_3RSHt&O4)h&5Az735>?*D5;j8+|us-Z# zckRI=Wy_0l3VE5T@V)a8{aTFQzwBoN;Vt9+)}*b5?JR6_83FvK8P>wRo0n`lzE=R# zo}sV0D7D>=iPGZlbbZhwX)bU^pv^^K?a4P0mYv+?8?CBow?X$Tw3!c_#x7qZ?1|Ez zi_K^mc=?=cCh8tP8z}`Zji=$2-xRiqE&!c<4&p!N;Qe-#60RAk`A7bOcP;cUe_K_Q z%&kG6dIziV3O@hOI3$0YC;|hj%eEP3)b&~e=wgR{70%fs8t)Tipqww}eRMPEQpElG z{6)LqTqF*G!JY^!cZSrUS0oK3og>u3OPX30mVs4$E&V?7Q~^^byd%!S044c7qMsG=HcZ z1^y7wHlgV4Iw~zJ`a|$})$raX`%c+{KCAO8sjTiv(k*C9XF#(9?E%W_Bl|T2u5F?A z=|j}>q(>m5AKDeTrzopR-w^yC6`r&3S~m;h8L7z^W}_ZbQp*&H=K=2EeSi|@8!a~0 zah7#mZPfVW{9WjV^3ZyPIKKHCMcgn~766;q?pq*t@$(!h`*${N(%x5iZ|yn8ViU#( z^D}Mk6kA%@aiV&TmG|O0qwb%+jo`;MQPn5*W$<~3&y>Z0zQQW6Gx%a_ta)VR=Xaj&u8dmU?g>P-X5@ouSh zA@sBZMpNLK1iF&t{E3A3ftr{07I;h1=I*Yc;?xgYIo;)>)EfMw(1#3+L(`f#zge11 zFS;~U;{Z4U=N{_XS+&A>hv~@g)=4o%f0}~M`}JbQ1x*XFjNV4;3x0M5uzo}CiM=Jo z51y|lUH1vZz9G#)-+}t6Pd150_wD7Z*KO5&M&p3x4Sl*FuqVBU0CKDMTVneuzf(T~ zCu`6|s_V0WQWqSMZbH8z@Xvy5(;jJ}UH8|BFMUAE->!$i_rc$7TjB)Ad$+M%DYXDj zLlpjgC6!*2V&;9J=F#1>d_VEM#rrH1omVOKY}EWs8eY%y+}r{BR*TVyz!qC+-q$T^ zoVpgEd7$2X)e>=~wVj;xrmD{|@dOKJ{`CXiu-vaY+O z6dJyP1}(29nC}ks^ab6lW_1xgz?)7r|L^?8dEmcB|AL;*5;lHk;pgc^2Y}-R{4mfB zYHbrkd#2L$179_NL3;}<-lv@-chWBM_(x@j4M_*M&d`zfOpJ+AzH#Ei?f2AYjYQVqrtTgglmT@mJmXEb6vVKk-u*u+OF%aOjs2Qu`t49YR+HuRzlJCqfwKvP{WUDAKUcc? zSCN^V1Dw#2e7^`{)Y#l?A+^EsezV*d;XVo2wePQxCj<(MGCuLdyO(lxE*JtM~ys z9erwwcH2K(Ri5PZqmvVzs6S}zC-4q9JU{7ErGR?XYNC!akMUZ_XTP`Zw`^$RQC~IR zO(S6JL*3}27;$520X-eog5p8rci3%=Lzu3C7&5tvTyZv2?JxKB33Qs1?=Rc~Ovpb+ zQTl@B1O2N*cAJ|$M6`P%ogF(%;kB0ucrT;==IPzq>T3=YY({DviSy8vZQmQq7mKQO z9OPjcLE38I=X28=LEjggq*Q)eMlZtpsqx!`p;HjrlpTu~{igrLetlP30@`NqXF$(m zy?w>T`|#`N>8Hl2ZVe0>{6%3a#TzS2`kdo0{lU2K`z;xCj#Kv8znorcj;Q-w`M}}* zl*lIqV%PBsLfj!WuMqDgCIIW^xHN&i7pk`Vqnhu7-=F+_^BEtmIDYh#{rVhI^Iok5 zZ7by5{g)~7@*2t_+*0uKd;{Y!5`PUZzgLEybW-CQ@!kUa=~cshyKCWYG1@eT1|P{) z&;PD~OkQVKZyhb#b@rthF)hdy{VYYB?vRn)+<<rYz}X5t+YCt*FU{%^V)jYD!8aT@^HJ}$c#?QxJ((`28Ee><&=R!o z=)>lY3xtu4gI{OgM!Gl2OcjB|uLUAFnjvTt(Pud9DR?wONsOF4w(zV8ARP*dC)m|5YIvce6 zwR4SVbk~l)hqnx1TXh!noCN;AHTFtzS%@c})L!-HnxJC0Z+8v0ex+MA9v5$&%+_ciFp=demC`1k{& z;#!mdxx8=q1Z~`_{8LW(j3Ar~Q!;>4fi{)+o7L`|WLS`Z@0}lQ!}WS#@O_m!$VH2_ z4td9|Apzc2m(dlU4rei0#EozRJpKSCJ>-XdTHVvNo> z52hhfCmNG-P7@1yXVBU}Mx<;my3Ach1FprX@oF@{SOomRUi-zR(7hCLzCiOF7`l*Q zfbnP_9HmT1F{j}worK3|X)7A!UiN9z3ZR7d#oW2nv-S8Vl z$`(^1F!7mIO1&1T#qnqHZtuj(a^ zs~!~NEIs`!a#rII^4$3$N*yUjnCwrZm+#%wymjf&GYvTXhh&K>GaAd0r(FcUlT3{N z^IPljGFM6rE~BU|Zfe~4ozN!&ZT9c2FK!R=l-q1*rp$oe)A3u)0nSQYFZhiI67rKM z8qga$i~6d~jKrep*@U>JYP=V=CHF>MpH;s!B{j@w zK!W`edJ^_jng*tYpC^=KU-vCV*O2XE14pRz-g{dhphme!g-(2>tR^4X6`6JBcI zgFsksDb>Ntez|+GC%c z^l|!6@(pgIxPi|W*nfZ}zbF#-XMLv%x~TaHKGtV1`n5YfNuy)Ff+|`KQS)D4Mw>2> zTT?GsT)J06OGY11*#0#YIEAQlcw{7OJ2j^A>p^N9jC&aWy5PV0ccple;3O|_yiv?^ z0SRq5p30^#4a5y24@zG2-?`VP;9ZAuY{G6a>DV1A4Jni?pifumSPS%XwF?km=sEJq z?$!iAzahZthw-zV-%P3WdyjAXe5Ed~2SP5db1SnEr)<2RjOR?vqcjsTbwSUwHW%9H z4-{P(rtmq6^C)@1vh}o+T4V%JbVH(C@UlBrYqK4 zQ`bLnH1KR|g^k;fK;HmerTagWi!CnD(9_N6EwEitHw8Mi?RQaGDm&7-VP*ujDjk5K z4}I(k*NcHW9p$*%iZlYe6M+*6x#K(R5})*N{=Fbs!#<=n!219=1KtRQ`C2{jeA4IBlIKX4FtiKbVJrt39cNdwV768iHTT6?`3(RDw1UQ(dd0e?62m3_#< zn=TdJ;d=@32dD$|V}Af%dvpBlfc#wgn&M5oHhKg6rzrO4G}I_0nP^^w#tZx&;7x>_ zwgaCP=Nu`dx({m#88iprn4n#pBBf57GETHI!puEr;&S!C#V5E_L;-K{FHbHN0=Q9b?IRhm$6Zl&VkOMRx6bss4EE zi?#}12Uj|Ui;q`L>DY?e#Qp;-(Z&pa!}@JeO27U@ zOx!=(63A-{dNY*gzZ!^Ky>?X8&6S1%qdu@k;cwsy9m2bt%oC1FbJ2b$u&uzqYjaPj z!R1oQet1}o7svi%yx)6$?r2e5D}_3(^`J1c9|_$r;Wv1*nS_<0C9No2tMI;>3uN7_vv_ZQ@-o>K5se#j%xl3wiVWcj0fRiLg!Fl zn&e;Yf8!{!4Xe|e2q~gdFY40&sT%j755|V)ce3kjq5rV9+=Hyu_+4YcI}I|N^XjHgNLPq;e1!AMmW71n4A@O_J9ep?kyE~#pfWyz&T(r5h^q|zhAfEhm@2PS7 z*+$+4rDM(A+E(S~X-mWjHUH6M&?MlcIlWTq-(5?2R`rR`4Do*Vc*tE|GhK0gdx~N@ zwN}5&@u2ayxm8|>aA6Y4FpCBWcs0R=Y~d$9sM2Trz2-bPe5-5to7i(V34Y* zIA=l&?2@Hzpx1#+bJWe;t}75jopvp{qtpe>8)I1;GS*&A5*H`9$PK1Bs^^8-kC*)> zSsNQr%9*jMHdbh7fdRU+COg?6#;&Szlk+m)4*g&l^%H`qLVHW&aa03lvR<4y5bV8z_9=+ysqnVVyHJDRZlm z?7D8A!ZsE5`S=9c5!Z(co9uyPS$L(0*N&~g{|Y5&=OVG_-ADT66r#q{eheDhd&Zm} zt!-NC5`CZOOS2)DeG1+|&hxGvXxaD?wC3DDiN7BP7`L&wp9^Mv)a;qnh`!mED2~9W zgxol^i5ON3=l9;w!B7M8fZR=}dyY1#^O8mBFiY94-D~9paCU=Uh{Efy*N+C$y4?eb z{XC3;!|R~4xw*pfhPm7;){DGw&F|C>7(Z|4#X{O_Nog^aS`YA70oFdy{VpKh$a!MR!Kqn%}w0Ru!9u8)BK5cH|)ovg<7E!s9;!)xvg^p)q1uUjUF zc}J{hr@g+KH)I9c{Dhd{LspAcXYSL9JyzrZUjDxGes^TwEb*-19?i1QrA}ziwtTkx zbqmW7w;nvl_yiK$%g%wf62Hs6BE*Mnx`=Q-sMwu#2Nr)fr;X?%Dk6<(V_iwjFQ5g@ z0A=y+c4E$}YVw!NOwCpF^AKot&}N14M(OI)EK(}M)i~!XfPDvYL+po$UL9Oy$Jpzt zpY0LQ1$1imX0Os~@L%efc}(JU_)nB_@W1Q7QaENHzX1F(n}F{uu-Tq4JY5k!%PPq( zunMuyjt~0lkJ8XOR!Ek9@-NqE;ud(XVeCet-T4Od6~hMW;pgKhR)NNQJM5PjH)4g5 zek4=d{5r(*n?Ati`A*Unm?<}>XE=Cy^>03A7C=4>_YYcJ^82zAZc zn2M=gjR^Z!iXO)88f5mt-{;-!)HrN+*1b{qn)h(}1OLmntI9lO9W^;!S3N&vjJmau z9pPml?HjV25DQ-Q7iC{jo}X+xwqNAZGy3LeP25-h4LhODpr7d?&euoo8sjadfUg|< zdr&v&M6sBD)m%m#ed!zczd$bg`|YoKTWNo%j1Cs%D`P-kjq&F_&Pa#RqSL(h)G^MM z*e{B039C@Lr?nvezuD{;Duo008piY!aI7cJS9Gg6Qra3%#R2^FQFx8YaXe;aHKKy* zACwf}vwuhtWFX(1C^Wf1Pf9$A{e8y+`vGwDq?c0Hyx}xGaD#Fd^a;@O1aRusX(p1o zJIPt5M^*bX+nyazAKvwf^y)m(o6+{fdvW`L9R&Kq*x91=P(2#=2>Tk)Q3HP7-#B2| zP26c!LvEZ@9#9L|^MUPyI>ZN5+~J?|BFvT=L65zti$PuA=JDc=VG-qp`;sNDd7jC8 z10UNKE3b7N=(3Ts!u`B~=l2TQRZT#g3-_+ne87MCA4h|i{ZfKYBnPZnr_bXbuo&|C zf>s;+y*7nQ*SeU}dH2>DUUzi|PC3T^NC$HkmJ=;9s&(IuK=ASpCGgWYw47kGp)CzS|Ek}rc zuVTrl{EB)Gmu+=pfOW-SpwJ()g#30kP~%lT2mdUT&~O{^Vdw(7GjNd77reZ-t`D68 zR!`B|-c07WOllsh5zu8C|=N~aGlR}3*`bAcTI`CYEnC!LRO^l|21H4e5L zaM*X}{n;jbCYa1~gme|S?IGhVaO#gtN4&dSS~u~(JQu%#bqVw)_CB=T^DN>jpVe5S zy%TUAqik<~LiyL`1o`CoQ4nz6fd4f3jl36#lRY=k+<)%s{Eh9~{Cp3}UZ+T-LXnTD zl{ydSvvWKbx2u*Q8k{wy~|nU%h7smB1AXi1P+; zoIbX-HvvD#8S}}uk&lHt6z74j7i5P*&X*z^(W!Z|bb{=o7Y0icot{!|L6REZ`!(wP&}RItWr%0%B+qLSAtnLm5NK?dzE|^! za%hzuRq1Z4;pb`yFd`v;rS2Y$Q}j5FC#HCUwiWn~F`m0ZOqEu)EeWwO6y9TRi8gHG z8~A*yl(r(A>@Htb^MLc7$vf1=jee)`TK19#FW8{!(-?haoyK)8R*F3r)6cY;Vmz)t z18X|?C(N{@YdyM@FGvO~K!yc)M_bU)EobQQAS^jYJz>t2?X+6gqQFNgHTP9Jl2TWb@i)a!Qdn zwAM`iv1FIT_VFvgS%P+sv9*QqXCo?4bC-0W-y7i6M7x+83CgPNi>YFojc5zL{h+ar z%Ty~1(d(A8Y(8qSW+$-u{TYF=IFS^k=~*I^lW~Qb=PMU&W~08Q-sym@57&^-@8Q%O z*B8(yw&yfFeM!0=G?4U1wTc7muKxmfpFRw%e8 zc=a4&5HLmouV?usZN%3TRFI-0rr?^_G`}!*I&(VS+IhTTIA>>ZOIO_sGB%qV%y3JfZx4=lciECY8#NapHWz|GDMU9~`#;$Y# z^r2`o5T$>*nfRD|fEKx&R@h%Z2fz6erYjkW@!@UsI&T!QZ(0Im?m{2-)rwaNW_eR+ z-XrA_bQ}kIAnJQo{if_ZV?jUPACneBM_*&49;kNd zeDL#m7UU@uoomHXr-C19+(Pz+cg45`o^sLl`mmMW#*U^Q&}R_%T~KFiaY~uC&_&*G z;Yl%L$3y0Jl(p9!ls?iFYPsH2jd#lLldmYqEh!rI(Up!9WQi~Y~_=W{ndCHZ$RUFvEkFD@b?xJ;FO@|$+`%7 zImV}MZiG0#q&xLI)k?Y#xelP8M!)7?aT9L4pHS$;Ic)`}{CjR&PQ)->nYbv1qqEql1`QQddU&BsFjQC+M^Q^zK21 z)b8PZn!B=w!uwOaH|35JxvH&bSn-JBzuD1K=yC}BnZWxoM4vp(hEs?3cC-ua&q5~O zbGw?7*wf007T!+Pv<817_#=RK%sx+fTkKEQ7WJX3;Nxd58||8{>nZ-xZF(A)uCxb# zFrG&ledyb{w-Pu>2XRzJ7dHpJJ}^e0O{=G4g}bkjjQrtRzW;K;+W~#UnI2_!{jF5R zZy=R`{vO!;+!@?96nA$mB7-KY6rO|Rqs|cWk<&mt^s^w_O`p`bk-R>74P6&%3$&V& zp0s#-ADRh%-h)hFxeh-S%b_XstWj0LzN?eLYk(3$A>wdc4cYVKXz4J1rzW@$yP=Kk z-Atj`-ca_>`=fjV{W1Su&}q7HOHp02l=*z#XUODt4bNx%bN7jYgVu7N^14zy=;pu< z1>Nc3WD$MMm~Jh~kl0^pA!PSL;W*M$tsjuHixc$%FaI_@!M|BMgi@*{!^XN^jc@rD zb^TFSp{ql;55`l~&{Q>U-Xmbu!T4C1Z4$_lE_?lcq_qJq?`xMqe$SX9DNgE&JUKBe~Y7fetpzD6um(21p3Z!t;S%e4L#QBs^*nuU*287I{R>raB0$- z^Q~+6ehuTkVjSw&#t41uHZ*>?BaOgy7tqdhoQW&u2S3!?O8{*KXAUrYoD#@^1%r8T;5dRIN`VFbH{Hi-%zcGMymaX zZ9jHsH)dLx*xB6%@%K7Qc^C)wZ)7`k?9JcWSM~JeoW{E)eurHLeKGjE_An6}B11Wb zj*<+F!;rZQ?c8l#HGOQRQ?Elq)qH#bpzlS$`x!+kG|++W`hSyb(Y_CKNk`rJLK$%y z+j6`qr8@XpVQhGQ(zVAq$@O}5O3tby`9Wqk@JB(;$P?$KTD{FUpQdyY`se{`2JUs= zj-KNCcn7)ecVjgU^A2E40DgLbzK}ZQP~4*rs=aYG=xlQw;#{oQrMSyh2WBZDz+m5$ z7r;AL+eZj1W2(1pk(xJoAu!rO?lRkHBDiiPIV@?T#{YLhn*y}SeQl)lzUV-az0Vi( zJ~Z0_*iW#k)urN?1qO1>udWseSCZ(sc@26Fc^o5VD9Qu90a_%Gk%z?G(DK^)FKCM~{5eH~(Qi(?e-ME2{Efdne|z3@64n3Wrp6cD3|bWA zSKf6K7o6tOM7;*Yw0PjKE!+78?-w7XqGfxPLg>>CGy&PMH6BQVy1LVznN?^v^e_Yd ze#pIwnMgv^FOsL}sPW#@!G8gGhOV1M(TQgAyit<)1pSSG@doXb{DInS{uY{xW%p$&NG(zGGWP(+9@L%s9a((jnx4F3 z&_yYq^#*+e^x^Z)HKM(F{#jg!_ERzTpU{t;j{U^d9mmKw!$-~Y{t>+V9_#xpOq5wX zC3`7J&69Eu`tZJahl4RLrC(SstZvoz4z$>j8 zD=nC$rQOl@6h2Q_34S}!16-RI&v-VI{iy`6Z%r`$(Z?YW|K1gQC>fD>=~TCUn_^zZZHrh_1`W(3A*&r9Q4_0E_Kd@fodzN3f@CS=g=RW?=LF zY#`_-o%TwR+s!%OtHkfrQ_$Z6?M$w%6X!3tkR5OKgP#l5jgb2qWlHG+vDDxUeS5J& z;pd;{pZuKatr{;T7-ZlaP*dXlLVh+9aIZYN;{d;!om6_WKyd@k3t<07-4(|OaS3r+ zY|XzF2cbRd!s`O88>QPt3G~q;oQ44VG0HFCupQZ}F-Tv*4;LA+{gQ>DN^0g)s;NZ4%_Coeq_z`oE|BYwA*4$mR3nHzD`y zhW=vU8e`61pvEmP2UZ&794X2W2R&=Z$cv(F2E8jlPsA7vKU7tOIOULTyQ+e}Ewdq) zZP~X67mBW@4pEoF|NOmkP`4U#eD7`-p~p|sHH#GO2hjM;Ngn=wx7w)*J(WmJ5={i# z6i0)80Wxl!d#@~A^`0EXAccJ~=0ne!ke}@{K`iR;D5nO^mG~S2$93erx7*jci0*Sr z>HqO`6;N4xPaC@kK|}#5K@3n36@+(Z?Z9pf6bvlvj-Mi;l!_>df{B1Ah=8I3@4bqO z-CfwNSlET%Gy6a1^PD}nbLT!YcXr?1yL0ExB)4fvH$mrT7=KUY^xq>_pL|Ru5rcL0 zfz2^AWAJy;zWQ?Z%r&H5j@I(gaU9xG$T;`aQxuCFn)tAuTn@fq*uF8wTc=T!tX62J zzTDYUVVNxZ9`M<}=}!%*!TQF;{^)1uvyyf4A1?2dRHX}9FYTzU0JL1TMzVu=rd{V zYO$d8W9(aRL_Ah2$PI-(_O~~cXFaoN`960o-=iORXP|A-i0KM-GN!P!Sn&$-p5sWw zZ)0AFB3iv&NtyQoiPu^O0wV=>M!pEDyj4#YQ|9YAR-!MCqi9>>`bhZ}c$E?sM~NKJ zETLmCWDI^1Dn~xDR96K))#|44UQdpNozcpJn&!6P_`|$J=s6a=lR@`h+(=2gWK6Gu zErbuwS(m*yZvM%WrNgVMlMN0k5x}km8OyofkJWPX#7tTq(1du6!Vt2jnNzU$8&;MaTO$_;=0kwZi$IL~2+o^~Z@+J>SP8 zaLuwow|UWBp6iM4xF^OG2s-ca;Fy(R{*H3nOA|s|q?is2bI>@C8tP-|T38yxkCdq8 z$?pz~wrG!E8>F)c?@CW*^&|FCwSYdGU>_edkVx?i?HXJJw4EW>i#_vD=jh=xBvL{GIqWI6=NFvr-cenA2_W4F?SGcU(EK zue=`cfmYS1LWSVp4PJlHmu3iYG%cSddk!K6dfdSg0IcCZ_lR6SJKBEClsJCN9=2pZ z;`-1q+48oz>R@k2G3dV@*D4ZtE)P!Yop+z7PQG1<*R-=hXP@$?@yT+5cRdwJY_z)A ztdljy(Bou|bPUdv611!cLkv%@&89?EIZ%A;+wXR=&$ zVIS?gS(7dSX9Z(J�>-bX@y4xt!4QqW{5|ywGQKr%XAi;uAV~P`n)X) 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%0Du!!PY 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