From b690084e9c682b8e0620a35d3b53134f9a0fd4a0 Mon Sep 17 00:00:00 2001
From: Florent Berthaut <florent.berthaut@univ-lille.fr>
Date: Thu, 22 Dec 2022 01:16:32 +0100
Subject: [PATCH] First commit

---
 .gitattributes                                |    1 +
 .gitignore                                    |    7 +
 COPYING                                       |  674 +++++
 README.md                                     |  177 +-
 data/Info.plist                               |   27 +
 data/build_linuxapp.sh                        |    8 +
 data/build_macapp.sh                          |   11 +
 data/revil.desktop                            |   13 +
 data/revil.icns                               |  Bin 0 -> 40371 bytes
 data/revil.png                                |  Bin 0 -> 19943 bytes
 data/revil.svg                                |  159 ++
 data/revil.xml                                |    4 +
 src/Reveal.cpp                                |  718 +++++
 src/Reveal.hpp                                |  272 ++
 src/audio/AudioManager.hpp                    |   41 +
 src/geoms/BoxGeometry.cpp                     |  116 +
 src/geoms/BoxGeometry.hpp                     |   38 +
 src/geoms/CamGeometry.cpp                     |   70 +
 src/geoms/CamGeometry.hpp                     |   40 +
 src/geoms/ConeGeometry.cpp                    |   71 +
 src/geoms/ConeGeometry.hpp                    |   38 +
 src/geoms/FrameGeometry.cpp                   |  131 +
 src/geoms/FrameGeometry.hpp                   |   38 +
 src/geoms/Geometry.cpp                        |  168 ++
 src/geoms/Geometry.hpp                        |   80 +
 src/geoms/QuadGeometry.cpp                    |   60 +
 src/geoms/QuadGeometry.hpp                    |   38 +
 src/geoms/SphereGeometry.cpp                  |   84 +
 src/geoms/SphereGeometry.hpp                  |   38 +
 src/geoms/TubeGeometry.cpp                    |   73 +
 src/geoms/TubeGeometry.hpp                    |   38 +
 src/gui/AttributeWidget.cpp                   |  517 ++++
 src/gui/AttributeWidget.hpp                   |  134 +
 src/gui/GuiListener.cpp                       |   45 +
 src/gui/GuiListener.hpp                       |   45 +
 src/gui/ListenerWidget.cpp                    |  109 +
 src/gui/ListenerWidget.hpp                    |   57 +
 src/gui/MainWindow.cpp                        |  250 ++
 src/gui/MainWindow.hpp                        |   90 +
 src/gui/ModuleWidget.cpp                      |   58 +
 src/gui/ModuleWidget.hpp                      |   44 +
 src/modules/Attribute.cpp                     |  316 +++
 src/modules/Attribute.hpp                     |  330 +++
 src/modules/ContextHandler.hpp                |   50 +
 src/modules/DepthCamModule.cpp                | 1805 ++++++++++++
 src/modules/DepthCamModule.hpp                |  406 +++
 src/modules/DepthGroupModule.cpp              |  116 +
 src/modules/DepthGroupModule.hpp              |   83 +
 src/modules/DepthMeshModule.cpp               |   97 +
 src/modules/DepthMeshModule.hpp               |   55 +
 src/modules/DepthModule.cpp                   |   63 +
 src/modules/DepthModule.hpp                   |   60 +
 src/modules/DepthShapeModule.cpp              |   83 +
 src/modules/DepthShapeModule.hpp              |   42 +
 src/modules/GeomModule.cpp                    |   63 +
 src/modules/GeomModule.hpp                    |   57 +
 src/modules/GroupModule.cpp                   |  162 ++
 src/modules/GroupModule.hpp                   |   59 +
 src/modules/Listener.cpp                      |   73 +
 src/modules/Listener.hpp                      |   72 +
 src/modules/ModelModule.cpp                   |  286 ++
 src/modules/ModelModule.hpp                   |   72 +
 src/modules/Module.cpp                        |  423 +++
 src/modules/Module.hpp                        |  238 ++
 src/modules/OutputManagerModule.cpp           |   60 +
 src/modules/OutputManagerModule.hpp           |   54 +
 src/modules/OutputOscModule.cpp               |   58 +
 src/modules/OutputOscModule.hpp               |   53 +
 src/modules/OutputPdModule.cpp                |   37 +
 src/modules/OutputPdModule.hpp                |   39 +
 src/modules/PreviewModule.cpp                 |  315 +++
 src/modules/PreviewModule.hpp                 |  108 +
 src/modules/ProjectorModule.cpp               | 2419 ++++++++++++++++
 src/modules/ProjectorModule.hpp               |  227 ++
 src/modules/RevealedArrowModule.cpp           |  348 +++
 src/modules/RevealedArrowModule.hpp           |  199 ++
 src/modules/RevealedCutModule.cpp             |  393 +++
 src/modules/RevealedCutModule.hpp             |  160 ++
 src/modules/RevealedGridModule.cpp            |  202 ++
 src/modules/RevealedGridModule.hpp            |  126 +
 src/modules/RevealedModelModule.cpp           |  114 +
 src/modules/RevealedModelModule.hpp           |   54 +
 src/modules/RevealedModule.cpp                | 1797 ++++++++++++
 src/modules/RevealedModule.hpp                |  469 ++++
 src/modules/RevealedPathModule.cpp            |  446 +++
 src/modules/RevealedPathModule.hpp            |  134 +
 src/modules/RevealedShapeModule.cpp           |   76 +
 src/modules/RevealedShapeModule.hpp           |   44 +
 src/modules/RevealedTextModule.cpp            |  200 ++
 src/modules/RevealedTextModule.hpp            |   68 +
 src/modules/RootSceneGroupModule.cpp          |  131 +
 src/modules/RootSceneGroupModule.hpp          |   77 +
 src/modules/SceneGroupModule.cpp              |   40 +
 src/modules/SceneGroupModule.hpp              |   66 +
 src/modules/ShapeModule.cpp                   |  123 +
 src/modules/ShapeModule.hpp                   |   59 +
 src/modules/SpaceModule.cpp                   |  315 +++
 src/modules/SpaceModule.hpp                   |  111 +
 src/osc/OscListener.cpp                       |  188 ++
 src/osc/OscListener.hpp                       |   49 +
 src/osc/OscManager.cpp                        |  264 ++
 src/osc/OscManager.hpp                        |   97 +
 src/osc/oscPack/ip/IpEndpointName.cpp         |   88 +
 src/osc/oscPack/ip/IpEndpointName.h           |   83 +
 src/osc/oscPack/ip/NetworkingUtils.h          |   56 +
 src/osc/oscPack/ip/PacketListener.h           |   50 +
 src/osc/oscPack/ip/TimerListener.h            |   47 +
 src/osc/oscPack/ip/UdpSocket.h                |  176 ++
 src/osc/oscPack/ip/posix/NetworkingUtils.cpp  |   64 +
 src/osc/oscPack/ip/posix/UdpSocket.cpp        |  605 ++++
 src/osc/oscPack/ip/win32/NetworkingUtils.cpp  |   95 +
 src/osc/oscPack/ip/win32/UdpSocket.cpp        |  571 ++++
 .../osc/MessageMappingOscPacketListener.h     |   80 +
 src/osc/oscPack/osc/OscException.h            |   62 +
 src/osc/oscPack/osc/OscHostEndianness.h       |  127 +
 .../oscPack/osc/OscOutboundPacketStream.cpp   |  683 +++++
 src/osc/oscPack/osc/OscOutboundPacketStream.h |  154 +
 src/osc/oscPack/osc/OscPacketListener.h       |   79 +
 .../oscPack/osc/OscPrintReceivedElements.cpp  |  261 ++
 .../oscPack/osc/OscPrintReceivedElements.h    |   54 +
 src/osc/oscPack/osc/OscReceivedElements.cpp   |  801 ++++++
 src/osc/oscPack/osc/OscReceivedElements.h     |  548 ++++
 src/osc/oscPack/osc/OscTypes.cpp              |   52 +
 src/osc/oscPack/osc/OscTypes.h                |  240 ++
 src/tags                                      | 2475 +++++++++++++++++
 src/utils/create_marker.cpp                   |   96 +
 waf                                           |  173 ++
 wscript                                       |  138 +
 128 files changed, 27083 insertions(+), 88 deletions(-)
 create mode 100755 .gitattributes
 create mode 100644 .gitignore
 create mode 100644 COPYING
 create mode 100644 data/Info.plist
 create mode 100644 data/build_linuxapp.sh
 create mode 100755 data/build_macapp.sh
 create mode 100644 data/revil.desktop
 create mode 100644 data/revil.icns
 create mode 100644 data/revil.png
 create mode 100644 data/revil.svg
 create mode 100644 data/revil.xml
 create mode 100644 src/Reveal.cpp
 create mode 100644 src/Reveal.hpp
 create mode 100644 src/audio/AudioManager.hpp
 create mode 100644 src/geoms/BoxGeometry.cpp
 create mode 100644 src/geoms/BoxGeometry.hpp
 create mode 100644 src/geoms/CamGeometry.cpp
 create mode 100644 src/geoms/CamGeometry.hpp
 create mode 100644 src/geoms/ConeGeometry.cpp
 create mode 100644 src/geoms/ConeGeometry.hpp
 create mode 100644 src/geoms/FrameGeometry.cpp
 create mode 100644 src/geoms/FrameGeometry.hpp
 create mode 100644 src/geoms/Geometry.cpp
 create mode 100644 src/geoms/Geometry.hpp
 create mode 100644 src/geoms/QuadGeometry.cpp
 create mode 100644 src/geoms/QuadGeometry.hpp
 create mode 100644 src/geoms/SphereGeometry.cpp
 create mode 100644 src/geoms/SphereGeometry.hpp
 create mode 100644 src/geoms/TubeGeometry.cpp
 create mode 100644 src/geoms/TubeGeometry.hpp
 create mode 100644 src/gui/AttributeWidget.cpp
 create mode 100644 src/gui/AttributeWidget.hpp
 create mode 100644 src/gui/GuiListener.cpp
 create mode 100644 src/gui/GuiListener.hpp
 create mode 100644 src/gui/ListenerWidget.cpp
 create mode 100644 src/gui/ListenerWidget.hpp
 create mode 100755 src/gui/MainWindow.cpp
 create mode 100755 src/gui/MainWindow.hpp
 create mode 100644 src/gui/ModuleWidget.cpp
 create mode 100644 src/gui/ModuleWidget.hpp
 create mode 100644 src/modules/Attribute.cpp
 create mode 100644 src/modules/Attribute.hpp
 create mode 100644 src/modules/ContextHandler.hpp
 create mode 100644 src/modules/DepthCamModule.cpp
 create mode 100644 src/modules/DepthCamModule.hpp
 create mode 100644 src/modules/DepthGroupModule.cpp
 create mode 100644 src/modules/DepthGroupModule.hpp
 create mode 100644 src/modules/DepthMeshModule.cpp
 create mode 100644 src/modules/DepthMeshModule.hpp
 create mode 100644 src/modules/DepthModule.cpp
 create mode 100644 src/modules/DepthModule.hpp
 create mode 100644 src/modules/DepthShapeModule.cpp
 create mode 100644 src/modules/DepthShapeModule.hpp
 create mode 100644 src/modules/GeomModule.cpp
 create mode 100644 src/modules/GeomModule.hpp
 create mode 100644 src/modules/GroupModule.cpp
 create mode 100644 src/modules/GroupModule.hpp
 create mode 100644 src/modules/Listener.cpp
 create mode 100644 src/modules/Listener.hpp
 create mode 100644 src/modules/ModelModule.cpp
 create mode 100644 src/modules/ModelModule.hpp
 create mode 100644 src/modules/Module.cpp
 create mode 100644 src/modules/Module.hpp
 create mode 100644 src/modules/OutputManagerModule.cpp
 create mode 100644 src/modules/OutputManagerModule.hpp
 create mode 100644 src/modules/OutputOscModule.cpp
 create mode 100644 src/modules/OutputOscModule.hpp
 create mode 100644 src/modules/OutputPdModule.cpp
 create mode 100644 src/modules/OutputPdModule.hpp
 create mode 100644 src/modules/PreviewModule.cpp
 create mode 100644 src/modules/PreviewModule.hpp
 create mode 100644 src/modules/ProjectorModule.cpp
 create mode 100644 src/modules/ProjectorModule.hpp
 create mode 100644 src/modules/RevealedArrowModule.cpp
 create mode 100644 src/modules/RevealedArrowModule.hpp
 create mode 100644 src/modules/RevealedCutModule.cpp
 create mode 100644 src/modules/RevealedCutModule.hpp
 create mode 100644 src/modules/RevealedGridModule.cpp
 create mode 100644 src/modules/RevealedGridModule.hpp
 create mode 100644 src/modules/RevealedModelModule.cpp
 create mode 100644 src/modules/RevealedModelModule.hpp
 create mode 100644 src/modules/RevealedModule.cpp
 create mode 100644 src/modules/RevealedModule.hpp
 create mode 100644 src/modules/RevealedPathModule.cpp
 create mode 100644 src/modules/RevealedPathModule.hpp
 create mode 100644 src/modules/RevealedShapeModule.cpp
 create mode 100644 src/modules/RevealedShapeModule.hpp
 create mode 100644 src/modules/RevealedTextModule.cpp
 create mode 100644 src/modules/RevealedTextModule.hpp
 create mode 100644 src/modules/RootSceneGroupModule.cpp
 create mode 100644 src/modules/RootSceneGroupModule.hpp
 create mode 100644 src/modules/SceneGroupModule.cpp
 create mode 100644 src/modules/SceneGroupModule.hpp
 create mode 100644 src/modules/ShapeModule.cpp
 create mode 100644 src/modules/ShapeModule.hpp
 create mode 100644 src/modules/SpaceModule.cpp
 create mode 100644 src/modules/SpaceModule.hpp
 create mode 100644 src/osc/OscListener.cpp
 create mode 100644 src/osc/OscListener.hpp
 create mode 100644 src/osc/OscManager.cpp
 create mode 100644 src/osc/OscManager.hpp
 create mode 100644 src/osc/oscPack/ip/IpEndpointName.cpp
 create mode 100644 src/osc/oscPack/ip/IpEndpointName.h
 create mode 100644 src/osc/oscPack/ip/NetworkingUtils.h
 create mode 100644 src/osc/oscPack/ip/PacketListener.h
 create mode 100644 src/osc/oscPack/ip/TimerListener.h
 create mode 100644 src/osc/oscPack/ip/UdpSocket.h
 create mode 100644 src/osc/oscPack/ip/posix/NetworkingUtils.cpp
 create mode 100644 src/osc/oscPack/ip/posix/UdpSocket.cpp
 create mode 100644 src/osc/oscPack/ip/win32/NetworkingUtils.cpp
 create mode 100644 src/osc/oscPack/ip/win32/UdpSocket.cpp
 create mode 100644 src/osc/oscPack/osc/MessageMappingOscPacketListener.h
 create mode 100644 src/osc/oscPack/osc/OscException.h
 create mode 100644 src/osc/oscPack/osc/OscHostEndianness.h
 create mode 100644 src/osc/oscPack/osc/OscOutboundPacketStream.cpp
 create mode 100644 src/osc/oscPack/osc/OscOutboundPacketStream.h
 create mode 100644 src/osc/oscPack/osc/OscPacketListener.h
 create mode 100644 src/osc/oscPack/osc/OscPrintReceivedElements.cpp
 create mode 100644 src/osc/oscPack/osc/OscPrintReceivedElements.h
 create mode 100644 src/osc/oscPack/osc/OscReceivedElements.cpp
 create mode 100644 src/osc/oscPack/osc/OscReceivedElements.h
 create mode 100644 src/osc/oscPack/osc/OscTypes.cpp
 create mode 100644 src/osc/oscPack/osc/OscTypes.h
 create mode 100644 src/tags
 create mode 100644 src/utils/create_marker.cpp
 create mode 100755 waf
 create mode 100755 wscript

diff --git a/.gitattributes b/.gitattributes
new file mode 100755
index 0000000..77510b2
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.pd binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..159d8d8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+build
+.w*
+.idea
+.lock-waf_linux2_build
+cmake-build-debug
+.*
+node_modules
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/README.md b/README.md
index 171fa81..502a1f7 100644
--- a/README.md
+++ b/README.md
@@ -1,92 +1,93 @@
-# Rivill
-
-
-
-## Getting started
-
-To make it easy for you to get started with GitLab, here's a list of recommended next steps.
-
-Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
-
-## Add your files
-
-- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
-- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
-
-```
-cd existing_repo
-git remote add origin https://gitlab.univ-lille.fr/mint/rivill.git
-git branch -M main
-git push -uf origin main
-```
-
-## Integrate with your tools
-
-- [ ] [Set up project integrations](https://gitlab.univ-lille.fr/mint/rivill/-/settings/integrations)
-
-## Collaborate with your team
-
-- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
-- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
-- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
-- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
-- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
-
-## Test and Deploy
-
-Use the built-in continuous integration in GitLab.
-
-- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
-- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
-- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
-- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
-- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
-
-***
-
-# Editing this README
-
-When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
-
-## Suggestions for a good README
-Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
-
-## Name
-Choose a self-explaining name for your project.
+# Revil
 
 ## Description
-Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
-
-## Badges
-On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
-
-## Visuals
-Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
-
-## Installation
-Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
-
-## Usage
-Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
-
-## Support
-Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
-
-## Roadmap
-If you have ideas for releases in the future, it is a good idea to list them in the README.
-
-## Contributing
-State if you are open to contributions and what your requirements are for accepting them.
-
-For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
-
-You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
-
-## Authors and acknowledgment
-Show your appreciation to those who have contributed to the project.
+Revil is an application for building and manipulating 3D SceneGraphs for 
+Mixed-Reality Artistic Performances and Digital Mediation. 
+It is based on OpenGL (glfw, glm), OpenNI2 
+and is entirely controllable via OpenSoundControl messages. It relies on the
+approach of revealing virtual content in the physical space by intersecting 
+it with performers and spectator's bodies and props. This content can be 
+used for visualisation, e.g. to augment digital performances or museum
+cabinets, or for interaction, e.g. controlling sound with 3D widgets.
+
+For video examples of what Revil can do, watch https://vimeo.com/album/4703717
+
+Revil has been used in the following projects:
+* http://ixmi.hitmuri.net
+* https://www.cristal.univ-lille.fr/mint/revealable-volume-displays.html
+* https://www.cristal.univ-lille.fr/mint/revealed-interfaces.html
+* https://terrev.univ-lille.fr/
+
+## Help 
+A tutorial describing the main components of Revil is available 
+in [the doc folder](doc/tutorial.md).
+Several examples are also provided.
+
+## Software requirements:
+* OpenGL >= 4.3 (or >=3 but there will be no revealing output)
+
+## Hardware Requirements: 
+* Depth Camera (one handled by OpenNI2)
+* Projector 
+
+## Compiling / Installing on GNU/Linux
+* Install the following packages :
+	* glm 
+	* glfw >= 3.3
+	* glew
+	* FLTK (http://fltk.org)  >= 1.3.X
+	* OpenNI2 (http://structure.io/openni)
+	* OpenCV >=3 (http://opencv.org/) 
+		with OpenCV Contrib aruco
+	* xml++2
+	* assimp
+* ./waf configure
+* ./waf 
+* sudo ./waf install
+
+
+## Compiling on Mac OSX
+* Install command-line tools
+* Install macports https://www.macports.org/install.php
+* Open a terminal
+* Install the following ports (sudo port install "port_name")
+	* glfw
+	* glm
+	* glew
+	* opencv3 +contrib
+	* fltk
+	* assimp
+	* libusb
+* Install OpenNI2
+	* Download https://github.com/occipital/OpenNI2/archive/refs/heads/master.zip
+	* Compile and install it :
+		* make
+		* make install
+* Clone and compile the revil source code
+	* git clone https://gitlab.cristal.univ-lille.fr/fberthau/revil.git
+	* cd revil
+	* ./waf configure
+	* ./waf 
+* Start revil
+	* ./build/revil
+* To create a .app 
+	* Install https://github.com/auriamg/macdylibbundler
+	* In the revil/build folder, type : 
+		* dylibbundler -od -b -x ./revil.app/Contents/MacOS/revil -d ./revil.app/Contents/libs/ 
+
+
+## Uses
+* OscPack (http://www.rossbencina.com/code/oscpack)
+* Calibration code from https://github.com/Kj1/ofxProjectorKinectCalibration
+* 1€ filter by Casiez et al. http://cristal.univ-lille.fr/~casiez/1euro/
+* Signed distance functions from https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
+
+## Authors:
+* Florent Berthaut, Assistant Professor, Université de Lille, CRIStAL/MINT
+        florent_DOT_berthaut_AT_univ-lille_DOT_fr
+* Alan Menit alanmenit_AT_gmail_DOT_com
+* Boris Legal
+* Anthony Beuchey
+* Cagan Arslan
 
-## License
-For open source projects, say how it is licensed.
 
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
diff --git a/data/Info.plist b/data/Info.plist
new file mode 100644
index 0000000..e9bc04e
--- /dev/null
+++ b/data/Info.plist
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>CFBundleDevelopmentRegion</key>
+    <string>English</string>
+    <key>CFBundleExecutable</key>
+    <string>revil</string>
+    <key>CFBundleIconFile</key>
+    <string>revil.icns</string>
+    <key>CFBundleIdentifier</key>
+    <string>net.hitmuri.www</string>
+    <key>CFBundleInfoDictionaryVersion</key>
+    <string>6.0</string>
+    <key>CFBundleName</key>
+    <string>Revil</string>
+    <key>CFBundlePackageType</key>
+    <string>APPL</string>
+    <key>CFBundleShortVersionString</key>
+    <string>0.0.1</string>
+    <key>LSMinimumSystemVersion</key>
+    <string>10.4</string>
+    <key>CFBundleVersion</key>
+    <string>1</string>
+</dict>
+</plist>
+
diff --git a/data/build_linuxapp.sh b/data/build_linuxapp.sh
new file mode 100644
index 0000000..0269e4a
--- /dev/null
+++ b/data/build_linuxapp.sh
@@ -0,0 +1,8 @@
+#install all dependencies through synaptic
+sudo apt-get install python3 libfltk1.3-dev libxml2++-dev 
+
+#compile revil
+./waf configure
+./waf
+
+#create app
diff --git a/data/build_macapp.sh b/data/build_macapp.sh
new file mode 100755
index 0000000..e0aa90d
--- /dev/null
+++ b/data/build_macapp.sh
@@ -0,0 +1,11 @@
+#install all dependencies through macports
+
+#compile revil
+./waf configure
+./waf
+
+#create app
+cd build
+dylibbundler -od -b -x ./revil.app/Contents/MacOS/revil -d ./revil.app/Contents/libs/ 
+cp -R /opt/local/lib/OpenNI2 revil.app/Contents/libs/
+
diff --git a/data/revil.desktop b/data/revil.desktop
new file mode 100644
index 0000000..520ef80
--- /dev/null
+++ b/data/revil.desktop
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Encoding=UTF-8
+Version=1.0
+Name=Revil
+Comment=3D Revealed Interfaces 
+Exec=/usr/local/bin/revil
+Icon=revil
+Terminal=false
+Type=Application
+Categories=AudioVideo;
+Name[en_US]=revil.desktop
+GenericName[en_US]=3D Revealed Interfaces 
+Comment[en_US]=3D Revealed Interfaces 
diff --git a/data/revil.icns b/data/revil.icns
new file mode 100644
index 0000000000000000000000000000000000000000..a75da2a2869f74f7ca265973366d9e165cf6df81
GIT binary patch
literal 40371
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
a|7>%EuLuq`G!^Eb@@8j?Kgtw4Ui$z!_a0FI

literal 0
HcmV?d00001

diff --git a/data/revil.png b/data/revil.png
new file mode 100644
index 0000000000000000000000000000000000000000..4228f2870ec49460c67bf4363d74c6f9afb8bb70
GIT binary patch
literal 19943
zcmeAS@N?(olHy`uVBq!ia0y~yU@Bx_U`*j)V_;zLugmRaU|?V=cJd72;Nak>;YjIV
zU|`@Z@Q5sCU=Z#AVaCN>oEi)a43Z_T5hcO-X(i=}MX3zs<>h*rdD+Fui3O>8`9<lo
z-`PkpFeos1x;TbZ%z1OSvL@u~-v1xJKc92*keo^(^P8mA+xFgl`*v%n0psgSRr%Ws
z^4H#BnpxZwwd&8Ew`Q^Huim~SCO%^(!?e6fdfTeja?RAtTAO<@>$`7s_d#BcL|-H0
z=bwKoI|_Q9FfyKRZ2bQD<B9EFlPvWG4ymXAtYdX?VR$#szTPR+_v}}JpBxPzneEpw
zlsPQnUKJZ~mvN$OKy8?-ocIHM%ZcviI*$L(oZ;sZGVzF2L&uw?;yNoXd!*R9_{lx>
zwqbryC%E%8>%aUkn|~p8zdJf!EVVcy7`nrHy3Wj)+n0;^8@4}xsaninrm^AEzL%Hl
zMY@kR+3eL56qIdnmI-9_j<0y=ayI21(}#0Td-gHamo#Wg33pm^ef;I(GPTE9Ca~4(
zc#`1TH+z^5%w)Bnae{wUjCs|qv*zWZe<EC5L=SD`Q&5t=b@QjGNOA)+!`1KUn{Kw7
zRovrrwUiSKWPLExViDJrPk;Lzzh<+w*SWdgvs9O>Kl9**i%V)N$Z*e}|8_6@rOdGI
z=tt2X$=jAc&rM$!yZiW~A1*FWo2CbMYMpSqUvC?-pLsDO9|KE;?~-lbxWkUCD`|<_
z2)l<UzRSwATy(3jj`KmqYcYnI3e&AK->nMmk8T$boT@diQ+XA`%LtvI#}@aUE!Zp=
zRtR1HJEN3EFi`WcfO`n1mGyMZ3mJ0@6&TNTA5Hor<>F%E^@qtT<k_Wt{{>m?vhEgg
z@b=C&-+$4nsbfV*VTZC-vh2L?e4(+KcMWIEIdOZ9bVrAmXuHKCqpgJx56xuy!{E?c
zdU}D(^U!OYE-p*EoMi$fs}f#bDs)u&RLkHVxn1U1#cKwoML|au`&OLMQ21T;K5nUl
zX3VNJoA?xzv_fSbb)53K_1RAIKz(F6k8rz%(xSje0`4JhRyOZz8SHZJ8pcSm++GW}
zbz)X-?P7-PK(G3BuJbndfs9!C`RKe3wyEF#R;~EQaDe6Yw21-@&N6}*H9)Q}e96k4
zCCFmm_DXwgwA-oBzpG1`1p`-ttT-ehuy&Q#suP;mbQf>1wM{-Yf2}gqb3)U)-0ayO
z9KI&IxFlXjjC&18A{3Mm-PGS!{$F~)^qTBqRi*Ed<^qCKjplVKYdLD3pS|{gF2j*s
zsaJ}2?p`b0(cu;O@*k^1$U>`{{}q9MEgRTgPc!@x9IW(F>NSVbqM&2Og)XWohh4>e
zg|Au%-eQ(<`MUcWuZzplzVAl_r*?d4V%_@U_3wpD>Ji&}LeG^#!a(-?5y7bqrDxCP
z1%z%5YrMQB`qKmP;_!8Unn6*#5){QuQm<a^(>lPu*7}oUqckYwPBFGyESlh5eeb!*
zj}@iv^Kwd!B;&kPl}<796}l*1dsx{m`lF@PT~1Z%`kI#;`xKP4*kvAdIBC88{a*9|
z+v`4?SE1LRE)7vyWb;tKUBpScW`E%C=?@FmMt@q7d#+1#?lnPB!gZDjJdxAkcK^YO
zf1otsEth(vbp3XaY3ecReHt!7-C}b&CRQ_CiQN8V@~V56wj>?3Ut`_Taf<W&5y93Y
z$F5xqKU^Bj(6=e?<Yu`Qb@xCC@J>O8GFM~Yv}x0yHa(DII3BhA$=nm4EOT@HBhm!~
zr%K29sTys&_q|{Es!7B2=<Om7;qiLqYe7L_`DmtvlC!k9-kg_AnGEYU<Y{tDJU{p9
zwQYB;nmbm=eDsl-II)*o{M?z)(7z(9)^EwvWMTbxD>}G%aw)rD;7*~}42!(BC`#F$
z68x#zFnLWhm)qC7z9*l|y(a16^0X`cQAbx!LWB3h9(D`Hx*I1L`#M%EsPLBw6kNLa
zq9k+rgShOwK@Qc;3K3bdjxHhZERG0@o;;TE#Z>E)@sy8}77PIs&lh?MDlIw$iZK>x
zoA<ev6MGr@Hs@(>XkX3{zpYO}X%&miqYf^etGBF<Gg>j2L~Iv{SkH3M-LLPs@ij#k
zm#LtVjB#nre;byA{tP~w@-!_b`kQXs`u7~jgFyuy%32fn?*G>axz4m=Q=Vp1e9qff
zk5WUF7AZXvaG#RS<#FosK8;nU110N^RmEIw{e0_oG1%Ca*GB}OUYzSa?aGqsDj|kv
z(c4A3ndZ-#>+|p8uI7#vmkK(RPfe~C)3q|YbosM0!~d+iK`#7xw>Kuw1O>b5qixYH
zl@s!EZ6li>m@!;l8{L(mU$k?($=ax|>8}Np7I}qmet#_>8q)sWJX;{gC6%{8U}CrB
z0YSl=4+Y#!ytq7WeO@PW^*xhB{@vh|*HVu^E&&_+*tXDR@r1Yy3(RCYw=i0q-*xoB
z{i>{N+t(aQi@c6kKk9JHNX~w}y4djo--F(3x@=XUPh^W9eQaOr+|i*WtG`^R*Fj6_
zZ-0!yAEBw12OM4X9y7SRi1676yPNR5jL;D(DXWWX&<<EwpC__ovF5}d<&0N$wRUt=
z_{&^O1V!nso0Y2>-fze=RNiDc`E+dyvy5P1#fKuTivpL{u1#NgVtwFAW|<4>jt1}7
zY}@u06p&w-=5;DtwScnf-zl2&uPOYn(E2l5R&?hQ&50Ekb~Sf&#H~?!|5j1zRMma^
zbG%Jk1!kt+P4fFXZCOfDV=0@U;NB3|`H2cv5$*5IcdzO%XkccrxnZ0av$~W;P*7It
z{1HLM9mOXno!n|`YtAqu|E>_%D*tSiqEB-~wXN0$cXYhCU~wey=<N%)s=5~c@?Ej-
z(k@jMqsCWrcAk7v3v!={h20GY(d^0Z!{3Jd<!O4r#jvi_KSHBGkljLQ(TB$~EmnC*
zFS=-Mp|qM|&(&S3J}eOzXL!UU+;wzuX+LgU7!r7iTkJ|!=+)&6F?|32)f--|p8xvY
zz8hA}9UX1$>5o<<<z(dAx;8EFZMYt>y`}HO<B2}c?x(Gd`#YzUOHh!P|GZ1U&1z6Z
z@w@E(zbz~WQy=WjZ{H+)^Npp<gN_a_?(;_iBfTr{?Pva>)es)By(J`Gq3GJ33Y%P6
zCl?px!^VXn(;x+_R6}|6_Li9)H9eq6$$TW>p8B+LsrT`>w>Llc3fwE?u(s5HM(3-o
zy`4wAUh^p_Ny+jRhKMC?oMF6s^Jiz<-R1Rx4UgAUdmZ?0es0Fc!q*&1N>aA>gxytr
z89ldd+2bzrd^5wnl)J%7bu(YS%(N<gd&?FaepND$R;b+Fnc{hN$GmypH497|%p<-}
znPAU)_3H9-dp{n_1*<ZXd9-55n(VxF>*gD!n!220Gq}2I`H`H93KhraY}=;3#<`;-
z<4uLX%+x7uD}(nhS@k@!e9D5kOnY{Bf_!uH!AuJ+$;|WB{Y>_3_4oTi)B<Y1-$^Oj
zTgo9Q_>}*@(UM6M;`aP_I_tD8Pn?tNN{7(%^C$b%9k*)f==gMcBcFoR9N&HMtvTOr
zKVUFVT2-Y9irh~}6#JakM}MsnwLH3O@sp04EI*^4p|5$Al(cx_{FVkht}R%sQj{EQ
z^DhuADD&^A$HJ+f_FQNDA=#jLO;`1qbZ_SoCdMluTe#Y%2Ww8bv@f3jfmuO=v>;=h
z#^vSP3mTM_wCZhy-4{-d+ps`vqDR;FgS|IwZMSayUw7`))4iae38?_dFKWn8xpa&%
zuO-A<W%5scz5*AQsm;zZtzNgj+w%*)J7K`I=+|eT{P*=H>mn~F-*s|vIeJ*J&q?`h
zCHI1=-ct9KoGxMWcb2`C14XTt9$%pdm*#ov;Kr%fWS5>0{JFT4Sx`_^zTLuTdY_v=
z`v+!*tH(4|SDr8Ymvq;`#pUR6#Xg^<i!as(Pn2ht$iEx3XiN3&ZMmQdEu==~(Fvbb
zTfg>deX3_ri`+hCLoB$E6m)R`%em}Y`ZQjEMVdh-@ovzi5MxmLC#Bh0M)WSIDqH>d
z4)cP0yOuub?Ah$6prj-%^JvA2OS-!MCvi9RGW2cC(-eMe_Oos(C^v)Lr!}i2`}N6J
z7MTSNr`2!HJiG6bRZ~YtSHH82sOze&rG0FUQhQovl?!$5Iku}2DiP!EeR?NHlQo0S
zmOM@GRqwa>DJU&^^jN^1b!wN}|7e-#><n3Jqfbp`dcP?TCUf~=<#fjs-iD4+@0r!k
zr#{D}%R0Ka96h=}M)SSd&$_FASEU&%uIY+8Uu7@Y2r7m|`y<!`DtFdjT;wTveQ#*v
z=C#pUXY2xP7aGp2xdci9UCq;jHS?`%{{OJM{#TXVLilmWlVETN+SmxYS8iOm^{a?F
zM;>#*l2UKh;KDh@QsL|NoCfLS>Q8@^apuy+jPA?(*<{!)q8B+%xFOIhmkP?_t;dZE
zO|r`MB7=f==ie_C_&KALTh^g8c-i*vUyQG>yPG`M$;GAhuwtK^s%-DMfQj#!e}uml
ztI}k=_WkRZJ^jrxf`LCD3Aigy>vQuDpBR1c^zy{={T+MO8_M0!0-68wc=e-<8zK|7
zypLa{^!gy<I*~c6R_(ua<I<<J*8)mPr|jo-E>7I}zKMHT+UA>PtoPFIIw@b{eqd}=
z`|E4(#)xZHZ5<7}qoVpcT$J2*@4PedmBsIvgnYHxcPES944i!WZEnowWyg0-Jk;+j
zBYW+@C&l}WAB<j$Nlk8dee&p7#h<#@0*i{atlPPBSK_HD%2x}QIe*m<v}AKE*uv!Q
z_#}eCo$<#1^Ro``iD6hEt+bo*P3x;XhPzyEN*ijmF0o#f)w=YQA$HX*(G_Jo*WDIf
zQI=Y?a~*s7xjTa0N1G1)TXRyV-9qZhfv1;GFZ@->5PHpaia6H;_QqG~&($XH-`J<9
z#hQ74eR<OY#TW9&maRT9aZ%NpZ~V!}dG^S%F1WYt%Y<EwB`ZCquP9@@!8P%@$PKQ9
z)r)tTs(<nk-4NQa_HpA{_2Z8vAE!yF@fDVMeAkP)F`@KszQYrp*J4^6qF1f26o%!!
zeYGn)uDbf1RmTd6OB*9t&f7)z-@8}UafR7Jt6&Zr!&jy&&RZD|Occ2J|NU2nn9DC7
z-DZ3c$-`6iLjJ=xmIIpwDx;boWU6z_n|kZkxnr~QZspF7x@mFbqW6-h=;sO?`x^gU
z{ulDkDzubWCjIN2ia&<0B^Eu5x_;-4na^CStAaCUolRSAHSvVtiKnlc{~cT{_c#6A
zE7lB)1P$v$7Q64fVg6v!uw0}fEM&gWgP9IbBv~An3wPQ~J(;rY&5f<ECF?fNsF!*4
zqVn~u*{feK_xo!TqR%=%W}OSy1Mx*w)2+_MM(^Hb_OV+}^wz=V85ZY47?-gr1*>u_
z>pBs_y38qM)rxQbe{<(g?){wkqljT1;|G<7<%*jkL+6(@sEby3H7(dIexoQX`gYml
zbCV7!_AxMI-naJ*-Ou_!_nNMV(5l-ZDSMSa1$Wqdx%2Jq{+ZYB-AkYA`mkX4`~LN1
zb2{_l@4Fl?T;`Ob<f7(O$`tbYNTHe{hniE$qAnjc1J+f-j6N&|tTIPlT&Q9wS@i$R
zy~%wiF0a}Z*^th3{N@_R4`1vis-N#Y{ynO_jj`RrNlWUh;wGL06|cp(w%Rf5Z$076
zWuvsJ-&?@O>}2Wu2fY^_7X4r3I(f@7wM*Bpn@5J;)tabjDagJqTHR5>@qeUlW7ga*
z3qAwa&{)x#Iu4>PYOAtL8#<Y;FwSWC_b^-OSNl562RExWUG4psn9tpyD{!;kEr0VW
zyQ#son}qZp7Imyn$h^OvKSY>m&-GocUQv7p(ir|Td=U9|pW|-5+IvgJZOjed>?PT+
zmzJj)&3wLpLzt_QaFJsGFN45LjRQ*@N+&T)zEapHa8>!@{vBTo8T!}^<dhB`$bQCh
zqtfAY9>ZVerCDJvWpC@-nRY8|s-L^3=bQe`3-u9K=PCt#(Er9|am$|JtGxJ%wi7Ml
zb`Hlm1F8=!_qoD6k4HSAYoCD)r^_n_21f%qCDRx3n|`QR2JYASrT;K*TBC8b)+W|f
zbG1G#;kLQDJ^%i*pnLNsILEZ!66l@xuwxCI!Cg@M@k9XsulC)`+2$Rpy~8+<%VnFz
zf#97vW!=?x3jgywPI@WxNbAhoefD)tuf8(qG5r58EGWq9&UV0f(XL3>J<D7keZS_&
z@IG^e2B?D|+|bS#!vU%wT@Ht`CbV_UVS2!Q&G7d}{ZCvI`i?5Sc(W&@@jTOtZSNG7
zl(aG(3$lWvZ=YXdT%oq^Om2@`eB-%uQ<$zdG0O-FUc6y>ZtFEphV~tsrggdfopT~z
z#NsT-y(@a=>{67nJ#3|vB<t|A{QIM$?qN@h3K{+<f@<E7K9?ix8}4m6`02rv`j^+P
zZ8qTuTUhU_tE8l))w9pT%sTnntE=ZDSwHy1%-m7^?+@q1S+mw>3An6{?&#>yawy%l
z>QxQH=`~Ch{xOms+qcb&361`}p##)bP|^|#jm@a6;VV@2Vf3uNcT|eSp1Gi@lwVLV
zP*w23SJ`gy*>7u(oL;G#_4rV$@#Tpp%o*n7f!(xm)6GbReaVFx^E$O1UuJx1-s$lq
z5NxKAYG3iLs~aoT*0tDdD0#VKo^AEMRjc-uatjIyGBTt^%g*rbnbL7(k*oTl(tOqr
zZm-3Zl$5ICHk2OkEBt)x_V2FRgg8H4M%j7h^6PeUf?A~=hmKh$U0Nb3#{TT-6#;PT
z)pmDTEcb)tYq~BjE+rZ39?P&l_?RR=-8sf1HzT(;_x!uNZv`sXg6-t>YkaKJclz{7
z#VMcm)R#9sU}OLr>g3npDR%tn%pC%e*YCXXTfO=>Q-k(_cE65}4zDIA$?nHR9o(H;
z-d}hAdYfwwI3ipQA6H!0RQlszbja7=3~}Iqa8Xv7wADiAeW&p?!CpO)tLz6D`#L&S
zgye3u&}g?%=JIHNf7~TSv_a~%oRX4~)KY~X%|{a}Ew4IM9c;Q)5_(lD@b3h$GkZ_o
z`<-^~PEKKh9b;t5_h0`EEw9RJelP<EkJRS&*+QM$qhw~JKkCX@{C>aP>MHAo>5<z7
zK&gsz!X_)T_nq34LQJas*8OK>1E<zhr{)J{tCNd6w40{9pU*z=HiOTWJVhm?MSCir
z-J5A#pI2JISI9aIJYY7PVbvN?YSE}?$>=|t)Ohuy<q^?<Tc6jpyt;mX-J_$U<CHJM
zL}^{-9|_KkN0JQFuT9g955L+C*0h4b<(Bm0kM@yj1s$h1`|gY1`uU{#b%!T5V5e(!
z+*6pn_n1|abBx^D?7VgF!v5~-*mE3|>^r!eU6YE#*H+!x)$ANIFXz+WRe4vVSv7t!
zEI**``c?g?onG%;hV=mxzd7$&&AO^z%r+zC9@oUF*94!sxQJy7<ZOB;(Z!T6aYOGz
zfSJSBRg2hqCoqI+1<hH`8EVh;;Jd5kwTw<3rh<i~Zk;!GtX=)O>NQ7$b4=Wl<c%KX
z>Cd;bR;)kzQTD<6-jh$9#f~rAc=N)oUFSLZJ|;{)v3r(K=fQuAcvxBG{HpIAXV`OY
z*HWK955H8{=ru&O^DI65Sx@>+EmKMB-|UOKo;`c@YuBztGTx#8O_s0Ky|P~}^S-^e
z>6QIY4?XMjFuQHDey?r1EYpXVR}7=C-+7aj{#=UDF5|9Ks>|1AX`A;fuX`49EMWSx
zzSMoEz=K~G_zU*c+w8v<$Xe~@a&Fevs;|Y@6n__XNH<65JiBuJ>RP4`iLb@9tk*He
zB+3?AoPT@cV=jY#RQZ&~bB*z*3%HwBAJDc4X%zXfn&sfiYyOMndg>+IJsCZ1e?IZ*
z__Mu~d+OSsFEdQ8&G2a}^O$x0-o5GH{;pr8b^b(e>#OU}wr>9(na%@l+tuyWwy&)<
zXY2bsSN!jc$37)|8y)s`_=G0xS<x4qz$KI3#PFE;swb0AP{N)LAF-=#3@gMJ$T>J~
ztkYsGSsoVtzx;8pdERC|%LrG#!tXj!B{@e5#SRp@?d{Ku`kKl#XXbgmMa?1XO4Av4
z9I;B#2)&uJ=X|L>;{pqFsj2hd%`1F-=zl}U;~1{1S+99ctv_a(UB+-DaK-ib>v!JB
z8K!#eU44sTVikisYu{yt1#!RX-(+w$C5Jq*U~pHADLz>yxKr)S_f>5##aCzC+nRNC
zT7*v7+swIh)0sZ7T8KAf-*qi9VBAwJuJ^}j#=C<SH&(6=d+Sws?<~W*ZF!o3+UFzp
z)hsVP5^!l>{Q6b%O5Hm-L@LfO$`v+0(0nbC&CJhWWBkEv322nz?h;RTSEY$FnPh}l
zoMSPNRl4k2x{T>KmjUyE9Zc!(gRbs)Y;oP}*yCvKnl*+iPbl&+uzj=o&Dk)2N$r0X
z-X?#iC;JclX3>l}mLBsxiDCW*KFO|-(ArqznM*;v2rr*}v+2KQl^#i48OM{*RO-g@
zR`@|VmkrYcK~}lKRjcYQmt6MUz4oxz#RCVnr#{FHkk;FkG3)l_%k|&<o~SSsGn`>E
zDCB7mXV@P!aqHD}zt>*Q+qW~DXML#2oy(sYq!(Yjp5nT0bHwXh9TtoIh7*5GD`oG!
z({}CJbt}h$9i>akzFfJsPv=c~cF?~4LaX+bx_3rio#L@2!ky>oIaP19>)*coVLou>
zaP1m~x4oT5_8bcDy>~!JdGF#MSDv#}xVXwOe&7g^pZfCh|2q=hsh{t9C{OP@s&wwz
z+4cM`_ZBJTvlQ%MS}*WGV$YYbep`llOdt3e_6J_|<y!JgZF0M9w1k;xwc5LYH1)~#
zECqR1Qh)tLe@gvYe_l9p_3D>z_X-@?dQH)pGi3i8hQJRw-wIgsIBf)s)-8X|Bzue@
z+)d;_GSi=^Q2EBkHmmwRp8yZg9L^|UKKx}p`@OiNz3=@`Ub&KSW51-FCSPIug&98g
zs_wIj-<f<eZ9i9ofAU1jz`aizmwNC2)|YzvTjX}0v^=Gc)2F<@&vx~D^!6zo)@=I<
zdDgN|)04fvIs3ZmgiU)hE;C=fulb>a*=EtI{*cxGo?QuDT^89MST|R&zdYJpgsFXp
zBTo$fe~(k&<(poGA7Gb1aV_xow>O!L1<j==5@XmKobME{94x)Y*?xI<_I0HWncTY*
z(=8d#xeM5I%{2ah<n+RjQ>VV&US0F*!{74GS8F+53UTdGUsuBWdESmXrP<rdO808L
zdEL3x=KXSpwCM7dJAZvUk7QmGbiVoIcc^vff2Idd5C5GLv_rjb#hefKrY6o1?!V7`
z+)|b`#=HH+hLCi#D_7^H&n=8twb1@>$~u;Jt+!d{v<vbSfIHr8D>I*-a(Dfj!%)38
zdPR|DL8^`z_t*Kim!*92`=Y<op<U_I^Xl|7JMLN~YjAa}ip#s}=;F-%HJ&Z;@(drl
z6^<X`87lZ$BP}z-(x3lcqs-@BI<wR%V`ZHA2EWvdrMB<?GQ_2Wv^*9tcPhShD=+-2
zeq?!o>+hDfKXunm{;f8&OS~&+waVXHP558$yU_KU{1g@)ek@?lb$i!t`_%{X*IKVg
z+N=4t^8KbhiBl&(R<Qle*1gmylOFkamZ|MENoUW>dou+rZ|-XD;Olq3qj4rX|9$bV
z>;0!Awg(*L`fImzX6^4s0e92x3MyGIU9X=fYsj<k|6W&@zZOS&gOZg#a)eC2CL6Lb
zZFyAGy-ZodDaO~=-CcZu>vi7-0fl=z(tKCUFL?i9PkF+R(}&+MeK2sz3%#oE@Kw3*
z)pG6`?k?;PllCV+V7mUCf&Wjb3U^;IZ$o)>I*)7PQ>GZM1=n^Rjfj7+D}HOAg$(05
z%QL?(H$FZhbN#RPV_$RI*fn}eRwna0rJHY_d~!eZ$!?G{&b|EbcYB08Pimgg&mM;C
zHP%iKW+&dSHoki6mm9-#o?nbgv+w47vwyxOrc$5XVo|{Z0dqGgmg~{x0Z)alYOj^%
z)8^R6qmVu~(Sxz(sMVtlA?uGl@V8}m6sV~HwIxN3J3HFcWapK?oe}S9`nux{S4cJM
z4Q-`rripffH}!755uP0Ly>s&8kDF>a6rTRBZ+g`kcKrFa=%v{%xASD9^cdo-%_siw
zzPE^L!Qs!hSbr=iZD(bDH)FELob0=XQ+n5~U4M@CpuFJ;xr<C|GJI6@G>XIoW!+pF
zHrA`_GqEaM`tLi3Ng&ig^p(Ypm9xAn@7XW>wWH&Ys1iThfxpF%J{~_-^F|=x>g`XT
zUPl}=`}Obj=2i0B-f>8CHvKZ(*Yf(y|9jad-TfD86vQ6oD^%UU8>z>!?uY`jOvBv0
zjvqcIeG|C&!Q<5DE3Y1K{kh1vPoBlG$S*qjq#n<%h2Sw0xeZoznsYi|fB2gg7@K}K
zaM`arIp0Dzhp)evBWpBe%k!lo8C%|IY+|1+)ET@+xouLPTl$I<$qcLbzt#or-DWuR
z$tGnN#gr=lISlIq9|%9P=r66fS8nFEc>RVql52nWTRszK*ab?hq0eK!8@=v0Tr}sx
z{E4T`S)KkD^SS69R$!K4$Pieg8OJNw>k=WCQ^5LT{hSl>RyO&bH@1sd-8f*^k-T$#
zXGV_8BG4E>!d$~Cm&4cXkv@>W#=6Vx$@%ZT^ZzNo?pb(ecR^w^!$n7XhbJGGg|7Y=
zb3{c+s&NBP;qR+lAHHsRuA00t;>N8uwNKWsSyp8{-W(b_J;I&Gl|l4sSLLke(ET#s
zdfyqZt2S)lY_4l~CEp$H?4m4s%`x-hnseta==W4AggzB;-xi`D^Zs}68sj#jlZAP#
z0h_+>=bQcNvY*=KYgWk`<$94ukuG{tuaaF%uQ+Q2F6DkLz|P<ubn(USwaRV}@~<(5
ze0(LNaOJea9GU)fmWZ^wfdxwO{J-74Kd!3MV+b(6a(u<(IRQ&#l%!e>_zN3OgkRzo
zn{uSgR*1!Vt#pS==}Tts>3y5uNqEKk`wJZ?d)>!$OLgX%v)2TjD-&K`D&*3!eZ#(L
z-iD1!pPqH~P+Ano@m+v@kI(8==Qj6A@LeypJQ64&vortvynywR<<D+ytzJ;IxYV6d
z_0YbHweQ!(b~DJB_V7=g^SGvV^80YnU7a0ndS9fsb8lccp!K@%@X2RI)<-#i`}j<C
z2+_a)<hS<WJ>FhwLOT~~P2bJqu;RQ_pOagNbM4NG$)Lghy)`WJi(dI%wNmp9fUO0H
zzGiB!KjZqnd*K^42<$9AIY}!0{XI^>t5z20Tz0%;G3SW;!_aZ!2t&omg4Zkj0<LB;
zoN!UvK6hu*(ao->mT`&vQuJ#KzV`dy6yrx91J)m2wsq_7rR$aU?F;-NyM1+id5`He
z#b(Rmqh0C27hgzqwEU9W7x=?3+34qz(jx(7jL#V>ZgSYab^cmfs=g#DI(k;vx|%Hl
zu}3HM9aTCwO?S2IRZcD+p@gn)_6w~U52P?mzHnLiVB`HM?2K`nwD!GHynZN%LE^?<
zjY%hMm>QgAM15YgTQCTQf4$FeCs)>JO2YkpQpaU;u1hU?6!hR!gwD5K1O38<eV<bU
zzZ(81^Iz(w%Hg!P#Y;!5c+2L`s{-qOMGLa<FR$4ztJJyn_V)iJan;p&>l<A^+<9OB
z{>t^MbNAP47~kHcp>k>8|F}?F=2f>{Qlvw+Yi^M3+w5DkGdJ>jt==2;K&?nkp2C0!
zEG;!1tA!-vU&ixjg!s++`(*Na_7AqNCmcM}d0gJR^4@pGGn?~HPM&YFZEI`Q%7u}0
z=e}nyxFivGsPR?3(^vb~%Y7=Xo>sn<VtGAx)~tBbdnK1I|9rJ%QI%{1_xJaW`~K@Z
z`nUIdZ0HgjeeQ(Y2X23R{y#QFy6J%>4^KVg2HADHd3WA1D?iqg+q*I1+Oy>$mR?C6
z!V_m+<86P;Fxl%}bdXlIR*|Wb%@Ib1koC<TJ9!Eh-cRCo`1j30)KcnzP~jZaStk{q
zR{m$%ut;;_kNJCKn-3{9{bNsz`(x1airaa<$N$Nb92q(stgR=0+LOl+&3a?qs@n`X
z;uGI;<%lQz{<pb~Dd&7=j(h3XZI<TucEnaRmE7=3?g*Zna<{-DGQrLBt*G172fCoa
z1jw*(ih=LRC(bJ~wlFIduZcePLfp6Wh}-Lqg-dMS`!M9|K2YovZa6*hLgTUp|K}Zk
z{GGpAe^*cKfqqMd3)kDXJXgG0zb)UoA(tuVdgK4FiEjh$K4ZAu+}L<Q^ya*iPs`pF
z&xw70>~VGX@5`IRg`DT`ZL}=TusC;mt#C)263045fm@1v3|9)*311D8f8<oFFT>#Q
zb=LFqvjkdi3o_@gxB4(;PR9RwO*XTLa92OkJ`S}#1vksZU3M+l<=rrs>rGI?@{Ttx
zulPFNh+W;s@S@CR6XOM4#|!F8)kS@qkDq+{%Vn!{Xz0xj4|9e$T`on>b>in;Pd$?N
z{qIL%Wx?eim(4Ege_9HPAcZfNx31XN6|bO~BVwWZ_V;qLV~@W_Z|7O2DHlKg+a7m@
zJtudinuz>(U3+=?{|md4HC9fWR_>HCt&}~m(Urlc^;O7&*3EUl+3k4#6#o}k@q503
z+z$B*H|sScSWZ0MP~W@kR*snFdFvk$)eL(!sI+D=9Dm6cz<RZly*5XeFV4?Xbk@m?
zQ=jWruX-&zareC28<lM@wYPeuCT<SUpTo((wCC)u#uou0ruE+)MH?8nCVrTIQmRE+
z=vVK%hZYO}**b(YsWHs>^=I}8lNI}fRvE{CdHgrOd2PEU!#xG1=~^51?OXRwKJ)zV
zJI7kN+yBZqc=8l-{kgj<5mZVCEmq3k_)bCU$j!w2R-S#fWwH(R5#>FHj9<Loebg#R
zBlCQ<a6|DL>y8&2(lkDF#;AO{KIM6>ZSBKWclme1ps>4YA7RdudS_qla)uQklUkn0
zq;JV?7IjV5nHKs$`<kq>s?zDh`!4S7ieZ&0ij7j@S}w)lZ8G_1u)E2wf))Hat%`Zy
zRgPDluu9U<`c(ItZPDQ$4p|o$39nUdoAmZ&Wb40F4zHu{I$qyPku{vcJFlE6#6IJ$
zqsw9=SC_D*Ht(yq|Ni&Gxz^!Dy9HyN&@)?w<c%|!AJkrxb!mTisC4~?K8aH^v#-Ak
zJihbbuH+pqDwUvhMUmw^M;X^S{Cv~l7_!pNz|pk!{h?M~_WjCVoaZp*UgLG1dG}@|
zUxVZ|S(n2F|2*<$Y<<9BzJO((8~cQlObhS5sC)4LYt3surBmJYXWf*_@7UJ=YhkW8
zc;nq;b76+Zon%=<5!Pu@=2Mu|In11w+}(9}7SnOYirp6<t}b3zE!oiB+gBga`|-!M
zDeu>}y>h*#>l`>S`h3Un|Cx6Ur{t&<t(<a5YPO3>%>Ss+=xXkU=lK&kJ_}rb&34fJ
z@SeYJr@r6kyQ=oOFX+MyAG?lEH<gR8SS`B9-+5yDStgf7<@#}dT8+ckR9sv0(BO{3
zk0QS%q7VQ6S|atS_uc#09UBz6_oO6hD`{2Azxc4{XR%P{R)-4x<ys;3X1mwEy?#xx
zInY6c!>QJ?^@YH(a8}2R^G6sDyh-`=Uh0u;JnN3^Jfok|ulp9JfcmWMdjw~7c+F;r
z_XMr)Qkdf$!>2UeM0IlE>j?}0m`MHI&^0INuA@oPD)F`7|7u>7bmsc_X#Y-u?TiQJ
zdQbBan-~z^r?$v&CI6<I{Y(#~A6c<ltk#tKzpL~_fSF#5MX;;WT@RBM&2_I@uL(NO
z6z;dzIZ*YwubK11>YX1eZtY6eFx|UXoN2}8cM6LR30~zEnXrMU@b<!AJAM4mclLH3
zVS7De;hOBcvf_y+qQ2xWbqrahCz*41p}@{_Ru2*!Pn<twyP@QzMd02eyP7+=-t8#y
zK5ebjzQc~OZqcglZyjfHywvPVK}`dm>b9i|*S%w7*u2)d<JgN6A6MyK6LgmR(e^I!
zbszJe-01M@{A-lkHszn6C&u6&SuPMLXmM^%lI`EGJPpSgY}AzM`I;U)ua<p&u=w%E
zpa}j~m73>wM>QV3ChPK3;Xvx_ntIn6;+Mr9RI%<$zRSp<^=WG5+qagl`woJJ#pbS>
z9$hXFcyW)d(t#P@LwG>V@zn?P1YZg-kXEwgyCCbLRG+`+<+8g!S8Sc~Y0qlLnv1)d
zHTwHr^EG{DT(gZ&@=URH*_P|quht44(C!JICu^Q~Na}H$;@hCV2EVQ=sw_J7;gm<R
z(nr<TT?WApm*$o0{@T7?QA_)gMfkC#jnPRPBNFZwX@KToUuJwct(CM}cKQk4_YvE2
z=4T!jNZL4K@!YxLQRM=GfwHpG*rlCb{&VeCTUz_S`T>LcQ?IW_E^o{E*-&~cpv?MQ
z7Q=Z-wKtrrRypmx`1ip7!;{xocdS^EWpRXe(c$m+FTLKy@A&oaHC-3hvaL)>vW7E?
zAAj7tsA_R!L)Ps(()oAN%Kjt@Ts6Ee=Io-Xeq8aL!t9#;T5l`EyI!4Vt=L-1AGomd
z)$HJT<<m-!2ULYlXWp=5yV>eh@rD-fHk4M}yUB1b>8_)T>-MS6cNj0t`#x{(s{Mfv
zq6!{otWw}B*jjox;9OSrZNAy;26=NYU;EZ_u&}*1{b7gJHDQ@Y3?*B({K>xcIf&~H
z-@R}rQIE#UW-g1DN0#%r#(dXi*yL)n<WQm0-W~b3zWcYH(0R?LWc2ZOm)xUE`|7jW
zpWoH%`^?QMwYIuL$5Lsb-QvqTl8)Lh*tIT$J!J3h%%`W^yUX?j23!r8@2Cn&#q-6p
zH{QQ+qu`?J<vaWKeHQ%?^0jo~-r2KP{5W^-#-&fsZsz9h-^M4|(-E`&Kzl$ByJ5`t
zdhWU&Lyzivvqda!?`rPw$q?vVqMg*S`|kJS{v1u4A6R_8aQ%B6Yu1|C9Znuh$9GB{
zuz5Y<poyAL{}P*g+lF${9|8QPYh!K(K1lBA{C5BNiTBQ(T9@^ot%<l8xy|{`-hK5x
zd==AI&EvkhS<y&t)wM{Mh06}GgI1T_*phX1{@Q4^rxw>0Ik>EjbY`u1-+KE&r8)!0
z*I#umAr@MnbQv^uS3e3`yEfma@?LJ_Rozv)*#5@9I3}GgIF*ZiqQ{ExfASX2-vSQu
zDSY}-eE05s?HjM3H!{a?9@zR$K}mRbRd&`s#wia4u5T%Ny4bh#NcHBOcS;!TSSDU&
zD2pr?oXT_c^Y!0#H@-jEvo1hi$5G%_?>lq77z^P8Kd;HUq&PQBeXbL~PgvuyV&4Ap
zwNYD_8czI?7i_c7!)T^*Xo_3|FGGdz)QpVKJb{=jS;Hx7t;=fU58VIs@6f8-zpARQ
zKlxkwS>ySx>5Z==ghE%niz)rO_4oh9Iqf@`P1i+UHddF*&-YR}*YJ3c<bk=@d|ei*
z3GJ=^_(*xJF`M!Fy|&AhD(`zbHarC_HdVjBezrcS*Tyh$MJc=B&48;n8gDa%9T6yB
z(0F?7d%lo##)<>G+BKFO3x8S!>W-z}Y2nOfu$g^)`W^1$8*eWzmDm&-I=$ih524Ui
z@p-S`#nnCFpYrzd%64P(nS1;jgX^Vw<5nnLXO>968*=WNsd>13aJ>D&U5BI0rq5om
z^z)Q2t*>kUd#4|HeD|7S`zO%I*3z2)Y%A)_{Pk~MljzSsdpY~*-KzWZnXY!PvF<o=
z<Q&6{`VW71iCQ0FY+&e0`E-nT?b^)1zspwaySZy+jPGo#ul7bab3TUMUS2cf5!*pm
zhJ6{bMl<%sygQb4e5cTXi2aTycC9-7>0*e+x>v0X%OXI9m}Y}(v2f>pnLmA9yXRDC
zfR<4n-nMRCJ#)e2QtrSN9Wgb#-?xAJbT=|L_qM3VvxiG>rK?Y_KY#eO$dLp8n*-wS
zsV!m>+__3~;*Wm|?;TalJFw^5w|&c89x1WvvCmIXz4iVCr^Al?CHzgP3`WV7oaP)(
zdw0CAxGKi5u=YYr2bXiBzUk4&&3Y@3D85rD7V7-ZdVwclekpgL#)`Oo>vmdh@s2u^
znO*JVnkReM`;PFlze(ml>!va+jQiBu@yWkY|E#CVI;mI57Dr^Af|Wl0b$D|3fr2{=
zgYm1^ublSoSo3YZr}S0HFAk<xr0<rqAN<J>mj)_wHnS_q+udPcXPC%$KVR-B<1WQZ
z$~*7OQ{dS3N@?O*_2Z9|cg+zrD}Ma3<ka`s3x7F-Ru8xwTNiWvPK|d&xzUW-KL6B2
zd++g1-0b$LQtQ*}ot;O1IhFQ?>WCGmoSvq=^SyCktH95>+;hyW<^I1du(MHGwYWMd
zKvbad@va*yXL(lMyYKq-yui<50haG+zkdZK#+ejb%zE_kzxU67Oe@y0o{tJjwO+Vy
z-8*Imr{67w4=k=*u2PnIB=D*Fq2KLIPniR3FM=w_b?gWJ=e&Kjt1Pa%`hJ1EX1sS#
z2&09gs~<zbI*W6up<B1^)jYqOUupaID_7Rs+<!iNWoFm${d4==majU&drjA6TF4VE
z)?2De`2U^hJ$^a!{O_qu`O?pp|G7KUaPi&+fyoORmNcwhYu&+>quwCX5G!!fsnooI
zC*-@slLv{*{2LPI%5X6VE_io9UO1ua+x!WV>=UC_xH0%hRg}m6Zx@LT3%zb}AYE$m
zNp<&MCtG9G*RdUlS#fUd+m}CcPJIqbE8e+&Z}!zyx~w*7jwWi8&6nA{uVC<A8{M&{
z<JIiT7hl};P&>RkckZiF0m*9#%MNT>7NHaUV#!6X%6pM9yC*p<;8xllTDqP2P1u6y
zhFGpQZLjh~Z)!ShXWA`0v6k_|Tb4$r6n2IcS>g;Vju%)NA}7iUuUftJ@ruQ}k~c;q
z{1mpnp>}`$ty!miyH;G=xz5^hxz$NVHBJN1MolfFNS8jA0<)0+sXgu0Ob1rw=uMY7
z9TT$VXx(y#9ZHXOiI@NQx79EH{?^{?YhOfO-l$Z(ygYuPzunKUjx(F`6pfUNOr7?8
z|4@AQuKk+ztA9&3g!BGvTy^`Km0xt>D!1c|>-e5(o_GGu&EWo9pEHoNu;~GN<B7!q
zch?@!E1e@N#j?A2@7~?sf2XaOD79mI{qF;}1J-$L-?B%mV9sXN3hQ6z|LvD@o_jL5
zR!WIq^TPt>I~Qko*i7nA^Q?@!xZh9XL$rHJT(Zr-<w^3@I+w)bDz>B<@iSUn+x66e
zY0mu_9yO<TC2Pp;yKnRAx4vcw)78l0$tQoWv1Xh6?Qd9Utl^d8D^8?8JMws=l4@_n
zt?&M!S1<gNl7EoMXm@vp$DKr3qZsglkk_xOx(ju9o3@|N%>JEf*yp+pRKWSqw)rW+
znAY+5Oa9}Pv(D~(w>dBW{WQ>Qk;tPRYPa(^KU9VO4PCYM>t0{&@UjS#9yida>fMKx
zXPK5Twv^q~S>#mIkj*eB_pafJefy#VLcdBfxbuDztX^$2Ga$c&|7!Lc;kHEw<QZ%B
zXinUryXL#cGtd8jBlT}^PP}vQdv50|yN)j`N_&~!uucfPdUv8i#VNJfUAYeuTh!U^
zbsc-+bBD1?^v8ucE|1#Vc$KdS_QokGExegNG5yhs8zE2Df)~qz1EPQRtLOYb{U%D!
ze)O?l%rf(a*|sfvET3EOAAF|v`Y<QUk4MGUWi@#!{uf%$){4g%d_D00Tvv)z{;tgJ
zq5Ky!X3pufcIahzn|Z$5Oid`eC%WzJK1t(!cDpx!zAu`wB~Q_4VU_8xax>1Q9k1_A
zIhnSe$>8IH@~2HX-?YVi4~tryyUOvLVfw^>w-fR<^GU7-O%t8o)u<tVXv4Res~w_m
zeZQYAYZS9FLZ{)i9@B=?yIM~)F}(Nx{m=87Y_sGKZ>x`!$~$WEK^r2(_h(dqnguHk
zu&=S^b8XB%mDr%HrJgA9h~Yrs)%?7iOwF0cUrL9s`O)6-$Nn{+lCs}|s->kz0`BCL
zNygRK2fq;i?y6FxdgycM&!aA0ueOOV@)B64FD6{n_xW*k?SF~a6CPUG%H=zEOpjL3
zQem{)bMJfq=64cj-dtU6&iv!tXZr=WE>7{WO9?mG@^xRmOo;Pt_qEJZ&Ri8*<R!RF
zk&huQCA5CW$?x7t>w_3gW}mKP;QI8!An-(}Yl!~#K8Y^vPy28D|FXnm#rZ=!S4~$u
z^4nzft5Vr{->+7S>2h5a@^+c3ljAJIuxGC|hh46$Va)rety$e2F{yVQQyd$o@m_q9
z;9WUG`i9Fdbq2XyAC-3--$|ai+bu57x!~xo#|AQtdVM?IJ=Q$`+wIinXLqk&DrzYe
z2~^!&XZ3Z0%ac<jCROgqMn4yno-W9-`F7*TnsetqGtSAn>lBjmIOc&+OLhPG*DNyx
zpM5>Es%WP-L(lei63e6*J~N(KUp6P^)MvTStL?H61Xtwc<YfPzTdEMal;iPC3x*CB
zrTgHOA=eZS3w9r63ct!8FeUUr=OGtYJrDhefbt*xTP{xV$f?OY-uFJLoF{GXdw<4)
zg{8+eb~4;kQVJB^$=LT<^R>bvFQIFSd`x?Gt=jg@>UH14S#y2<1-h==`cA>ffc5HC
z@kn=`RM6_PU5N&H0x>QB{x0q8a8sEwJ($1XU|YtQ-HG>>e{|SuYWhF;@?~Rx&<bS%
z(aEdgYIeWZw>Fo%pM5vT3p6Yfu=mEU#gmpKZ|o>5`{&VM%k`$&gFocE#)an{Z=`Mn
zt(I1@E^^q;aCg?(cLmJ})eFDvSCLw~fxqyPh2Nuds^0f1&V72iaDPZ8XvwSeqKjdI
zH#-W}?eGiH;1zDrXjmWJK4ns4{AT5~)><cv_y6A;93NhO?z6eas{@BmGlcN($PN1X
z(>wIhu7K;Vr#}B;$YH*~n!w$#e8DYMrRb2anxSutVzz5fKbu$BZ~bn5@5YF29`?Gc
z0v7I_^ULO{aCUW-)7}*?8lS06{_gl>srFIfsryfZ%Bg7gDP5&!&t47Kdu3O%+Y+e*
zh757s33?4b1%A$8y6*HutZ<I}>Q}XWukDu2ox4|d-+!^&F<Rvh<sbcu-E1hOJJWlL
z<pVB;xz}V}T$fsH-nUL~OZU~bvj^6PW{7()Gc2BPy7h0C_|zRil8>^A4shvC^qvB0
z<!NoYva9*T0n^vBX2-tn*wB46iO*%-hIa~!E`@11%P1IWzpdn6YuuLYXLFD5fjh|X
zvYOi1SPk<6{>hPZ=gPOd>bxfF5^~GyZOHqt<@#|o$7gDX*<{Na$>f>sRuS(sVVse2
zH|Z>69e0CuG>>DWD#Nnq@+Swca&2j^ER6N$^6+}175MLyz{ML=ZV8mTgqrQ<Inch=
zxh?tItE;mw&-?Dlx-aW)(pp2g|H2LSk>xFsr#?ShXw$aCeCgtgn<x6*%aj#zdztYi
zC$M&NDZAj*eV2C5*){(}C1`1O>9K;`Id-)>SNyxPt9iu=7rV^40#Qnd_ZIbZczL|!
zEo2bcv2e<^Cq**LMIDaqYF*LsZ|&l(rPE4XZt(n>RnVWRbgFxj%p-<9YgTRBmh$bz
zY}x+*VIli-?mC9}OgjCs=d$CEY$unWA*-Ba82;?<)zwukj`uvf#B)CD2lLl_ixvr5
zYTvz8wW-uCVu|g0UjfU@yP7*rxoh$lPCQT;Htp1`5ODW+Mb!i0>JY~!1&x_^!?<)A
z?D~WvUr*}ra@OQ840w>sTUsi=^_|4JV=14O2mEa-We?oQ@!{W=_w!TkChBg@xY)_G
z=l-td4mZ6s(!5i?2(UA7)hO<*_;`A)b({8zl{-ZoJl7PvPht045cM(r@s-l`PLefy
zRad!Wp5Ltt8k>tQm+`W!37olL=bhebf`?7NACunBX})(Em(qcD@0ZeRYi{o-c<94;
z4m5TWn0>|P*~Kl-&u-<jjIiV>WGL`E_1P<J_55QgpJp?>+xSjFYm(NJBGKQy-g-hi
zWgNDavJ3W}oXGWOiL%t+38g0*Po;J+hvb8blk~Zu-D7qQw%24`jxKQc5_jMJ*sjGl
z-o@?t;lU6H9xv<YSo5~S&3SYGZf1pS*@@yx?%67zTwnJ*oOSuyH<l3l<hza`DqD9d
z{FqVdvN7~&(R2n0(Cl#K<1UX)hd)1yZfE%Gd`Ikc#~#5<->qBrT((Nyk#ejjl|gRX
zI|VH^(VZKnoSW8v6*RuYR?t|=F8Fk=vcv7Rj4vji1sMKs={up!zHWC?Y;m#Yo%%}>
z-Kk6Kz1Pht<qj0|aV!1mdQI@C(Yo#BoDE%)QJq>oQ<>Mij@VPNE479B0q5z4J;8sc
z|I!TB+k8%9-La|K=8Qjfm9hsKu6T8H`|p1hult-pUGCMdKm$7=4odFcdf$0Zmp(c5
z)+fe(qW{!OOpB{s>=+-s2j#U31{>?2PugVmp*RPWC!4ap+!v>PKW?eD>E^2ktRah6
zX&>5i>Qm#n-s9i30t~0mT(L>BAadoMPX<!6Yxa9JE(K*xllYzG51l6G-;&{M`m}4#
zucn*!U;qB!)+e#fvh#?)$d7fU?16%3GG-X5iujj_9`d^i>yaoK>56y8Bo=14hn#+2
z^ooJENuPhs<q#p6iK-0SqRItCXLZHwUAOb*)^{hiH_i_}ns4kDk|~n0wc^*kl|j1K
zjSCx2Y*`iauIhEq!>pd;+q+(cg1l5vb9joT{FXkDp39sd2bN6UvTD@}Z!XK_>!P-D
zALvVx-_h}`y>S2LgLCHjtYi8R{F-l(Q}D#q-cR>keHh>n(sI8=Fm&A_`z>4RZ?E07
zcL|q+hzDq7mF4w>hXM|<$3HTDiP$b6dPDm1zWTmWmwh~cV(z8fb#zIKoA_<dqB`CJ
z28Ywt9n1~W!+WL6drOZLoQ>Q0X}y5vOx+_LZoXfIuW?o$j#li@n#c5B``JephM;}*
z%ps?1JG*&Y?zJma+_FlsV7k7xtm#2JL!Z^1<60j)1OIvoZdx(HWgq8)lxyZ^!~^H9
zKOn!>`k0f8U(kcu*JKqpD84zoh9Okz)8|DpK3|m?>f)y)2R`h$!=13Bd&>VcniDOy
zPOxO}VrW>AcP&ZwqMvBU`-UmUbS?Y@cz!3d{*ZC83qK&Us3~yb)@!`Up^WkN?b&)R
zW|8hZOIQ3~?~<qa?4gFpKUc<yN`J$O85A@gr@D1?baZs3cx8Qjl-ymq;UBxS%c=62
zf=WtCi<AnR9*DYHi!r!tx><Cms=K43W5tRl1&v$Vn)n!OHdlWaW0;vFI|U@HW9hdf
zqn)V%G|<Q}_o$VIprBx2Bv(_;M!u&u|MP2hG<I}!WcVoUyc6GDy5@PiMX3y5p^J-)
z%i`_n*Ir%q7kizcKc|zM$!?*Si;Ig%Rli7fuf>A{ihfHnCM$!?x+xeLe&(<x`ycD`
zM+5~01$+G_oK4#weumlZzr-4bJ?ecO9eh`~AG~MS*7>Te;|oIrlQ2uhg@1eJN;C9q
z?or`lW~}?NE_C%ak<T;E^A}#-dB^^D%=Q__)sz-}IKlBjA*6nplD+u#zh{pv?*Esr
zBWC@^?c8_$D3g`zSG}5g;%Q&|<2_slK5{fYRxGk<n91;CI``DwJxud;zB$Hkk*+!Q
zc^jj}q8oxPE-6Xs4Yysseye?a>~8V7Pfx8s*MjzXUUk26b#F|=W5zQA3*thTcRrS3
zyqd|djB$nRj}L{+v)kXZPLO`FI&>l@lTYI-7Y1RrdmV?IpLF|v{BgXy_C|BK=s$If
zBZ7iccULPEdB1Jpw68h7DfKs3<$}t$Z)+L;8GV>${ynzf;FTOTW5?zMCYkg_-}ozq
zWsc8WuxfH>%BICuj;_a?m+(0n1iGqm7qGZ2bNtHj<$vw*%`GNj_H%iT=<wC7P<-br
zrs(1lA`+kJrJ}dBPXgR>=XSUr5ud*Iz5m3VGO3vIS<EsESGijp5Y#gAZB$-Tf5F-*
zq(5L{ro@l@JwFaQtcvOX#(I$5FE88p=B_WU&T|<4>)d*z=He0(qh!D1`;BD%?dLcq
z8$bG($8eWHPX6Tc+#N3#W#*|}p1|G2Cb+Ww#KlFo6dannOdLx8JIjA%{{Q4ccpA$N
zex>*JtJmi4PCU#Vbn(Sgft}~H+B!hPFZcUqTYP-my06AdU$pz^oZxwNyY^{K&t?eF
zU**o;cUfW8U*~%V7*;qihe%(jKh}Rpo8iOOwbo@ZrUknjW{UF`zRdVyANpi>n4ybH
zh`_48;$L&7YQNvgxA3s{@g%|W)6?4aDP$D5_JvGTcHOG@LjG5u&_uQ``X4VT9Jt7!
zCaE4ish#<%H>iCU+0MYuTPPhB?O)jRfN`}1X!{B4K5O-fKPHs2iyi}Q#_YMhef`0}
zTn?p)iv?INZ~6bQH<LO2>nlN)uL3LG|6e|E`M}n{ZY~Y+tV-AKm%rI~U;f-C>!Y6@
zRX=js@jzcNaOOmX9S3(cay_5(^mH|&jpYY39nd`0$(d)iC<wijXJ(ZxW?<m;0i6r*
zsiA7cK7&7B<DboCTj1AtlF7&IfArHiUxj}fH^@6biSE@7x67Jatf4RU=$-Yi7t7O1
z%hDJ^B)<v>2G)H&b!O)N4Sfp=EY0QacmMnP!>s?wXORiN^>-{-w|;$o(UDU1=S4eD
zzOtAsd-WujPvhe&ov)VsJ-w&n#FPK`@9jNyEc9Nb%>RG$jkgI;y0KB%sY7vklT*XA
z9Ph2HjGBHsax!nOE1SA+@hPeE6WCJ2LznK0KDm4SuGRY@a<823%k63jdnL4T!ztgk
zBXRF`KMfK+<obk7)3c$XQ}&U?w=*{XYYq9fTX3>epS$s|c8PL--(t)CH~RjZE}r+<
zX2*5rUOw@ek+SbLH$)|vUA<_o^mP4UJLBq^67fCn{MWvGwd&VfkGGrEt2W*Idtj5u
zrjCviKVC=Qy;xXyOVQ=rvzOPdS;mD=*W6`3#m&vBLCR^y-;44E^Ai<oYJOkODf{E|
z)7T>O-QncD`<)rT3p0ovN>~{o!>BRq>-kk{zbe<(HfP!|C|Gz*t8njuwNv|*l$3-I
zWE;(_T>N@f=Lr#`Yr9NmiK{Cal}2og_>*``(Iw^2+`vaZs(vmhUWGrF$L_pie(9W|
z(&N`XLeJmDXG~h$(Gjw@s`&oJ;`e*am&&@h96LW#xzKabL<_-*E7KVjZ7xne{nz{b
zuF~Sme9B7k_aynvY%X3aD?RyUtI45`4i8ru_PU2@vDu$~)@HT~PUJ3j>wLZM`MgL|
z<Fq**$~_$&Ayb&oTiQ%AeEqM??!VWqMwcg_trs6*{IX^1*G%R(!HJpAZQGwW|K{d9
zFK#qb{N10g>+kzpPwD8%JtMSTdwTWBJNx5a8Yn3RmEL2#$MVhMjp=t=L(gwLSFXL2
zzWdJ8CCKQTM~vBTjSqjh(gg)4o>UHsoAk=J*;iLqHu^H3iqYMktvB>D)>;S(T5f01
zVSQI{<I?1_?`~DzuQgvb$1^4BWKZd(hYw~rmnbPIB}dC9)oe4L{kHV`{O`OxCI1sX
zKMT6G&}G>sL-$8pvYR_PVmR8x&TKn7-}?K5bvfVCcNgu{zI0B-D74q|!L{4h%9>}}
zhJzey^wi?Q>kqdd>|4Ba^XIu+m^*z$lc()C9u+N~I_XKk(!(7cC#HONFTO80ImLa)
zmrLo<w{CZ5vJ1^zb4;i3?c2ABR~I@vJLI;0?&vu2C6FQR*k8#9M_K0mDocOfxW&2C
zM=ZUzZlU_@yWAOi%^e*feK+TKd<=D}IC>{ux#h01y8phq=g$1R%Vd3*+?uoX$k(*Z
zwtTu%d6boujM_XZFFxEm<1Onq!N>PFs?(2DJb1<~_ru_6jnYbq;!Z(^a{G?Vg@S^D
zp0NyK%-x0YybY3!5}ra;n{Fl_5PV>e_WNvYy~*u-!*}a@Kl)C!nYrp*)T0YV%JZ*#
zK8T4vFSFccd%-dFb5|L~eN!|9CuS}w{IY|sT*jc>KzsV0ZQIIu`7C5U2z-;+^K$8>
zd$(@gvfcjYRrv9sb9zMw&qY1bX=#2JcT#6+*`!bZ@7y!3xc^YXfZ<E>wS0pIhToE}
z_5bEfvJqV9z|mZ4YO3u1>la)7hRV+;Dp+n#Ivs0b?)l1Zs#o!vh%;Aam>%&_Q#`hl
zuXFZQ_KboV$%fZ<N7@=3Pgv*79Ke6(;2OE_Ri~c2xUd|^S$Np#ft&Q-y=jU88e%Uq
zvwzz^2t89a`{wC5t+#rrC*R%v{IfB{xVwfgeQ*3O?diJ@-`TA#nI<#0z#?J8{WE+I
z{)v5v<9S$6P``g!gpJA7_UrQJpGswMxBha<eJis-afkWN>fi>ocC}`;@_eRQ2HN$1
zeh3K8e0T5AoBFeVcS<}i=Jov4p8xD~>lWwEnoBq3b51-B+wuGLRG!bQbBi`#Zw%Kx
zcKvM5{@Jo8M7Vy3|9xieewoia((=Z--|zERX^PGEny*nOIIF38vh(Ej3n|OF6MkmM
z{GG8xD$XV45s%~^fxGj+sNDQ^kX`;y-0d#UTj!!4ZF^EAezs_RoBJ-=3fUXIH}meq
zcYip={`c?iFZ?TZ*~~j_8nMwrf91-|u6Od&_g$Q5e`ofcHHlxY71*Zr9=YN0^IL)M
zt)H$g`x@*P+`hYA^v>@8i&npG-okwHOYynm{?(gqE<W&wEA{6R$M)mRzr(V!w{QLP
zY5MzR6CAZNy!Fa2zVTVMFGS-CGcTvf13U4I4+5`brPkQoU;jsHAJ-ZW^Q|2m46eoZ
zAAU%<f8fBikF)f3i|n3j7wR+JUlA~EyW#7y8<8?nx7M}FKCPLTksU2|_TQz4)d$wj
z`JI_9IMK_Z?Pgkgef;F}`=^vi%)E6j@=;mp=6;DkS6O1Mnd%ERuN8YdZQ8kW)7R9z
z4tc_TyYm0v&xbyIC_nqAn(sbi+VZ)cF3a|c7yjSAud(s}g)j0mIi715{?GdG{c*+K
z$82|J<a%?pzO7<#RCD@n`~A$Sm8*9PZ+`#yU+kG@OF>$<hRgm-EOkG=SZd9Lk0s}X
zuFpRG_sHG)f2!*@o<Fng!M?W{_5UZ&(pH#y<@UXKnzD8^-VN^`)LCzs^!d-7?hc;`
z_h;YqkNWg;`DH$(;KMuJ9~JG~`t08a@tX5WA9&u~)@jkz{rN{)T+TnGrgVM$euZG2
zbsGip*z*qm{j|ln^Td`%2b?edUB11vY~S=UiJ5oK{Y`Mz`>uQE|MTKK=M9_ZzT0Pf
zsQx8;uv#~$98#Tm#y3o_#GE;N@kA@ZnH9`C{+E=dr`x?%FshvUyX;jPFZbR6i=t`%
z`x7@@O<ZkiZh!gGy|_6IHA<piBeGvF@|kpp<Im3*g|-IjcSDqnQfK~6=X`hBEWSwb
zT;wB}HRiKr7wt)`X8f)$yN&JpTHV;#YHi^_6<cWG7XG+y@8Qz4Z9+TvA|{k=^L*s2
z|K7i5%BPFZ3l5!OJNvi7#5&KAFUc&!;6a*v)JhYHGi=VjzW>wjuh}0Wwa<FKedV@p
z+j*x=&v;BSh|#zr^jN1s#q-r&Tf-FxbIj5<C-?NGUCX%e;;HL$>9cDtE)?ACcE|s{
z)1uVultY$pI1T@mdWT<sw`KE*Cq?&eyV>4+W54?*_u<mgyXCpJO7;jXbXgVqzKxgL
zTUj~YJ7MSHq6AAto#VBf!S%ll+3%Tt-)_^=Ece)2u|-+#aiF<%*1Px8d)znPxc=!u
z^YTl4)eB|btc=Nf*zr5{VC}@&x@@xyv$sizCtu?+VKxrx(+WPU@XkKw?#-XOw=|!4
zvT&!p(&HBow`OP0es*T34rk)V!%1hRF?Ba~YvwzeowvJJyzSODsqO;|1{`x(`WW(=
z^BMDn58dXJky*3Ww&MCS-@`ADuF<>u`nvuJ5iW1%Nin`X+6KE%on3eEuXf1&?-8q_
zO}_8Xe);B)>n+EWqJU0e&y(MJrC+Cuary2z-~Z0{h{buo^ZU6I*X@*UnErhhFT=Aq
ze~$TbFN@3D`}1t2=9oyZ6&R}@t79;>e)rBf%`Bp+kwHCqrAbJ5c=;L&6BCn}?q^qB
z<lY%`w!Of$WWUtr)oWrt>~pJ}IeVpDly-d6%+%;lKhJF`_V^myDJ-~h!98B-v|x=p
z58jn0mzi(SdFvBY`px#{ojrT@?zLSe>#}OL*PITIuB!KYzn_|+vVHdNwL8`y%1OL6
zQ>B*AeC^8@6=rW`g6@Vqa&cL8;#^KyWzx1&cf%RCGk6F0sc05#u8)~~e*5yd&Jbfn
zU&n6G(=#=_-;-wkxNh%3-UENO6rW@<{(bjV&A<FheTr9oLCqqe!VR%&*Phn#3`^Q(
zv?Km`ns#CQsTa%!MyfWucP)OrY>Tr;>1C&BN=lPE8b2Rk{@wWZfb#P5`S*8h%zO6X
zgVCM!J@3M!IKm&*sTQzqV9_l%+PQ;&sjTCw`CfB6PKX%nD!VVe`1tZK+qS1adU)9T
z%wMB3vuuyC9$a(tq0k-i#BBoKTW6eIT~j0(%#mIr?`r40J=oQSMWg@ORZ*_bXKU+p
zri!%)=&?N$eq57arx@eZ^Vu+(A%@Fj$?S?(Mmu&dU7VbK%W}!COcg&Dmxg|~&wRad
z&%eIuueT|#$apbn((k1UL!uri>M-dUes4XnG_P#u)aS2E{bF8ezU)<>HGBJVS*KO=
z-5$BPq&Vf?-?4FDSw_ano%$P9BHMlkotgGvpU8LBUA@0GkG|OVYumYV%P;XMUG-P>
zb8!j!T9W;GPOzfRW`T8FhH;P6t}|#itZvvf<#FgF>pR<*EnckrR>8<}#gWbqkI<@$
zx3`{5TDEMx%lB;MH3r|a8!ofvhn@O(?Dm4$f8WlksVlzanDQy0Q&@1K=h1`zs{j5{
z-Ld|_->CBatUH8fOf1{RedTf5PSc-%_JQ)uA|Z7prOEfe>3E)1>Gs1>5BL(&Zp}P*
z`md+?@0+vw`eZZRC!X{KIdj>Rx6<a<&RUedVl&U)C=qS&TkNXQ_H#MgciKl4-LHvG
ze||di_{5W-gy6Dl%e~UqX%%Y4Yg<2*-U+w*Bl#gT;T=o76;nQwzLbrB&+VvPyT18-
zFin*T1UWVH<x2U#D+-r{M5VnuEi-NA@27H3lXsdkewI14{;c17&)E!L4;T~(NfbzI
z`t-V-_g~9R>x+LE?A~u`RQyc-{jDu8E4=D$XR`g1pRB}t?(jTSD+UGz22WQ%mvv4F
FO#n-78A$*D

literal 0
HcmV?d00001

diff --git a/data/revil.svg b/data/revil.svg
new file mode 100644
index 0000000..56af93c
--- /dev/null
+++ b/data/revil.svg
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="210mm"
+   height="297mm"
+   viewBox="0 0 744.09448819 1052.3622047"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+   sodipodi:docname="revil.svg"
+   enable-background="new">
+  <defs
+     id="defs4">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6513">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop6515" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop6517" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient6030"
+       osb:paint="gradient">
+      <stop
+         style="stop-color:#8c8c8c;stop-opacity:1;"
+         offset="0"
+         id="stop6032" />
+      <stop
+         style="stop-color:#8c8c8c;stop-opacity:0;"
+         offset="1"
+         id="stop6034" />
+    </linearGradient>
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="-132.85714 : 497.60967 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="201.23735 : 663.32396 : 1"
+       inkscape:persp3d-origin="107.76153 : 116.50168 : 1"
+       id="perspective4511" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4499">
+      <stop
+         style="stop-color:#e03838;stop-opacity:1;"
+         offset="0"
+         id="stop4501" />
+      <stop
+         style="stop-color:#e03838;stop-opacity:0;"
+         offset="1"
+         id="stop4503" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4499"
+       id="linearGradient4545"
+       gradientUnits="userSpaceOnUse"
+       x1="119.00173"
+       y1="176.68629"
+       x2="491.26828"
+       y2="176.68629"
+       gradientTransform="translate(77.142857,11.428571)" />
+    <filter
+       inkscape:collect="always"
+       style="color-interpolation-filters:sRGB"
+       id="filter6463">
+      <feBlend
+         inkscape:collect="always"
+         mode="screen"
+         in2="BackgroundImage"
+         id="feBlend6465" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6513"
+       id="radialGradient6519"
+       cx="260.49961"
+       cy="200.31575"
+       fx="260.49961"
+       fy="200.31575"
+       r="174.20097"
+       gradientTransform="matrix(1,0,0,0.36832117,0,126.53522)"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.49497475"
+     inkscape:cx="-446.62596"
+     inkscape:cy="898.65332"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1920"
+     inkscape:window-height="1018"
+     inkscape:window-x="0"
+     inkscape:window-y="36"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     style="display:inline;filter:url(#filter6463)">
+    <path
+       style="fill:#be6565;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4.44099951;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 130.01379,128.08841 c 21.52877,0.022 43.05755,0.0441 64.58635,0.066 22.3643,-24.06221 48.52474,-31.460888 67.2259,-58.191769 2.71923,-0.06472 20.98912,-11.557161 33.93105,-24.068007 15.4842,-14.968435 25.95668,-31.394675 28.5419,-31.451169 50.54179,-1.104457 -14.12859,63.648811 -14.12859,63.648811 -4.32309,21.069986 25.52253,23.438544 42.33546,21.471776 42.70584,1.240658 85.40384,-0.8708 127.81819,-5.21873 25.73481,0.95872 51.31917,4.15799 76.90885,6.766478 9.54752,15.5434 0.83547,34.65487 -20.48439,28.40762 -26.2476,-2.99553 -27.63034,-2.30793 -53.8003,-2.02882 -12.78621,1.48832 -49.8581,9.73983 -62.64433,11.22817 -13.52493,16.3347 22.62946,13.21758 33.1675,10.07832 39.0413,-3.04219 77.95598,5.00291 116.9575,3.82945 23.10382,5.19727 8.0288,36.69047 -13.60972,28.74833 -44.19318,-2.94318 -88.36238,6.11604 -132.48254,0.88974 -19.82007,8.99739 21.64912,8.11335 30.86918,8.87517 27.68051,0.65118 54.70333,7.75945 82.5212,7.68297 22.55858,-7.69442 38.01639,26.96661 11.18339,29.72006 -36.46307,1.38329 -72.43925,-4.63303 -108.75088,-5.88757 -14.49857,0.76494 -17.71181,-4.22347 -30.32901,0.80137 -10.13989,10.28009 8.44125,11.49178 13.96391,12.36504 16.24581,9.74748 43.72122,2.97051 59.96588,18.47736 6.7707,13.90543 -22.57952,14.89139 -37.10486,9.32981 -30.11101,-5.44137 -35.65502,-1.94584 -60.67011,-9.04294 -19.50206,-3.53729 -40.83637,-3.42785 -60.71049,-0.67171 -24.72427,1.38733 -39.52595,0.63872 -62.90978,-7.17843 -35.40447,-1.67908 -63.45037,-6.42784 -94.2085,-0.57775 L 144.76,253.13224 Z"
+       id="path6341"
+       inkscape:connector-curvature="0"
+       inkscape:export-filename="/home/flo/test.png"
+       inkscape:export-xdpi="127.06"
+       inkscape:export-ydpi="127.06"
+       sodipodi:nodetypes="cccssccccccccccccccccccccccccc" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:0%;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';letter-spacing:-9.01962376px;word-spacing:0px;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:7.52591181;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       x="84.118187"
+       y="241.26474"
+       id="text4136"
+       transform="scale(1.133983,0.88184743)"
+       inkscape:export-filename="/home/flo/test.png"
+       inkscape:export-xdpi="127.06"
+       inkscape:export-ydpi="127.06"><tspan
+         sodipodi:role="line"
+         id="tspan4138"
+         x="84.118187"
+         y="241.26474"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:137.36247253px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';letter-spacing:-9.01962376px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:7.52591181;stroke-opacity:1">REVIL</tspan></text>
+  </g>
+</svg>
diff --git a/data/revil.xml b/data/revil.xml
new file mode 100644
index 0000000..b7a00b3
--- /dev/null
+++ b/data/revil.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<mime-type xmlns="http://www.freedesktop.org/standards/shared-mime-info" type="application/revil">
+  <glob pattern="*.rev"/>
+</mime-type>
diff --git a/src/Reveal.cpp b/src/Reveal.cpp
new file mode 100644
index 0000000..68396b4
--- /dev/null
+++ b/src/Reveal.cpp
@@ -0,0 +1,718 @@
+/***************************************************************************
+ *	Reveal.cpp
+ *	Part of Revil
+ *	2015-  Florent Berthaut
+ *	hitmuri.net
+ ****************************************************************************/
+/*
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "Reveal.hpp" 
+
+#include <iostream>
+#include <unistd.h>
+#include <FL/filename.H>
+
+#include <OpenNI.h>
+
+#include "geoms/BoxGeometry.hpp"
+#include "geoms/CamGeometry.hpp"
+#include "geoms/QuadGeometry.hpp"
+#include "geoms/SphereGeometry.hpp"
+#include "geoms/TubeGeometry.hpp"
+#include "geoms/ConeGeometry.hpp"
+#include "geoms/FrameGeometry.hpp"
+
+#include "modules/RevealedShapeModule.hpp"
+#include "modules/RevealedPathModule.hpp"
+#include "modules/RevealedTextModule.hpp"
+#include "modules/RevealedCutModule.hpp"
+#include "modules/RevealedArrowModule.hpp"
+#include "modules/RevealedGridModule.hpp"
+#include "modules/RevealedModelModule.hpp"
+#include "modules/GroupModule.hpp"
+#include "modules/SpaceModule.hpp"
+#include "modules/PreviewModule.hpp"
+#include "modules/ProjectorModule.hpp"
+#include "modules/DepthCamModule.hpp"
+#include "modules/DepthShapeModule.hpp"
+#include "modules/DepthMeshModule.hpp"
+#include "modules/DepthGroupModule.hpp"
+#include "modules/RootSceneGroupModule.hpp"
+#include "modules/SceneGroupModule.hpp"
+#include "modules/OutputManagerModule.hpp"
+#include "gui/MainWindow.hpp"
+#include "gui/GuiListener.hpp"
+#include "osc/OscManager.hpp"
+#include "osc/OscListener.hpp"
+
+using namespace std;
+
+Reveal* Reveal::getInstance() {
+	static Reveal rev;
+	return &rev;
+}
+
+Reveal::~Reveal(){}
+
+Reveal::Reveal() : GroupModule() {
+	m_type="Revil";
+	m_name="revil";
+	addAttribute(new Attribute("open", 
+				Attribute::FILE_OPEN_ATTRIBUTE, 
+				openCallback, this, Attribute::LOCAL, 
+				false));
+	addAttribute(new Attribute("save", 
+				Attribute::FILE_SAVE_ATTRIBUTE, 
+				saveCallback, this, Attribute::LOCAL, 
+				false));
+	addAttribute(new Attribute("quit", 
+				Attribute::ACTION_ATTRIBUTE, 
+				quitCallback, this, Attribute::LOCAL, 
+				false));
+	addAttribute(new Attribute("ressources_folder", 
+				Attribute::FOLDER_OPEN_ATTRIBUTE, 
+				ressourcesCallback, this, Attribute::LOCAL, 
+				false));
+	addAttribute(new Attribute("ressource_upload", 
+				Attribute::ACTION_STRING_ATTRIBUTE, 
+				uploadCallback,this,2,Attribute::GLOBAL,false));
+	addAttribute(new Attribute("debug_osc_input", 
+				Attribute::BOOL_ATTRIBUTE, 
+				debugOscCallback,this,1,Attribute::GLOBAL));
+	m_debugOSC=false;
+}
+
+void idleFunc(void* data) {
+	Reveal::getInstance()->update();
+	usleep(1000);
+}
+
+void Reveal::init() {
+	m_openPlanned=0;
+
+	//initialize osc input 
+	OscManager::getInstance()->init();
+
+	//initialize depth cameras
+	openni::OpenNI::initialize();
+	openni::OpenNI::setLogConsoleOutput(false);
+	cout<<"Initialized OpenNI "<<openni::OpenNI::getExtendedError()<<endl;
+
+	//initialize observers counter
+	m_upObsIdCounter=0;
+
+	//create all scene geometries 
+	m_geomsMap[GEOM_BOX] = new BoxGeometry();
+	m_geomsMap[GEOM_QUAD] = new QuadGeometry();
+	m_geomsMap[GEOM_SPHERE] = new SphereGeometry();
+	m_geomsMap[GEOM_TUBE] = new TubeGeometry();
+	m_geomsMap[GEOM_CONE] = new ConeGeometry();
+	m_geomsMap[GEOM_FRAME] = new FrameGeometry();
+	map<GEOM_ID, Geometry*>::iterator itGeom = m_geomsMap.begin();
+	for(; itGeom!=m_geomsMap.end(); ++itGeom) {
+		itGeom->second->setGeomID(itGeom->first);
+		m_geoms.push_back(itGeom->second);
+	}
+
+	m_contextHandlersCounter=0;
+
+	m_maxNbRevealed=502;
+	m_maxNbDepthCams=10;
+
+	//add the outputs module
+	m_output = new OutputManagerModule();
+	addChild(m_output);
+
+	//add spaces module 
+	m_spaces = new SpacesModule();
+	addChild(m_spaces);
+
+	//create scene module
+	m_scene = new RootSceneGroupModule();
+	m_scene->addGroupAttributes();
+	addChild(m_scene);
+
+	//Initialize main window
+	fl_register_images();
+	MainWindow::getInstance()->init();
+	Fl::add_idle(idleFunc, MainWindow::getInstance());
+
+	//Initialize glfw for preview and projector windows
+	glewExperimental = GL_TRUE;
+	if(!glfwInit()) {
+		exit(EXIT_FAILURE);
+	}
+	glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); //FIXME GLFW 3.3
+	glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
+	glfwWindowHint(GLFW_AUTO_ICONIFY, GL_FALSE);
+#ifdef GL42
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+#else 
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
+#endif
+#ifdef OSX
+	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
+#endif
+
+	//add preview module
+	m_preview = new PreviewModule();
+	m_spaces->addChild(m_preview);
+
+	refreshModules();
+
+	//Show main window
+	MainWindow::getInstance()->show();
+
+	//start timer
+	gettimeofday(&m_prevTime, NULL);
+}
+
+GLFWwindow* Reveal::getPreviewWindow() {
+	return m_preview->getWindow();
+}
+
+void Reveal::planOpen(std::string opSt) {
+	//FIXME find better strategy for delaying text
+	m_openPlanned=10;
+	m_openPlannedName=opSt;
+}
+
+void Reveal::update() {
+	//delete listeners, attributes and modules
+	testDelete();
+
+	//update osc manager
+	OscManager::getInstance()->update();
+
+	//FIXME distinguish between anim and update (cam)
+	//update observers every 50ms 
+	timeval curTime, timeDiff;
+	gettimeofday(&curTime,NULL);
+	timersub(&curTime, &m_prevTime, &timeDiff);
+	int timeDiffMs = timeDiff.tv_sec*1000.0+timeDiff.tv_usec/1000.0;
+	m_prevTime=curTime;
+	vector<Module*>::iterator itUp = m_updateObservers.begin();
+	for(; itUp!=m_updateObservers.end(); ++itUp) {
+		(*itUp)->update(timeDiffMs);
+	}
+
+	//draw all spaces
+	m_spaces->draw();
+
+	//delayed open to fix text rendering issues ...
+	if(m_openPlanned>0) {
+		m_openPlanned--;
+		if(m_openPlanned==0) {
+			open(m_openPlannedName);
+		}
+	}
+
+	glfwPollEvents();
+}
+
+int Reveal::run() {
+	return Fl::run();
+}
+
+void Reveal::askQuit() {
+	MainWindow::getInstance()->cbQuit();
+}
+
+void Reveal::quit() {
+	glfwTerminate();
+	exit(0);
+}
+
+void Reveal::open(const std::string& fileName) {
+	cout<<"Opening "<<fileName<<endl;
+	bool open=true;
+	xmlDocPtr doc = xmlReadFile(fileName.c_str(), NULL, 0);
+	xmlNodePtr rootNode = xmlDocGetRootElement(doc);
+	if(doc==NULL || rootNode==NULL) {
+		DEBUG("Could not open file "<<fileName);
+		open=false;
+	}
+	else if(xmlStrcmp(rootNode->name, (const xmlChar*)"Revil")) {
+		xmlFreeDoc(doc);
+		DEBUG("Could not open file "<<fileName);
+		open=false;
+	}
+	if(open) { //if the file is valid
+		m_currentFile=fileName;
+		//clear the scene and spaces
+		m_scene->deleteChildren();
+		m_spaces->removeChild(m_preview);
+		m_spaces->deleteChildren();
+		m_spaces->addChild(m_preview);
+		m_revealedMap.clear();
+		m_registeredOutputRevealed.clear();
+		m_registeredOutputDepthCams.clear();
+		m_upObsIdCounter=0;
+		m_updateObservers.clear();
+		//and load
+		load(rootNode);
+		m_attributesMap["save"]->initFile(m_currentFile);
+		MainWindow::getInstance()->refreshModules();
+		DEBUG("Opened file "<<fileName);
+	}
+}
+
+void Reveal::save(const std::string& fileName) {
+	cout<<"Saving to "<<fileName<<endl;
+	m_currentFile=fileName;
+	xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
+	xmlNodePtr rootNode = GroupModule::save(NULL);
+	xmlDocSetRootElement(doc, rootNode);
+	xmlSaveFormatFileEnc(fileName.c_str(), doc, "UTF-8", 1);
+	xmlFreeDoc(doc);
+	xmlCleanupParser();
+}
+
+void Reveal::setRessourcesFolder(const std::string& f) {
+
+}
+
+void Reveal::uploadRessource(const std::vector<std::string>& vf) {
+
+}
+
+void Reveal::load(xmlNodePtr node) {
+	Module::load(node);
+	xmlNodePtr modsNode;
+	for(modsNode=node->children; modsNode; modsNode=modsNode->next){
+		if(modsNode->type == XML_ELEMENT_NODE &&
+				!xmlStrcmp(modsNode->name, (const xmlChar *) "Modules")) {
+			xmlNodePtr modNode;
+			for(modNode=modsNode->children; modNode; modNode=modNode->next){
+				if(modNode->type == XML_ELEMENT_NODE) {
+					if(!xmlStrcmp(modNode->name,(const xmlChar *)"Scene")) {
+						m_scene->load(modNode);
+					}
+					else if(!xmlStrcmp(modNode->name,(const xmlChar*)"Spaces")){
+						m_spaces->load(modNode);
+					}
+				}
+			}
+		}
+	}
+}
+
+Module* Reveal::createModule(const std::string& typeStr) {
+	Module* mod=NULL;
+	if(typeStr.compare("Projector")==0) {
+		mod=new ProjectorModule();
+	}
+	else if(typeStr.compare("Space")==0) {
+		mod=new SpaceModule();
+	}
+	else if(typeStr.compare("DepthGroup")==0) {
+		mod=new DepthGroupModule();
+	}
+	else if(typeStr.compare("DepthCam")==0) {
+		mod=new DepthCamModule();
+	}
+	else if(typeStr.compare("DepthShape")==0) {
+		mod=new DepthShapeModule();
+	}
+	else if(typeStr.compare("DepthMesh")==0) {
+		mod=new DepthMeshModule();
+	}
+	else if(typeStr.compare("SceneGroup")==0) {
+		mod=new SceneGroupModule();
+	}
+	else if(typeStr.compare("Shape")==0) {
+		mod=new RevealedShapeModule();
+	}
+	else if(typeStr.compare("Model")==0) {
+		mod=new RevealedModelModule();
+	}
+	else if(typeStr.compare("Path")==0) {
+		mod=new RevealedPathModule();
+	}
+	else if(typeStr.compare("Text")==0) {
+		mod=new RevealedTextModule();
+	}
+	else if(typeStr.compare("Cut")==0) {
+		mod=new RevealedCutModule();
+	}
+	else if(typeStr.compare("Arrow")==0) {
+		mod=new RevealedArrowModule();
+	}
+	else if(typeStr.compare("Grid")==0) {
+		mod=new RevealedGridModule();
+	}
+	return mod;
+}
+
+Listener* Reveal::createListener(const std::string& typeStr) {
+	Listener* lis=NULL;
+	if(typeStr.compare("OscListener")==0) {
+		lis=new OscListener();
+	}
+	return lis;
+}
+
+int Reveal::getVisibilityMask(const std::string& visibleFrom) {
+	int res=0;
+	map<string, int>::iterator itVis = m_visibleFromMap.find(visibleFrom);
+	if(itVis!=m_visibleFromMap.end()) {
+		res=itVis->second;
+	}
+	return res;
+}
+
+void Reveal::addUpdateObserver(Module* upObs) {
+	m_updateObservers.push_back(upObs);
+	upObs->setUpID(m_upObsIdCounter);
+	m_upObsIdCounter++;
+}
+
+void Reveal::removeUpdateObserver(Module* upObs) {
+	vector<Module*>::iterator itObs = m_updateObservers.begin();
+	for(; itObs!=m_updateObservers.end(); ) {
+		if((*itObs)->getUpID()==upObs->getUpID()) {
+			itObs = m_updateObservers.erase(itObs);
+		}
+		else {
+			itObs++;
+		}
+	}
+}
+
+void Reveal::addModuleListObserver(ModuleListObserver* obs) {
+	unsigned int obsID=0;
+	while(m_moduleListObservers.find(obsID)!=m_moduleListObservers.end()) {
+		obsID++;
+	}
+	m_moduleListObservers[obsID]=obs;
+	obs->setModuleListObsID(obsID);
+}
+
+void Reveal::removeModuleListObserver(ModuleListObserver* obs) {
+	m_moduleListObservers.erase(obs->getModuleListObsID());
+}
+
+void Reveal::addContextHandler(ContextHandler* cont) {
+	m_contextHandlers[m_contextHandlersCounter]=cont;
+	cont->setContextHandlerID(m_contextHandlersCounter);
+	m_contextHandlersCounter++;
+}
+
+void Reveal::removeContextHandler(ContextHandler* cont) {
+	m_contextHandlers.erase(cont->getContextHandlerID());
+}
+
+void Reveal::registerGeom(Geometry* geom) {
+	GEOM_ID newID = GEOM_MODEL;
+	while(m_geomsMap.find(newID)!=m_geomsMap.end()) {
+		newID = GEOM_ID(int(newID)+1);
+	}
+	geom->setGeomID(newID);
+	m_geomsMap[newID]=geom;
+	m_geoms.push_back(geom);
+}
+
+void Reveal::unregisterGeom(Geometry* geom) {
+	m_geomsMap.erase(geom->getGeomID());
+	vector<Geometry*>::iterator itGeom = m_geoms.begin();
+	for(; itGeom!=m_geoms.end(); ) {
+		if((*itGeom)->getGeomID()==geom->getGeomID()) {
+			itGeom = m_geoms.erase(itGeom);
+		}
+		else {
+			++itGeom;
+		}
+	}
+}
+
+void Reveal::registerRevealed(RevealedModule* rev) {
+	m_revealedVec.push_back(rev);
+	updateRevealed();
+}
+
+void Reveal::unregisterRevealed(RevealedModule* rev) {
+	vector<RevealedModule*>::iterator itRev=m_revealedVec.begin();
+	for(; itRev!=m_revealedVec.end();) {
+		if((*itRev)->getRevID()==rev->getRevID()) {
+			itRev=m_revealedVec.erase(itRev);
+		}
+		else {
+			++itRev;
+		}
+	}
+	updateRevealed();
+	unregisterOutputRevealed(rev);
+}
+
+void Reveal::updateRevealed() {
+	m_revealedMap.clear();
+	vector<RevealedModule*>::iterator itRev=m_revealedVec.begin();
+	unsigned int id=1;
+	for(; itRev!=m_revealedVec.end(); ++itRev, ++id) {
+		(*itRev)->setRevID(id);
+		m_revealedMap[id]=*itRev;
+	}
+}
+
+void Reveal::refreshModules() {
+	//recreate map of modules and attributes
+	m_modulesMap.clear();
+	m_fullAttributesMap.clear();
+	GroupModule::listModulesAndAttributes("", m_modulesMap, 
+			m_fullAttributesMap);
+
+	//inform observers of the new module list
+	map<unsigned int, ModuleListObserver*>::iterator itObs 
+		= m_moduleListObservers.begin(); 
+	for(; itObs!=m_moduleListObservers.end(); ++itObs) {
+		itObs->second->updateModulesList(m_modulesMap);
+	}
+
+	//refresh space/projectors list
+	m_visibleFromVec.clear();
+	m_visibleFromMap.clear();
+	m_visibleFromVec.push_back("none");
+	m_visibleFromMap[m_visibleFromVec.back()]=VISIBLE_FROM_NONE;
+	m_visibleFromVec.push_back("all");
+	m_visibleFromMap[m_visibleFromVec.back()]=VISIBLE_FROM_ALL;
+	m_spaces->getVisibleFromList(m_visibleFromVec, m_visibleFromMap);
+
+	map<unsigned int, RevealedModule*>::iterator itMod
+		= m_revealedMap.begin(); 
+	for(; itMod!=m_revealedMap.end(); ++itMod) {
+		itMod->second->setVisibleFromList(m_visibleFromVec);
+	}
+
+	//refresh display
+	MainWindow::getInstance()->refreshModules();
+
+	/*
+	//TEMP list all attributes of all modules 
+	map<string, Attribute*>::iterator itAtt = m_attributesMap.begin();
+	for(;itAtt!=m_attributesMap.end(); ++itAtt) {
+	cout<<itAtt->first<<endl;
+	}
+	*/
+}
+
+Attribute* Reveal::findAttribute(const std::string& fullName) {
+	map<string,Attribute*>::iterator itAtt = m_fullAttributesMap.find(fullName);
+	if(itAtt!=m_fullAttributesMap.end()) {
+		return itAtt->second;
+	}
+	return NULL;
+}
+
+Module* Reveal::findModule(const std::string& fullName) {
+	map<string, Module*>::iterator itMod = m_modulesMap.find(fullName);
+	if(itMod!=m_modulesMap.end()) {
+		return itMod->second;
+	}
+	return NULL;
+}
+
+void Reveal::registerOutputRevealed(RevealedModule* rev) {
+	bool found=false;
+	vector<RevealedModule*>::iterator itSh=m_registeredOutputRevealed.begin();
+	for(; itSh!=m_registeredOutputRevealed.end(); ++itSh) {
+		if((*itSh)->getRevID()==rev->getRevID()) {
+			found=true;
+		}
+	}
+	if(!found) {
+		m_registeredOutputRevealed.push_back(rev);
+	}
+	updateOutputRevealed();
+}
+
+void Reveal::unregisterOutputRevealed(RevealedModule* rev) {
+
+	//remove it from list
+	vector<RevealedModule*>::iterator itSh=m_registeredOutputRevealed.begin();
+	for(; itSh!=m_registeredOutputRevealed.end(); ) {
+		if((*itSh)->getRevID()==rev->getRevID()) {
+			itSh=m_registeredOutputRevealed.erase(itSh);
+		}
+		else {
+			++itSh;
+		}
+	}
+
+	//reset offsets 
+	updateOutputRevealed();
+}
+
+void Reveal::updateOutputRevealed() {
+	vector<RevealedModule*>::iterator itSh=m_registeredOutputRevealed.begin();
+	unsigned int offset=0;
+	for(; itSh!=m_registeredOutputRevealed.end(); ++itSh) {
+		(*itSh)->updateRevOffset(offset);
+	}
+}
+
+void Reveal::registerOutputDepthCam(DepthCamModule* cam) {
+	bool found=false;
+	vector<DepthCamModule*>::iterator itCa=m_registeredOutputDepthCams.begin();
+	for(; itCa!=m_registeredOutputDepthCams.end(); ++itCa) {
+		if((*itCa)->getDepthID()==cam->getDepthID()) {
+			found=true;
+		}
+	}
+	if(!found) {
+		m_registeredOutputDepthCams.push_back(cam);
+	}
+}
+
+void Reveal::unregisterOutputDepthCam(DepthCamModule* cam) {
+	vector<DepthCamModule*>::iterator itCa=m_registeredOutputDepthCams.begin();
+	for(; itCa!=m_registeredOutputDepthCams.end(); ) {
+		if((*itCa)->getDepthID()==cam->getDepthID()) {
+			itCa=m_registeredOutputDepthCams.erase(itCa);
+		}
+		else {
+			++itCa;
+		}
+	}
+}
+
+void Reveal::deleteListener(Listener* lis) {
+	m_listenersDeleteVec.push_back(lis);
+}
+
+void Reveal::deleteModule(Module* mod) {
+	m_modulesDeleteVec.push_back(mod);
+	refreshModules();
+}
+
+void Reveal::testDelete() {
+	bool erasedListeners=false;
+	vector<Listener*>::iterator itLis = m_listenersDeleteVec.begin();
+	for(; itLis!=m_listenersDeleteVec.end(); ++itLis) {
+		delete (*itLis);
+		erasedListeners=true;
+	}
+	m_listenersDeleteVec.clear();
+
+	if(m_modulesDeleteVec.size()>0) {
+		MainWindow::getInstance()->refreshModules(true, erasedListeners);
+	}
+	vector<Module*>::iterator itMod = m_modulesDeleteVec.begin();
+	for(; itMod!=m_modulesDeleteVec.end(); ++itMod) {
+		delete (*itMod);
+	}
+	m_modulesDeleteVec.clear();
+}
+
+GLuint Reveal::createProgram(const char* vertSource, const char* fragSource) {
+	GLint compile_ok = GL_FALSE, link_ok = GL_FALSE;
+	GLuint vertexShader, fragmentShader;
+	vertexShader = glCreateShader(GL_VERTEX_SHADER);
+	glShaderSource(vertexShader, 1, &vertSource, NULL);
+	glCompileShader(vertexShader);
+	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compile_ok);
+	if(!compile_ok) {
+		cout << "Error in vertex shader" << endl;
+		GLint maxLength = 0;
+		glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);
+		std::vector<GLchar> errorLog(maxLength);
+		glGetShaderInfoLog(vertexShader,maxLength,&maxLength, &errorLog[0]);
+		vector<GLchar>::iterator itC=errorLog.begin();
+		for(; itC!=errorLog.end(); ++itC) {
+			cout<<*itC;
+		}
+		cout<<endl;
+	} 
+	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+	glShaderSource(fragmentShader, 1, &fragSource, NULL);
+	glCompileShader(fragmentShader);
+	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compile_ok);
+	if(!compile_ok) {
+		cout << "Error in fragment shader" << endl;
+		GLint maxLength = 0;
+		glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
+		std::vector<GLchar> errorLog(maxLength);
+		glGetShaderInfoLog(fragmentShader,maxLength,&maxLength, &errorLog[0]);
+		vector<GLchar>::iterator itC=errorLog.begin();
+		for(; itC!=errorLog.end(); ++itC) {
+			cout<<*itC;
+		}
+		cout<<endl;
+	}
+	GLuint program = glCreateProgram();
+	glAttachShader(program, vertexShader);
+	glAttachShader(program, fragmentShader);
+	glLinkProgram(program);
+	glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
+	if(!link_ok) {
+		cout<<"Error linking glsl program "<<program<<" "<<endl;
+		GLint maxLength = 0;
+		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
+		std::vector<GLchar> errorLog(maxLength);
+		glGetProgramInfoLog(program,maxLength,&maxLength, &errorLog[0]);
+		vector<GLchar>::iterator itC=errorLog.begin();
+		for(; itC!=errorLog.end(); ++itC) {
+			cout<<*itC;
+		}
+		cout<<endl;
+	}
+	return program;
+}
+
+void Reveal::measureStart() {
+	gettimeofday(&m_measureTime, NULL);
+	m_measuring=true;
+}
+
+void Reveal::measureStore(const int& nbPixels) {
+	if(m_measuring) {
+		timeval curTime, timeDiff;
+		gettimeofday(&curTime, NULL);
+		timersub(&curTime, &m_measureTime, &timeDiff);
+		int timeDiffMs=int(timeDiff.tv_sec)*1000000 
+			+ int(timeDiff.tv_usec);
+		if(m_measurePixelNb.find(nbPixels)==m_measurePixelNb.end()) {
+			m_measurePixelTimes[nbPixels]=0;
+			m_measurePixelNb[nbPixels]=0;
+		}
+		m_measurePixelNb[nbPixels]++;
+		m_measurePixelTimes[nbPixels]+=timeDiffMs;
+		cout<<nbPixels<<" "
+			<<float(m_measurePixelTimes[nbPixels])
+			/ float(m_measurePixelNb[nbPixels])<<endl;
+
+		m_measuring=false;
+	}
+}
+
+//MAIN 
+int main( int argc, char **argv ) {
+	Reveal::getInstance()->init();
+	if(argc>1) {
+		char* abs = new char[200];
+		fl_filename_absolute(abs, 200, argv[1]);
+		Reveal::getInstance()->planOpen(string(abs));	 
+	}
+	return Reveal::getInstance()->run();
+}
+
+
diff --git a/src/Reveal.hpp b/src/Reveal.hpp
new file mode 100644
index 0000000..e1cf895
--- /dev/null
+++ b/src/Reveal.hpp
@@ -0,0 +1,272 @@
+/***************************************************************************
+ *	Reveal.hpp
+ *	Part of Reveal
+ *	2015-  Florent Berthaut
+ *	hitmuri.net
+ ****************************************************************************/
+/*
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef Reveal_h
+#define Reveal_h
+
+#include "modules/ContextHandler.hpp"
+#include "modules/GroupModule.hpp"
+
+class DepthCamModule;
+class ProjectorsModule;
+class SceneModule;
+class RootSceneGroupModule;
+class RevealedModule;
+class SpacesModule;
+class OutputManagerModule;
+class PreviewModule;
+
+class Geometry;
+class ModuleListObserver;
+
+class Reveal : public GroupModule {
+
+	public:
+		enum REVIL_PROGRAM {
+			PREVIEWPROG, SLICEPROG, SELECTPROG, RENDERPROG, CALIBPROG, POSTPROG
+		};
+		enum REVIL_UNIFORM {
+			VIEWMAT, VIEWPROJMAT, MODELMAT, INVMODELMAT, MIRRORED, MODELSCALE,
+			SUBSHAPEINVMAT,
+			VIEWPORTWIDTH, VIEWPORTHEIGHT, 
+			SHAPECOLOR, SHAPEID, SHAPEIDBIT, SUBSHAPEID, SUBSHAPESNB, 
+			SHAPEGEOM,
+
+			SURFACE, SURFACECOLOR, SURFACETHICKNESS,
+
+			INSIDEVISIBLE, INSIDESTRUCT, STRUCTRATIO,
+			GRADIENTALPHA, GRADIENTTYPE, GRADIENTSTEPS, GRADIENTCURVERATIO, 
+			GRADIENTTEXTURE,
+			DENSITYALPHA, DENSITYTYPE, DENSITYRATIO, DENSITYSIZE, 
+			DENSITYCURVERATIO,
+			TEXALPHA, TEXBLEND, TEXOFFSET, TEXSCALE, TEXGRAY,
+			REACTIVITY,
+
+			BBOXMIN, BBOXSIZE, BBOXROT, BBOXLOCALSIZE, 
+
+			REVSIZE, REVSURFACE, REVINSIDE, REVCENTER,	
+			REVCURSOR, REVCOLOR, REVHISTO, REVVOXELS, REVEALEDBY, 
+			OUTSHAPESIZE, OUTHISTOSIZE, OUTVOXELSIZE, OUTDEPTHSIZE, OUTNBDEPTH,
+			BRECT,
+			OUTPUTTEX, SLICETEX, SELECTTEX, INSIDETEX, SURFACETEX, COORDSTEX,
+			REACTTEX, SURFDISTEX,
+			CAMTEX, CAMTEXFIL, CAMXRESO, CAMYRESO, CAMXZFACTOR, CAMYZFACTOR, 
+			CAMFILTER, CAMFLIP, CAMCONTOURTHRESH, 
+			CAMMARKERS, MARKTEX, BACKGROUND,
+			DEPTHTYPE, DEPTHID, OUTPUTCURS, 
+			PATW, PATPOSX, PATPOSY, PATNBX, PATNBY, PATBRIGHT, PATTERNTEX,
+			PATRANGE, PATOFFSET,
+			POSTFILTER, RENDERTEX
+		};
+
+		enum GEOM_ID { 
+			GEOM_BOX, GEOM_SPHERE, GEOM_TUBE, GEOM_CONE, GEOM_FRAME,
+			GEOM_PATH, GEOM_QUAD,
+			GEOM_CAM1280, GEOM_CAM640, GEOM_CAM320,
+			GEOM_MODEL
+		};
+
+		enum VISIBLE_FROM {
+			VISIBLE_FROM_NONE, VISIBLE_FROM_ALL
+		};
+
+	public:
+		static Reveal* getInstance();
+		~Reveal();
+
+		void init();
+		int run();
+		void update();
+		void planOpen(std::string);    
+
+		void initPrograms();
+
+		static void openCallback(Module* mod, const std::string& f) {
+			dynamic_cast<Reveal*>(mod)->open(f);
+		}
+		void open(const std::string& f);
+		static void saveCallback(Module* mod, const std::string& f) {
+			dynamic_cast<Reveal*>(mod)->save(f);
+		}
+		void save(const std::string& f);
+		static void quitCallback(Module* mod) {
+			dynamic_cast<Reveal*>(mod)->askQuit();
+		}
+		void askQuit();
+		void quit();
+
+		static void ressourcesCallback(Module* mod, const std::string& f) {
+			dynamic_cast<Reveal*>(mod)->setRessourcesFolder(f);
+		}
+		void setRessourcesFolder(const std::string& f);
+		static void uploadCallback(Module* mod, 
+								   const std::vector<std::string>& vf
+								   ) {
+			dynamic_cast<Reveal*>(mod)->uploadRessource(vf);
+		}
+		void uploadRessource(const std::vector<std::string>& vf);
+		static void debugOscCallback(Module* mod, 
+								   const std::vector<bool>& vf
+								   ) {
+			dynamic_cast<Reveal*>(mod)->debugOSC(vf[0]);
+		}
+		void debugOSC(const bool& deb){m_debugOSC=deb;}
+		const bool& getDebugOSC() {return m_debugOSC;}
+
+		virtual void load(xmlNodePtr);
+
+		void addUpdateObserver(Module* upObs);
+		void removeUpdateObserver(Module* upObs);
+
+		void refreshModules();
+		Module* createModule(const std::string& typeStr);
+		Module* findModule(const std::string& fullName);
+		Attribute* findAttribute(const std::string& fullName);
+
+		int getVisibilityMask(const std::string& visibleFrom);
+
+		Listener* createListener(const std::string& typeStr);
+
+		inline SpacesModule* getSpaces(){return m_spaces;}
+	
+		//Revealed modules
+		void registerRevealed(RevealedModule*);
+		void unregisterRevealed(RevealedModule*);
+		RevealedModule* getRevealedModule(const unsigned int& s) { 
+			if(m_revealedMap.find(s)!=m_revealedMap.end()) {
+				return m_revealedMap[s];
+			}
+			return NULL;
+		}
+		unsigned int getNbRevealed(){return m_revealedVec.size();}
+		inline const int& getMaxNbRevealed(){return m_maxNbRevealed;}
+		void updateRevealed();
+
+		void registerOutputRevealed(RevealedModule* rev);
+		void unregisterOutputRevealed(RevealedModule* rev);
+		inline std::vector<RevealedModule*>& editRegisteredOutputRevealed() {
+			return m_registeredOutputRevealed;
+		}
+		void updateOutputRevealed();
+
+		inline const int& getMaxNbDepthCams(){return m_maxNbDepthCams;}
+		void registerOutputDepthCam(DepthCamModule* cam);
+		void unregisterOutputDepthCam(DepthCamModule* cam);
+		inline std::vector<DepthCamModule*>& editRegisteredOutputDepthCams() {
+			return m_registeredOutputDepthCams;
+		}
+
+		//removing things
+		void deleteListener(Listener*);
+		void deleteModule(Module*);
+
+		//Geometries
+		const std::vector<Geometry*>& getGeoms(){return m_geoms;}
+		Geometry* getGeom(const GEOM_ID& geomStr) { 
+			return m_geomsMap[geomStr];
+		}
+		void registerGeom(Geometry* geom);
+		void unregisterGeom(Geometry* geom);
+
+		void addModuleListObserver(ModuleListObserver* obs);
+		void removeModuleListObserver(ModuleListObserver* obs);
+
+		void addContextHandler(ContextHandler* cont);
+		void removeContextHandler(ContextHandler* cont);
+		inline ContextHandler* getContextHandler(const int& id) {
+			return m_contextHandlers[id];
+		}
+
+		GLuint createProgram(const char* vertSource, const char* fragSource);
+
+		GLFWwindow* getPreviewWindow();
+
+		void measureStart();
+		void measureStore(const int& nbPixels);
+		const std::string& getCurrentFile(){return m_currentFile;}
+
+	private:
+		Reveal();
+		void testDelete();
+
+	private:
+		SpacesModule* m_spaces;
+		RootSceneGroupModule* m_scene;
+		PreviewModule* m_preview;
+		OutputManagerModule* m_output;
+		bool m_debugOSC;
+
+		int m_openPlanned;
+		std::string m_openPlannedName;
+		std::string m_currentFile;
+
+		std::map<std::string, Module*> m_typesMap;
+
+		std::vector<Module*> m_updateObservers;
+		unsigned int m_upObsIdCounter;
+		timeval m_prevTime;
+
+		std::map<std::string, Module*> m_modulesMap;
+		std::map<std::string, Attribute*> m_fullAttributesMap;
+		std::map<unsigned int, ModuleListObserver*> m_moduleListObservers;
+
+		std::map<GEOM_ID, Geometry*> m_geomsMap;
+		std::vector<Geometry*> m_geoms;
+
+		std::map<std::string, int> m_visibleFromMap;
+		std::vector<std::string> m_visibleFromVec;
+
+		int m_contextHandlersCounter;
+		std::map<unsigned int, ContextHandler*> m_contextHandlers;
+
+		std::vector<RevealedModule*> m_revealedVec;
+		std::map<unsigned int, RevealedModule*> m_revealedMap;
+		int m_maxNbRevealed;
+		std::vector<RevealedModule*> m_registeredOutputRevealed;
+		int m_maxNbDepthCams;
+		std::vector<DepthCamModule*> m_registeredOutputDepthCams;
+		std::vector<Listener*> m_listenersDeleteVec;
+		std::vector<Attribute*> m_attributesDeleteVec;
+		std::vector<Module*> m_modulesDeleteVec;
+
+
+		timeval m_measureTime;
+		bool m_measuring;
+		std::map<int, int> m_measurePixelTimes;
+		std::map<int, int> m_measurePixelNb;
+};
+
+class ModuleListObserver {
+	public:
+		virtual ~ModuleListObserver(){}
+		virtual void updateModulesList(const std::map<std::string, Module*>&)=0;
+		void setModuleListObsID(const unsigned int& id){m_moduleListObsID=id;}
+		const unsigned int& getModuleListObsID(){return m_moduleListObsID;}
+
+	protected:
+		unsigned int m_moduleListObsID;
+
+};
+
+#endif
+
diff --git a/src/audio/AudioManager.hpp b/src/audio/AudioManager.hpp
new file mode 100644
index 0000000..ead8896
--- /dev/null
+++ b/src/audio/AudioManager.hpp
@@ -0,0 +1,41 @@
+/***************************************************************************
+ *	AudioManager.hpp
+ *	Part of Revil
+ *	2015-  Florent Berthaut
+ *	hitmuri.net
+ ****************************************************************************/
+/*
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <portaudio.h>
+
+
+#ifndef OscManager_h
+#define OscManager_h
+
+class AudioManager {
+	public:
+		static AudioManager* getInstance();
+		~AudioManager();
+
+
+	private:
+		AudioManager(){}
+
+}
+
+#endif
+
diff --git a/src/geoms/BoxGeometry.cpp b/src/geoms/BoxGeometry.cpp
new file mode 100644
index 0000000..fd56f5a
--- /dev/null
+++ b/src/geoms/BoxGeometry.cpp
@@ -0,0 +1,116 @@
+/***************************************************************************
+ *  BoxGeometry.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "BoxGeometry.hpp"
+
+using namespace std;
+
+BoxGeometry::BoxGeometry(): Geometry() {
+    m_vertexBufferData.push_back(-0.5);
+        m_vertexBufferData.push_back(-0.5);
+            m_vertexBufferData.push_back(0.5);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(0.5);
+        m_vertexBufferData.push_back(-0.5);
+            m_vertexBufferData.push_back(0.5);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(0.5);
+        m_vertexBufferData.push_back(0.5);
+            m_vertexBufferData.push_back(0.5);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(-0.5);
+        m_vertexBufferData.push_back(0.5);
+            m_vertexBufferData.push_back(0.5);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(-0.5);
+        m_vertexBufferData.push_back(-0.5);
+            m_vertexBufferData.push_back(-0.5);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(0.5);
+        m_vertexBufferData.push_back(-0.5);
+            m_vertexBufferData.push_back(-0.5);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(0.5);
+        m_vertexBufferData.push_back(0.5);
+            m_vertexBufferData.push_back(-0.5);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(-0.5);
+        m_vertexBufferData.push_back(0.5);
+            m_vertexBufferData.push_back(-0.5);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+
+    //front
+    m_indexBufferData.push_back(0);
+        m_indexBufferData.push_back(2);
+            m_indexBufferData.push_back(3);
+    m_indexBufferData.push_back(0);
+        m_indexBufferData.push_back(1);
+            m_indexBufferData.push_back(2);
+    //right
+    m_indexBufferData.push_back(1);
+        m_indexBufferData.push_back(5);
+            m_indexBufferData.push_back(6);
+    m_indexBufferData.push_back(1);
+        m_indexBufferData.push_back(6);
+            m_indexBufferData.push_back(2);
+    //back
+    m_indexBufferData.push_back(4);
+        m_indexBufferData.push_back(7);
+            m_indexBufferData.push_back(6);
+    m_indexBufferData.push_back(4);
+        m_indexBufferData.push_back(6);
+            m_indexBufferData.push_back(5);
+    //left
+    m_indexBufferData.push_back(7);
+        m_indexBufferData.push_back(4);
+            m_indexBufferData.push_back(0);
+    m_indexBufferData.push_back(7);
+        m_indexBufferData.push_back(0);
+            m_indexBufferData.push_back(3);
+    //top
+    m_indexBufferData.push_back(3);
+        m_indexBufferData.push_back(2);
+            m_indexBufferData.push_back(6);
+    m_indexBufferData.push_back(3);
+        m_indexBufferData.push_back(6);
+            m_indexBufferData.push_back(7);
+    //bottom
+    m_indexBufferData.push_back(0);
+        m_indexBufferData.push_back(5);
+            m_indexBufferData.push_back(1);
+    m_indexBufferData.push_back(0);
+        m_indexBufferData.push_back(4);
+            m_indexBufferData.push_back(5);
+
+    m_compoSizes.push_back(m_indexBufferData.size());
+}
+
+BoxGeometry::~BoxGeometry() {}
+
diff --git a/src/geoms/BoxGeometry.hpp b/src/geoms/BoxGeometry.hpp
new file mode 100644
index 0000000..423d487
--- /dev/null
+++ b/src/geoms/BoxGeometry.hpp
@@ -0,0 +1,38 @@
+/***************************************************************************
+ *  BoxGeometry.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef BoxGeometry_h
+#define BoxGeometry_h
+
+#include "Geometry.hpp"
+
+class BoxGeometry : public Geometry {
+    public:
+        BoxGeometry();
+        virtual ~BoxGeometry();
+
+    protected:
+
+};
+
+#endif
diff --git a/src/geoms/CamGeometry.cpp b/src/geoms/CamGeometry.cpp
new file mode 100644
index 0000000..2c18101
--- /dev/null
+++ b/src/geoms/CamGeometry.cpp
@@ -0,0 +1,70 @@
+/***************************************************************************
+ *  CamGeometry.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "CamGeometry.hpp"
+
+using namespace std;
+
+CamGeometry::CamGeometry(const int& width, const int& height): Geometry() {
+    m_points=false;
+    setSize(width, height);
+}
+
+CamGeometry::~CamGeometry() {}
+
+void CamGeometry::setSize(const int& width, const int& height) {
+    m_vertexBufferData.clear();
+    m_indexBufferData.clear();
+    m_compoSizes.clear();
+
+    for(int r=0; r<height; r++) {
+        for(int c=0; c<width; c++) {
+            m_vertexBufferData.push_back(GLfloat(c));
+            m_vertexBufferData.push_back(GLfloat(r));
+            m_vertexBufferData.push_back(10.0);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+        }
+    }
+    for(int r=0; r<height-1; r++) {
+        for(int c=0; c<width-1; c++) {
+            if(m_points) {
+                m_indexBufferData.push_back(width*r+c);
+            }
+            else {
+                m_indexBufferData.push_back(width*r+c);
+                m_indexBufferData.push_back(width*(r)+c+1);
+                m_indexBufferData.push_back(width*(r+1)+c);
+
+                m_indexBufferData.push_back(width*(r+1)+c+1);
+                m_indexBufferData.push_back(width*(r+1)+c);
+                m_indexBufferData.push_back(width*(r)+c+1);
+            }
+        }
+    }
+
+    m_compoSizes.push_back(m_indexBufferData.size());
+	for(auto& cont : m_contexts) {
+		cont.second.m_refresh=true;
+	}
+}
+
diff --git a/src/geoms/CamGeometry.hpp b/src/geoms/CamGeometry.hpp
new file mode 100644
index 0000000..aaa89c4
--- /dev/null
+++ b/src/geoms/CamGeometry.hpp
@@ -0,0 +1,40 @@
+/***************************************************************************
+ *  CamGeometry.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef CamGeometry_h
+#define CamGeometry_h
+
+#include "Geometry.hpp"
+
+class CamGeometry : public Geometry {
+    public:
+        CamGeometry(const int& width, const int& height);
+        virtual ~CamGeometry();
+
+        void setSize(const int & width, const int& height);
+
+    protected:
+
+};
+
+#endif
diff --git a/src/geoms/ConeGeometry.cpp b/src/geoms/ConeGeometry.cpp
new file mode 100644
index 0000000..cc521b9
--- /dev/null
+++ b/src/geoms/ConeGeometry.cpp
@@ -0,0 +1,71 @@
+/***************************************************************************
+ *  ConeGeometry.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ConeGeometry.hpp"
+
+using namespace std;
+
+ConeGeometry::ConeGeometry(): Geometry() {
+
+    int nbEdges=10;
+    int length=1;
+
+    //add the vertices 
+    m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(0.5);
+    m_vertexBufferData.push_back(0);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    float angle=0;
+    float angleStep=M_PI*2.0/float(nbEdges);
+    for(int v=0; v<nbEdges; ++v, angle+=angleStep) {
+        glm::vec4 pnt = glm::vec4(cos(angle)*length/2.0, 
+                                  -0.5,
+                                  sin(angle)*length/2.0, 
+                                  1);
+        m_vertexBufferData.push_back(pnt[0]);
+        m_vertexBufferData.push_back(pnt[1]);
+        m_vertexBufferData.push_back(pnt[2]);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    }
+
+    //indices
+    //  sides
+    for(int v=1; v<nbEdges+1; ++v) {
+        m_indexBufferData.push_back(0);
+        m_indexBufferData.push_back((v+1<nbEdges+1)?v+1:1);
+        m_indexBufferData.push_back(v);
+    }
+    //  bottom
+    for(int v=2; v<nbEdges; ++v) {
+        m_indexBufferData.push_back(1);
+        m_indexBufferData.push_back(v);
+        m_indexBufferData.push_back(v+1);
+    }
+
+
+    m_compoSizes.push_back(m_indexBufferData.size());
+}
+
+ConeGeometry::~ConeGeometry() {}
+
diff --git a/src/geoms/ConeGeometry.hpp b/src/geoms/ConeGeometry.hpp
new file mode 100644
index 0000000..f95358f
--- /dev/null
+++ b/src/geoms/ConeGeometry.hpp
@@ -0,0 +1,38 @@
+/***************************************************************************
+ *  ConeGeometry.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef ConeGeometry_h
+#define ConeGeometry_h
+
+#include "Geometry.hpp"
+
+class ConeGeometry : public Geometry {
+    public:
+        ConeGeometry();
+        virtual ~ConeGeometry();
+
+    protected:
+
+};
+
+#endif
diff --git a/src/geoms/FrameGeometry.cpp b/src/geoms/FrameGeometry.cpp
new file mode 100644
index 0000000..363becf
--- /dev/null
+++ b/src/geoms/FrameGeometry.cpp
@@ -0,0 +1,131 @@
+/***************************************************************************
+ *  FrameGeometry.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "FrameGeometry.hpp"
+
+using namespace std;
+
+FrameGeometry::FrameGeometry(): Geometry() {
+
+    float inter=0.4;
+    for(float x=0; x<2; ++x) {
+        m_vertexBufferData.push_back(0.1*(x-0.5));
+            m_vertexBufferData.push_back(0);
+                m_vertexBufferData.push_back(0.5);
+					m_vertexBufferData.push_back(0);
+						m_vertexBufferData.push_back(0);
+        m_vertexBufferData.push_back(inter*2*(x-0.5));
+            m_vertexBufferData.push_back(inter);
+                m_vertexBufferData.push_back(0.45);
+					m_vertexBufferData.push_back(0);
+						m_vertexBufferData.push_back(0);
+        m_vertexBufferData.push_back(-0.5+x);
+            m_vertexBufferData.push_back(0.5);
+                m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+						m_vertexBufferData.push_back(0);
+        m_vertexBufferData.push_back(inter*2*(x-0.5));
+            m_vertexBufferData.push_back(inter);
+                m_vertexBufferData.push_back(-0.45);
+					m_vertexBufferData.push_back(0);
+						m_vertexBufferData.push_back(0);
+
+        m_vertexBufferData.push_back(0.1*(x-0.5));
+            m_vertexBufferData.push_back(0);
+                m_vertexBufferData.push_back(-0.5);
+					m_vertexBufferData.push_back(0);
+						m_vertexBufferData.push_back(0);
+        m_vertexBufferData.push_back(inter*2*(x-0.5));
+            m_vertexBufferData.push_back(-inter);
+                m_vertexBufferData.push_back(-0.45);
+					m_vertexBufferData.push_back(0);
+						m_vertexBufferData.push_back(0);
+        m_vertexBufferData.push_back(-0.5+x);
+            m_vertexBufferData.push_back(-0.5);
+                m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+						m_vertexBufferData.push_back(0);
+        m_vertexBufferData.push_back(inter*2*(x-0.5));
+            m_vertexBufferData.push_back(-inter);
+                m_vertexBufferData.push_back(0.45);
+					m_vertexBufferData.push_back(0);
+						m_vertexBufferData.push_back(0);
+    }
+
+    //around faces
+    for(int v=0; v<8; v++) {
+        if(v<7) {
+            m_indexBufferData.push_back(v%16);
+                m_indexBufferData.push_back((v+9)%16);
+                    m_indexBufferData.push_back((v+1)%16);
+        }
+        m_indexBufferData.push_back(v%16);
+            m_indexBufferData.push_back((v+8)%16);
+                m_indexBufferData.push_back((v+9)%16);
+    }
+
+    m_indexBufferData.push_back(15);
+            m_indexBufferData.push_back(8);
+        m_indexBufferData.push_back(0);
+
+
+    //extremities
+    m_indexBufferData.push_back(0);
+        m_indexBufferData.push_back(1);
+            m_indexBufferData.push_back(7);
+    m_indexBufferData.push_back(8);
+        m_indexBufferData.push_back(15);
+            m_indexBufferData.push_back(9);
+
+    m_indexBufferData.push_back(12);
+        m_indexBufferData.push_back(11);
+            m_indexBufferData.push_back(13);
+    m_indexBufferData.push_back(4);
+        m_indexBufferData.push_back(5);
+            m_indexBufferData.push_back(3);
+
+
+    //sides faces
+    for(int x=0; x<2; x++) {
+        m_indexBufferData.push_back(2+x*8);
+            m_indexBufferData.push_back((x==0)?7:1+x*8);
+                m_indexBufferData.push_back((x==0)?1:7+x*8);
+
+        m_indexBufferData.push_back(2+x*8);
+            m_indexBufferData.push_back((x==0)?6:7+x*8);
+                m_indexBufferData.push_back((x==0)?7:6+x*8);
+
+        m_indexBufferData.push_back(2+x*8);
+            m_indexBufferData.push_back((x==0)?5:6+x*8);
+                m_indexBufferData.push_back((x==0)?6:5+x*8);
+
+        m_indexBufferData.push_back(2+x*8);
+            m_indexBufferData.push_back((x==0)?3:5+x*8);
+                m_indexBufferData.push_back((x==0)?5:3+x*8);
+    }
+
+
+    m_compoSizes.push_back(m_indexBufferData.size());
+}
+
+FrameGeometry::~FrameGeometry() {}
+
diff --git a/src/geoms/FrameGeometry.hpp b/src/geoms/FrameGeometry.hpp
new file mode 100644
index 0000000..7902713
--- /dev/null
+++ b/src/geoms/FrameGeometry.hpp
@@ -0,0 +1,38 @@
+/***************************************************************************
+ *  FrameGeometry.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef FrameGeometry_h
+#define FrameGeometry_h
+
+#include "Geometry.hpp"
+
+class FrameGeometry : public Geometry {
+    public:
+        FrameGeometry();
+        virtual ~FrameGeometry();
+
+    protected:
+
+};
+
+#endif
diff --git a/src/geoms/Geometry.cpp b/src/geoms/Geometry.cpp
new file mode 100644
index 0000000..47a3841
--- /dev/null
+++ b/src/geoms/Geometry.cpp
@@ -0,0 +1,168 @@
+/***************************************************************************
+ *  Geometry.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "Geometry.hpp"
+#include <iostream>
+
+using namespace std;
+
+Geometry::Geometry():m_hasTexCoords(false), m_points(false) {
+    m_geomID=(Reveal::GEOM_ID)-1;
+}
+
+Geometry::~Geometry() {}
+
+void Geometry::draw(const int& contextID,
+                    const Reveal::REVIL_PROGRAM& prog, 
+                    map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                    const int& visibilityMask) {
+
+    if(m_contexts.find(contextID)==m_contexts.end()) {
+        ContextGeometry& cont = m_contexts[contextID];
+        cont.m_refresh=true;
+        glGenVertexArrays(1, &cont.m_vertexArrayID);
+        glBindVertexArray(cont.m_vertexArrayID); 
+        glGenBuffers(1, &cont.m_vertexBuffer);
+        glGenBuffers(1, &cont.m_indexBuffer);
+    }
+    if(m_contexts[contextID].m_refresh) {
+        ContextGeometry& cont = m_contexts[contextID];
+        glBindBuffer(GL_ARRAY_BUFFER, cont.m_vertexBuffer);
+        glBufferData(GL_ARRAY_BUFFER, 
+                     m_vertexBufferData.size()*sizeof(GLfloat),
+                     &m_vertexBufferData[0], GL_STATIC_DRAW);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cont.m_indexBuffer);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 
+                     m_indexBufferData.size()*sizeof(GLuint), 
+                     &m_indexBufferData[0], GL_STATIC_DRAW);
+        cont.m_refresh=false;
+    }
+
+    ContextGeometry& cont = m_contexts[contextID];
+
+    //load vertices
+    GLintptr posOff = 0;
+    GLintptr texOff = 3*sizeof(float);
+    GLsizei stride = 0;
+    glBindVertexArray(cont.m_vertexArrayID); 
+    glBindBuffer(GL_ARRAY_BUFFER, cont.m_vertexBuffer);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cont.m_indexBuffer);
+
+    glEnableVertexAttribArray(0);
+	stride= 5*sizeof(float);
+	glEnableVertexAttribArray(1);
+	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride,(GLvoid*)texOff);
+    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)posOff);
+
+    //draw geomodules attached to that geometry 
+    vector<GeomModule*>::const_iterator itGeom=m_modules.begin();
+    for(; itGeom!=m_modules.end(); ++itGeom) {
+        if((*itGeom)->isVisible() 
+                && (((*itGeom)->getVisibilityMask() & visibilityMask)
+                    || prog==Reveal::PREVIEWPROG )) {
+            //for each component
+            unsigned int start=0;
+            for(unsigned int c=0; c<m_compoSizes.size(); ++c) {
+                //load uniforms and model mat
+                (*itGeom)->draw(contextID, prog, uniforms, c);
+                //draw triangles
+                if(m_points) {
+                    glDrawElements(GL_POINTS, m_compoSizes[c], 
+                           GL_UNSIGNED_INT,(GLvoid*)(start*sizeof(GLuint)));
+                }
+                else {
+                    glDrawElements(GL_TRIANGLES, m_compoSizes[c], 
+                           GL_UNSIGNED_INT,(GLvoid*)(start*sizeof(GLuint)));
+                }
+                start+=m_compoSizes[c];
+            }
+        }
+    }
+    glDisableVertexAttribArray(0);
+	glDisableVertexAttribArray(1);
+}
+
+void Geometry::drawDirect(const int& contextID) {
+    if(m_contexts.find(contextID)==m_contexts.end()) {
+        ContextGeometry& cont = m_contexts[contextID];
+        glGenVertexArrays(1, &cont.m_vertexArrayID);
+        glBindVertexArray(cont.m_vertexArrayID); 
+        glGenBuffers(1, &cont.m_vertexBuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, cont.m_vertexBuffer);
+        glBufferData(GL_ARRAY_BUFFER, 
+                     m_vertexBufferData.size()*sizeof(GLfloat),
+                     &m_vertexBufferData[0], GL_STATIC_DRAW);
+        glGenBuffers(1, &cont.m_indexBuffer);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cont.m_indexBuffer);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, 
+                     m_indexBufferData.size()*sizeof(GLuint), 
+                     &m_indexBufferData[0], GL_STATIC_DRAW);
+    }
+
+    ContextGeometry& cont = m_contexts[contextID];
+
+    //load vertices
+    glBindBuffer(GL_ARRAY_BUFFER, cont.m_vertexBuffer);
+    glEnableVertexAttribArray(0);
+    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)0);
+	glEnableVertexAttribArray(1);
+	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float),(void*)(3*sizeof(float)));
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cont.m_indexBuffer);
+
+    //draw triangles
+    glDrawElements(GL_TRIANGLES, m_indexBufferData.size(), 
+                   GL_UNSIGNED_INT, 0);
+
+    glDisableVertexAttribArray(0);
+	glDisableVertexAttribArray(1);
+}
+
+void Geometry::registerModule(GeomModule* geom) {
+    unsigned int id=0;
+    while(m_modulesMap.find(id)!=m_modulesMap.end()) {
+        id++;
+    }
+    geom->setGeomID(id);
+    m_modulesMap[id]=geom;
+    m_modules.push_back(geom);
+}
+
+void Geometry::unregisterModule(GeomModule* geom) {
+    m_modulesMap.erase(geom->getGeomID());
+    vector<GeomModule*>::iterator itGeom=m_modules.begin();
+    for(; itGeom!=m_modules.end();) {
+        if((*itGeom)->getGeomID()==geom->getGeomID()) {
+            itGeom=m_modules.erase(itGeom);
+        }
+        else {
+             ++itGeom;
+        }
+    }
+}
+
+void Geometry::refresh() {
+    map<int, ContextGeometry>::iterator itCo=m_contexts.begin();
+    for(; itCo!=m_contexts.end(); ++itCo) {
+        itCo->second.m_refresh=true;
+    }
+}
+
diff --git a/src/geoms/Geometry.hpp b/src/geoms/Geometry.hpp
new file mode 100644
index 0000000..4b52904
--- /dev/null
+++ b/src/geoms/Geometry.hpp
@@ -0,0 +1,80 @@
+/***************************************************************************
+ *  Geometry.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef Geometry_h
+#define Geometry_h
+
+#include <glm/vec3.hpp>
+#include <map>
+#include <vector>
+
+#include "../modules/GeomModule.hpp"
+#include "../Reveal.hpp"
+
+struct ContextGeometry {
+    GLuint m_vertexBuffer;
+    GLuint m_vertexArrayID;
+    GLuint m_indexBuffer;
+    bool m_refresh;
+};
+
+class Geometry {
+    public:
+        Geometry();
+        virtual ~Geometry();
+        virtual void draw(const int& contextID,
+                          const Reveal::REVIL_PROGRAM&, 
+                          std::map<Reveal::REVIL_UNIFORM, GLint>&,
+                          const int& visibilityMask);
+        virtual void drawDirect(const int& contextID);
+        
+        void registerModule(GeomModule*);
+        void unregisterModule(GeomModule*);
+        inline const std::vector<GeomModule*>& getModules(){return m_modules;}
+
+        inline void setGeomID(const Reveal::GEOM_ID& id) {m_geomID=id;}
+        inline const Reveal::GEOM_ID& getGeomID() {return m_geomID;}
+
+        std::vector<GLfloat>& editVertexBufferData(){return m_vertexBufferData;}
+        std::vector<GLuint>& editIndexBufferData(){return m_indexBufferData;}
+        std::vector<int>& editCompoSizes(){return m_compoSizes;}
+        void refresh();
+
+        void hasTexCoords(bool tc){m_hasTexCoords=tc;}
+
+    protected:
+        Reveal::GEOM_ID m_geomID;
+        bool m_hasTexCoords;
+        bool m_points;
+
+        std::vector<GeomModule*> m_modules;
+        std::map<unsigned int, GeomModule*> m_modulesMap;
+
+        std::vector<GLfloat> m_vertexBufferData;
+        std::vector<GLuint> m_indexBufferData;
+        std::vector<int> m_compoSizes;
+
+        std::map<int, ContextGeometry> m_contexts;
+};
+
+#endif
diff --git a/src/geoms/QuadGeometry.cpp b/src/geoms/QuadGeometry.cpp
new file mode 100644
index 0000000..469888a
--- /dev/null
+++ b/src/geoms/QuadGeometry.cpp
@@ -0,0 +1,60 @@
+/***************************************************************************
+ *  QuadGeometry.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "QuadGeometry.hpp"
+
+using namespace std;
+
+QuadGeometry::QuadGeometry(): Geometry() {
+    m_vertexBufferData.push_back(-1);
+        m_vertexBufferData.push_back(-1);
+            m_vertexBufferData.push_back(0);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(1);
+        m_vertexBufferData.push_back(-1);
+            m_vertexBufferData.push_back(0);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(1);
+        m_vertexBufferData.push_back(1);
+            m_vertexBufferData.push_back(0);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    m_vertexBufferData.push_back(-1);
+        m_vertexBufferData.push_back(1);
+            m_vertexBufferData.push_back(0);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+
+    m_indexBufferData.push_back(0);
+    m_indexBufferData.push_back(2);
+    m_indexBufferData.push_back(3);
+    m_indexBufferData.push_back(0);
+    m_indexBufferData.push_back(1);
+    m_indexBufferData.push_back(2);
+
+    m_compoSizes.push_back(m_indexBufferData.size());
+}
+
+QuadGeometry::~QuadGeometry() {}
+
diff --git a/src/geoms/QuadGeometry.hpp b/src/geoms/QuadGeometry.hpp
new file mode 100644
index 0000000..3820bbc
--- /dev/null
+++ b/src/geoms/QuadGeometry.hpp
@@ -0,0 +1,38 @@
+/***************************************************************************
+ *  QuadGeometry.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef QuadGeometry_h
+#define QuadGeometry_h
+
+#include "Geometry.hpp"
+
+class QuadGeometry : public Geometry {
+    public:
+        QuadGeometry();
+        virtual ~QuadGeometry();
+
+    protected:
+
+};
+
+#endif
diff --git a/src/geoms/SphereGeometry.cpp b/src/geoms/SphereGeometry.cpp
new file mode 100644
index 0000000..c38804d
--- /dev/null
+++ b/src/geoms/SphereGeometry.cpp
@@ -0,0 +1,84 @@
+/***************************************************************************
+ *  SphereGeometry.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "SphereGeometry.hpp"
+
+using namespace std;
+
+SphereGeometry::SphereGeometry(): Geometry() {
+    int nbHor=20;
+    int nbVert=10;
+    float rad=0.5;
+    float stepH = (M_PI*2.0/float(nbHor));
+    float stepV = (M_PI/float(nbVert));
+
+    //top vertex
+    m_vertexBufferData.push_back(0);
+        m_vertexBufferData.push_back(rad);
+            m_vertexBufferData.push_back(0);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+    //bottom vertex
+    m_vertexBufferData.push_back(0);
+        m_vertexBufferData.push_back(-rad);
+            m_vertexBufferData.push_back(0);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+
+    //other vertices and indices
+    for(int v=1; v<nbVert+1; ++v) {
+        float posY = rad*cos(float(v)*stepV);
+        float out = abs(rad * sin(float(v)*stepV));
+        for(int h=0; h<nbHor; ++h) {
+            float angleH = float(h)*stepH;
+            m_vertexBufferData.push_back(out*cos(angleH));
+            m_vertexBufferData.push_back(posY);
+            m_vertexBufferData.push_back(out*sin(angleH));
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+
+            if(v==nbVert) { //bottom row
+                m_indexBufferData.push_back(2+(v-1)*nbHor+h);
+                m_indexBufferData.push_back(2+(v-1)*nbHor+(h+1)%nbHor);
+                m_indexBufferData.push_back(1);
+            }
+            else {//other rows (2 triangles)
+                if(v==1) { //top row
+                    m_indexBufferData.push_back(0);
+                    m_indexBufferData.push_back(2+(v-1)*nbHor+(h+1)%nbHor);
+                    m_indexBufferData.push_back(2+(v-1)*nbHor+h);
+                }
+                m_indexBufferData.push_back(2+(v-1)*nbHor+h);
+                m_indexBufferData.push_back(2+(v-1)*nbHor+(h+1)%nbHor);
+                m_indexBufferData.push_back(2+(v)*nbHor+(h+1)%nbHor);
+
+                m_indexBufferData.push_back(2+(v-1)*nbHor+h);
+                m_indexBufferData.push_back(2+(v)*nbHor+(h+1)%nbHor);
+                m_indexBufferData.push_back(2+(v)*nbHor+h);
+            }
+        }
+    }
+    m_compoSizes.push_back(m_indexBufferData.size());
+}
+
+SphereGeometry::~SphereGeometry() {}
+
diff --git a/src/geoms/SphereGeometry.hpp b/src/geoms/SphereGeometry.hpp
new file mode 100644
index 0000000..1d2c9ec
--- /dev/null
+++ b/src/geoms/SphereGeometry.hpp
@@ -0,0 +1,38 @@
+/***************************************************************************
+ *  SphereGeometry.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef SphereGeometry_h
+#define SphereGeometry_h
+
+#include "Geometry.hpp"
+
+class SphereGeometry : public Geometry {
+    public:
+        SphereGeometry();
+        virtual ~SphereGeometry();
+
+    protected:
+
+};
+
+#endif
diff --git a/src/geoms/TubeGeometry.cpp b/src/geoms/TubeGeometry.cpp
new file mode 100644
index 0000000..4e34cec
--- /dev/null
+++ b/src/geoms/TubeGeometry.cpp
@@ -0,0 +1,73 @@
+/***************************************************************************
+ *  TubeGeometry.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "TubeGeometry.hpp"
+
+using namespace std;
+
+TubeGeometry::TubeGeometry(): Geometry() {
+
+    int nbEdges=10;
+    int length=1;
+
+    //add the vertices
+    float angle=0;
+    float angleStep=M_PI*2.0/float(nbEdges);
+    for(int p=0; p<2; ++p) {
+        for(int v=0; v<nbEdges; ++v, angle+=angleStep) {
+            glm::vec4 pnt = glm::vec4(cos(angle)*length/2.0, 
+                                      p*length-length/2.0,
+                                      sin(angle)*length/2.0, 
+                                      1);
+            m_vertexBufferData.push_back(pnt[0]);
+            m_vertexBufferData.push_back(pnt[1]);
+            m_vertexBufferData.push_back(pnt[2]);
+				m_vertexBufferData.push_back(0);
+					m_vertexBufferData.push_back(0);
+        }
+    }
+
+    for(int v=0; v<nbEdges-2; ++v) {
+        m_indexBufferData.push_back(v);
+        m_indexBufferData.push_back(v+1);
+        m_indexBufferData.push_back(nbEdges-1);
+    }
+    for(int v=0; v<nbEdges; ++v) {
+        m_indexBufferData.push_back(v);
+        m_indexBufferData.push_back(nbEdges+v);
+        m_indexBufferData.push_back((v+1)%nbEdges);
+
+        m_indexBufferData.push_back(nbEdges+v);
+        m_indexBufferData.push_back(nbEdges+(v+1)%nbEdges);
+        m_indexBufferData.push_back((v+1)%nbEdges);
+    }
+    for(int v=0; v<nbEdges-2; ++v) {
+        m_indexBufferData.push_back(nbEdges+v);
+        m_indexBufferData.push_back(nbEdges+nbEdges-1);
+        m_indexBufferData.push_back(nbEdges+v+1);
+    }
+
+    m_compoSizes.push_back(m_indexBufferData.size());
+}
+
+TubeGeometry::~TubeGeometry() {}
+
diff --git a/src/geoms/TubeGeometry.hpp b/src/geoms/TubeGeometry.hpp
new file mode 100644
index 0000000..ca76894
--- /dev/null
+++ b/src/geoms/TubeGeometry.hpp
@@ -0,0 +1,38 @@
+/***************************************************************************
+ *  TubeGeometry.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef TubeGeometry_h
+#define TubeGeometry_h
+
+#include "Geometry.hpp"
+
+class TubeGeometry : public Geometry {
+    public:
+        TubeGeometry();
+        virtual ~TubeGeometry();
+
+    protected:
+
+};
+
+#endif
diff --git a/src/gui/AttributeWidget.cpp b/src/gui/AttributeWidget.cpp
new file mode 100644
index 0000000..c942390
--- /dev/null
+++ b/src/gui/AttributeWidget.cpp
@@ -0,0 +1,517 @@
+/***************************************************************************
+ *  AttributeWidget.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "AttributeWidget.hpp"
+#include <iostream>
+#include <FL/fl_draw.H>
+#include <FL/Fl.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Native_File_Chooser.H>
+#include <FL/filename.H>
+
+#include "../Reveal.hpp"
+#include "MainWindow.hpp"
+#include "ListenerWidget.hpp"
+#include "GuiListener.hpp"
+
+using namespace std;
+
+AttributeWidget::AttributeWidget(int x, int y, 
+                                 int w, int h, 
+                                 Attribute* attribute):Fl_Group(x,y,w,h,""),
+                                                       m_attribute(attribute) {
+    m_name = m_attribute->getName();
+    m_fullName = m_attribute->getFullName();
+    m_nbValues = m_attribute->getNbValues();
+    label(m_name.c_str());
+    align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+    color(FL_SELECTION_COLOR);
+    box(FL_BORDER_BOX);
+    end();
+
+
+    int margin=5;
+    //add widgets depending on type
+	if(m_nbValues<=4) {
+		switch(m_attribute->getType()) {
+        case Attribute::FLOAT_ATTRIBUTE :
+        case Attribute::ACTION_FLOAT_ATTRIBUTE : {
+            int inpWidth=50;
+            int pos=fl_width(m_name.c_str())+margin*2;
+            if(m_attribute->getType()==Attribute::ACTION_FLOAT_ATTRIBUTE) {
+                label("");
+                m_button = new Fl_Button(x+margin*2, y+margin, 
+                                         pos, h-2*margin, 
+                                         m_name.c_str());
+                pos+=margin*4;
+                m_button->callback(statAction, this);
+                m_button->box(FL_FLAT_BOX);
+                if(m_attribute->getAccessibility()==Attribute::OUTPUT) {
+                    m_button->deactivate();
+                }
+                add(m_button);
+            }
+            for(unsigned int v=0; v<m_nbValues; ++v) {
+                Fl_Value_Input* adj = new Fl_Value_Input(
+                                                x+pos+(inpWidth+margin)*v,
+                                                y+margin, inpWidth, h-2*margin, 
+                                                "");
+                adj->step(0.1);
+                adj->bounds(-10000, 10000);
+                if(m_attribute->getType()==Attribute::FLOAT_ATTRIBUTE) {
+                    adj->callback(statFloats, this);
+                }
+                adj->value(m_attribute->getFloat(v));
+                adj->box(FL_FLAT_BOX);
+                adj->color(FL_BACKGROUND_COLOR, FL_SELECTION_COLOR);
+                if(m_attribute->getAccessibility()==Attribute::OUTPUT) {
+                    adj->deactivate();
+                }
+                add(adj);
+                m_valueInputs.push_back(adj);
+            }
+        }break;
+        case Attribute::INT_ATTRIBUTE : 
+        case Attribute::ACTION_INT_ATTRIBUTE : {
+            int inpWidth=50;
+            int pos=fl_width(m_name.c_str())+margin*2;
+            if(m_attribute->getType()==Attribute::ACTION_INT_ATTRIBUTE) {
+                label("");
+                m_button = new Fl_Button(x+margin*2, y+margin, 
+                                         pos, h-2*margin, 
+                                         m_name.c_str());
+                pos+=margin*4;
+                m_button->callback(statAction, this);
+                m_button->box(FL_FLAT_BOX);
+                if(m_attribute->getAccessibility()==Attribute::OUTPUT) {
+                    m_button->deactivate();
+                }
+                add(m_button);
+            }
+            for(unsigned int v=0; v<m_nbValues; ++v) {
+                Fl_Value_Input*  adj = new Fl_Value_Input(
+                                                x+pos+(inpWidth+margin)*v,
+                                                y+margin, inpWidth, h-2*margin,
+                                                "");
+                adj->step(1);
+                adj->bounds(-10000, 10000);
+                if(m_attribute->getType()==Attribute::INT_ATTRIBUTE) {
+                    adj->callback(statInts, this);
+                }
+                adj->value(m_attribute->getInt(v));
+                adj->box(FL_FLAT_BOX);
+                adj->color(FL_BACKGROUND_COLOR, FL_SELECTION_COLOR);
+                if(m_attribute->getAccessibility()==Attribute::OUTPUT) {
+                    adj->deactivate();
+                }
+                add(adj);
+                m_valueInputs.push_back(adj);
+            }
+        }break;
+        case Attribute::BOOL_ATTRIBUTE : {
+            int pos=fl_width(m_name.c_str())+10;
+            for(unsigned int v=0; v<m_nbValues; ++v) {
+                vector<string>& labels = m_attribute->editValueLabels();
+                string lab=" X ";
+                if(labels.size()>v) {
+                    lab=labels[v].c_str();
+                }
+                Fl_Toggle_Button* adj = new Fl_Toggle_Button(
+                                                pos,y+margin, 
+                                                fl_width(lab.c_str()), 
+                                                h-2*margin,
+                                                lab.c_str());
+                adj->copy_label(lab.c_str());
+                pos+=fl_width(lab.c_str())+margin;
+                adj->callback(statChecks, this);
+                adj->value(m_attribute->getBool(v));
+                adj->box(FL_FLAT_BOX);
+                adj->down_box(FL_DOWN_BOX);
+                adj->clear_visible_focus();
+                adj->color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR);
+                if(m_attribute->getAccessibility()==Attribute::OUTPUT) {
+                    adj->deactivate();
+                }
+                add(adj);
+                m_checks.push_back(adj);
+            }
+        }break;
+        case Attribute::STRING_ATTRIBUTE: 
+        case Attribute::ACTION_STRING_ATTRIBUTE: {
+            int inpWidth=50;
+            int pos=fl_width(m_name.c_str())+margin*2;
+            if(m_attribute->getType()==Attribute::ACTION_STRING_ATTRIBUTE) {
+                label("");
+                m_button = new Fl_Button(x+margin*2, y+margin, 
+                                         pos, h-2*margin, 
+                                         m_name.c_str());
+                pos+=margin*4;
+                m_button->callback(statAction, this);
+                m_button->box(FL_FLAT_BOX);
+                if(m_attribute->getAccessibility()==Attribute::OUTPUT) {
+                    m_button->deactivate();
+                }
+                add(m_button);
+            }
+
+            for(unsigned int v=0; v<m_nbValues; ++v) {
+                Fl_Widget* adj;
+                if(m_attribute->getStringValuesChoices().size()>v) {
+                    Fl_Choice* ch = new Fl_Choice(x+pos+(inpWidth+margin)*v, 
+                                                 y+margin, inpWidth, h-2*margin,
+                                                 "");
+                    vector<string>& choices 
+                        = m_attribute->editStringValuesChoices()[v];
+                    vector<string>::iterator itChoice = choices.begin();
+                    int c=0;
+                    for(; itChoice!=choices.end(); ++itChoice, ++c) {
+                        if(m_attribute->getType()==Attribute::STRING_ATTRIBUTE){
+                            ch->add("", 0, statChoices, this);
+                            ch->replace(c, (*itChoice).c_str());
+                        }
+                        else {
+                            ch->add("", 0, NULL, this);
+                            ch->replace(c, (*itChoice).c_str());
+                        }
+                        if(fl_width((*itChoice).c_str())+30>inpWidth) {
+                            inpWidth=fl_width((*itChoice).c_str())+30;
+                        }
+                        if(m_attribute->getString(v).compare((*itChoice))==0 ) {
+                            ch->value(c);
+                        }
+                    }
+                    ch->size(min(inpWidth,w/2),ch->h());
+                    m_choices.push_back(ch);
+                    adj=ch;
+                }
+                else {
+                    Fl_Input* inp = new Fl_Input(x+pos+(inpWidth+margin)*v, 
+                                                 y+margin, inpWidth, h-2*margin,
+                                                 "");
+                    inp->value(m_attribute->getString(v).c_str());
+                    if(fl_width(inp->value())>inpWidth) {
+                        inp->size(fl_width(inp->value()), inp->h());
+                    }
+                    if(m_attribute->getType()==Attribute::STRING_ATTRIBUTE) {
+                        inp->callback(statStrings, this);
+                    }
+                    m_inputs.push_back(inp);
+                    adj=inp;
+                }
+                adj->when(FL_WHEN_CHANGED);
+                adj->box(FL_FLAT_BOX);
+                adj->color(FL_BACKGROUND_COLOR, FL_SELECTION_COLOR);
+                if(m_attribute->getAccessibility()==Attribute::OUTPUT) {
+                    adj->deactivate();
+                }
+                add(adj);
+            }
+        }break;
+        case Attribute::FILE_OPEN_ATTRIBUTE :
+        case Attribute::FILE_SAVE_ATTRIBUTE :
+        case Attribute::FOLDER_OPEN_ATTRIBUTE : 
+        case Attribute::FOLDER_SAVE_ATTRIBUTE : {
+            label("");
+            m_button = new Fl_Button(x+margin, y+margin, 
+                                     fl_width(m_name.c_str())+10, h-2*margin, 
+                                     m_name.c_str());
+            if(m_attribute->getType()==Attribute::FILE_OPEN_ATTRIBUTE) {
+                m_button->callback(statFileOpen, this);
+            }
+            else if(m_attribute->getType()==Attribute::FOLDER_OPEN_ATTRIBUTE) {
+                m_button->callback(statFolderOpen, this);
+            }
+            else if(m_attribute->getType()==Attribute::FOLDER_SAVE_ATTRIBUTE) {
+                m_button->callback(statFolderSave, this);
+            }
+            else {
+                m_button->callback(statFileSave, this);
+            }
+            m_button->box(FL_FLAT_BOX);
+            if(m_attribute->getAccessibility()==Attribute::OUTPUT) {
+                m_button->deactivate();
+            }
+            add(m_button);
+            m_output = new Fl_Output(x+m_button->w()+margin*2, 
+                                     y+margin, 
+                                     60, h-2*margin, "");
+            m_output->value(fl_filename_name(m_attribute->getFile().c_str()));
+            m_output->deactivate();
+            m_output->size(fl_width(m_output->value())+10,m_output->h());
+            m_output->box(FL_NO_BOX);
+            add(m_output);
+        }break;
+        case Attribute::ACTION_ATTRIBUTE : {
+            label("");
+            m_button = new Fl_Button(x+margin, y+margin, 
+                                              fl_width(m_name.c_str())+10, 
+                                              h-2*margin, 
+                                              m_name.c_str());
+            m_button->callback(statAction, this);
+            m_button->box(FL_FLAT_BOX);
+            if(m_attribute->getAccessibility()==Attribute::OUTPUT) {
+                m_button->deactivate();
+            }
+            add(m_button);
+        }break;
+        default:break;
+    	}
+	}
+
+    //add listeners button 
+    m_listenersBut = new Fl_Toggle_Button(x+w-(40+margin), y+margin, 
+                                               20, h-2*margin,"L");
+    m_listenersBut->callback(statShowListeners, this);
+    m_listenersBut->box(FL_FLAT_BOX);
+    m_listenersBut->color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR);
+    add(m_listenersBut);
+
+    //register us as guilistener of the attribute
+	if(m_nbValues<=4) {
+		m_guiListener = new GuiListener(this);
+		m_attribute->addListener(m_guiListener);
+	}
+	else {
+		m_guiListener=NULL;
+	}
+}
+
+AttributeWidget::~AttributeWidget() {
+	if(m_guiListener) {
+		m_attribute->removeListener(m_guiListener);
+		delete m_guiListener;
+	}
+}
+
+void AttributeWidget::cbFolderSave(Fl_Widget*) {
+    Fl_Native_File_Chooser fnfc;
+    fnfc.title(m_name.c_str());
+    fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY);
+    if(fnfc.show()==0) {
+        m_attribute->setFile(string(fnfc.filename()), m_guiListener->getID());
+        m_output->value(fl_filename_name(m_attribute->getFile().c_str()));
+        m_output->size(fl_width(m_output->value())+10, m_output->h());
+    }
+}
+
+void AttributeWidget::cbFolderOpen(Fl_Widget*) {
+    Fl_Native_File_Chooser fnfc;
+    fnfc.title(m_name.c_str());
+    fnfc.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY);
+    if(fnfc.show()==0) {
+        m_attribute->setFile(string(fnfc.filename()), m_guiListener->getID());
+        m_output->value(fl_filename_name(m_attribute->getFile().c_str()));
+        m_output->size(fl_width(m_output->value())+10, m_output->h());
+    }
+}
+
+void AttributeWidget::cbFileOpen(Fl_Widget*) {
+    Fl_Native_File_Chooser fnfc;
+    fnfc.title(m_name.c_str());
+    fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
+    if(fnfc.show()==0) {
+        m_attribute->setFile(string(fnfc.filename()), m_guiListener->getID());
+        m_output->value(fl_filename_name(m_attribute->getFile().c_str()));
+        m_output->size(fl_width(m_output->value())+10, m_output->h());
+    }
+}
+
+void AttributeWidget::cbFileSave(Fl_Widget*) {
+    Fl_Native_File_Chooser fnfc;
+    fnfc.title(m_name.c_str());
+    fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
+    if(fnfc.show()==0) {
+        m_attribute->setFile(string(fnfc.filename()), m_guiListener->getID());
+        m_output->value(fl_filename_name(m_attribute->getFile().c_str()));
+        m_output->size(fl_width(m_output->value())+10, m_output->h());
+    }
+}
+
+void AttributeWidget::cbAction(Fl_Widget*) {
+    if(m_attribute->getType()==Attribute::ACTION_STRING_ATTRIBUTE) {
+        vector<string> vals;
+        if(m_attribute->getStringValuesChoices().size()>0) {
+            vector<Fl_Choice*>::iterator itCh = m_choices.begin();
+            for(; itCh!=m_choices.end(); ++itCh) {
+                vals.push_back((*itCh)->text());
+            }
+        }
+        else {
+            vector<Fl_Input*>::iterator itInp = m_inputs.begin();
+            for(; itInp!=m_inputs.end(); ++itInp) {
+                vals.push_back((*itInp)->value());
+            }
+        }
+        m_attribute->setStrings(vals, m_guiListener->getID());
+    }
+    else if(m_attribute->getType()==Attribute::ACTION_FLOAT_ATTRIBUTE) {
+        vector<float> vals;
+        vector<Fl_Value_Input*>::iterator itInp = m_valueInputs.begin();
+        for(; itInp!=m_valueInputs.end(); ++itInp) {
+            vals.push_back((*itInp)->value());
+        }
+        m_attribute->setFloats(vals, m_guiListener->getID());
+    }
+    else if(m_attribute->getType()==Attribute::ACTION_INT_ATTRIBUTE) {
+        vector<int> vals;
+        vector<Fl_Value_Input*>::iterator itInp = m_valueInputs.begin();
+        for(; itInp!=m_valueInputs.end(); ++itInp) {
+            vals.push_back((*itInp)->value());
+        }
+        m_attribute->setInts(vals, m_guiListener->getID());
+    }
+    else {
+        m_attribute->setAction();
+    }
+}
+
+void AttributeWidget::cbFloats(Fl_Widget*) {
+    vector<float> vals;
+    vector<Fl_Value_Input*>::iterator itInp = m_valueInputs.begin();
+    for(; itInp!=m_valueInputs.end(); ++itInp) {
+        vals.push_back((*itInp)->value());
+    }
+    m_attribute->setFloats(vals, m_guiListener->getID());
+}
+
+void AttributeWidget::cbInts(Fl_Widget*) {
+    vector<int> vals;
+    vector<Fl_Value_Input*>::iterator itInp = m_valueInputs.begin();
+    for(; itInp!=m_valueInputs.end(); ++itInp) {
+        vals.push_back((*itInp)->value());
+    }
+    m_attribute->setInts(vals, m_guiListener->getID());
+}
+
+void AttributeWidget::cbStrings(Fl_Widget*) {
+    vector<string> vals;
+    vector<Fl_Input*>::iterator itInp = m_inputs.begin();
+    for(; itInp!=m_inputs.end(); ++itInp) {
+        vals.push_back((*itInp)->value());
+    }
+    m_attribute->setStrings(vals, m_guiListener->getID());
+}
+
+void AttributeWidget::cbChoices(Fl_Widget*) {
+    vector<string> vals;
+    vector<Fl_Choice*>::iterator itCh = m_choices.begin();
+    for(; itCh!=m_choices.end(); ++itCh) {
+        vals.push_back((*itCh)->text());
+    }
+    m_attribute->setStrings(vals, m_guiListener->getID());
+}
+
+void AttributeWidget::cbChecks(Fl_Widget*) {
+    vector<bool> vals;
+    vector<Fl_Toggle_Button*>::iterator itCh = m_checks.begin();
+    for(; itCh!=m_checks.end(); ++itCh) {
+        vals.push_back((*itCh)->value());
+    }
+    m_attribute->setBools(vals, m_guiListener->getID());
+}
+
+void AttributeWidget::cbShowListeners(Fl_Widget*) {
+    if(m_listenersBut->value()) {
+        MainWindow::getInstance()->showListeners();
+
+        //FIXME unselect other listenersbuttons in the other attribute widgets
+        
+        Fl_Pack* group = MainWindow::getInstance()->getListenersGroup();
+        group->clear();
+        //add one widget per listener of type osclistener
+        vector<Listener*>& listeners = m_attribute->editListeners();
+        vector<Listener*>::iterator itLis = listeners.begin();
+        for(; itLis!=listeners.end(); ++itLis) {
+            if((*itLis)->getListenerType().compare("OscListener")==0) {
+                group->add(new ListenerWidget(0, 0, group->w(), 30, *itLis));
+            }
+        }
+        //add the add button
+        m_addListenerBut = new Fl_Button(0, 0, group->w(), 30, "Add");
+        m_addListenerBut->box(FL_FLAT_BOX);
+        m_addListenerBut->callback(statAddListener, this);
+        group->add(m_addListenerBut);
+        group->redraw();
+    }
+    else {
+        MainWindow::getInstance()->hideListeners();
+    }
+    MainWindow::getInstance()->redraw();
+}
+
+void AttributeWidget::cbAddListener(Fl_Widget*) {
+    Listener* lis = Reveal::getInstance()->createListener("OscListener");
+    if(lis!=NULL) {
+        m_attribute->addListener(lis);
+        cbShowListeners(this);
+    }
+}
+
+void AttributeWidget::updateAttributeValues(vector<float>& floatValues, 
+                                            vector<int>& intValues,
+                                            vector<bool>& boolValues,
+                                            vector<string>& stringValues) {
+    switch(m_attribute->getType()) {
+        case Attribute::FLOAT_ATTRIBUTE : {
+            unsigned int w=0;
+            for(;w<floatValues.size() && w<m_valueInputs.size(); ++w) {
+                m_valueInputs[w]->value(floatValues[w]);
+            }
+        }break;
+        case Attribute::INT_ATTRIBUTE : {
+            unsigned int w=0;
+            for(;w<intValues.size() && w<m_valueInputs.size(); ++w) {
+                m_valueInputs[w]->value(intValues[w]);
+            }
+        }break;
+        case Attribute::BOOL_ATTRIBUTE : {
+            unsigned int w=0;
+            for(;w<boolValues.size() && w<m_checks.size(); ++w) {
+                m_checks[w]->value(boolValues[w]);
+            }
+        }break;
+        case Attribute::FILE_OPEN_ATTRIBUTE:
+        case Attribute::FILE_SAVE_ATTRIBUTE:
+        case Attribute::FOLDER_SAVE_ATTRIBUTE:
+        case Attribute::FOLDER_OPEN_ATTRIBUTE: {
+            m_output->value(stringValues[0].c_str());
+            m_output->size(fl_width(m_output->value())+10, m_output->h());
+        }break;
+        case Attribute::STRING_ATTRIBUTE : {
+            unsigned int w=0;
+            for(;w<stringValues.size() && w<m_inputs.size(); ++w) {
+                m_inputs[w]->value(stringValues[w].c_str());
+            }
+            w=0;
+            for(;w<stringValues.size() && w<m_choices.size(); ++w) {
+                m_choices[w]->value(
+                                m_choices[w]->find_index(
+                                    stringValues[w].c_str()));
+            }
+        }break;
+        default:break;
+    }
+}
+
diff --git a/src/gui/AttributeWidget.hpp b/src/gui/AttributeWidget.hpp
new file mode 100644
index 0000000..8a0eaea
--- /dev/null
+++ b/src/gui/AttributeWidget.hpp
@@ -0,0 +1,134 @@
+/***************************************************************************
+ *  AttributeWidget.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef AttributeWidget_h 
+#define AttributeWidget_h
+
+#include "../modules/Attribute.hpp"
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Output.H>
+#include <FL/Fl_Choice.H>
+#include <FL/Fl_Toggle_Button.H>
+#include "GuiListener.hpp"
+
+class AttributeWidget : public Fl_Group {
+    public:
+        AttributeWidget(int x, int y, int w, int h, Attribute* attribute);
+        virtual ~AttributeWidget();
+
+        static void statFolderSave(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbFolderSave(w);
+        }    
+        void cbFolderSave(Fl_Widget*);
+
+        static void statFolderOpen(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbFolderOpen(w);
+        }    
+        void cbFolderOpen(Fl_Widget*);
+
+        static void statFileOpen(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbFileOpen(w);
+        }    
+        void cbFileOpen(Fl_Widget*);
+
+        static void statFileSave(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbFileSave(w);
+        }    
+        void cbFileSave(Fl_Widget*);
+
+        static void statAction(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbAction(w);
+        }    
+        void cbAction(Fl_Widget*);
+
+        static void statFloats(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbFloats(w);
+        }    
+        void cbFloats(Fl_Widget*);
+
+        static void statInts(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbInts(w);
+        }    
+        void cbInts(Fl_Widget*);
+
+        static void statStrings(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbStrings(w);
+        }    
+        void cbStrings(Fl_Widget*);
+        static void statChoices(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbChoices(w);
+        }    
+        void cbChoices(Fl_Widget*);
+        static void statChecks(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbChecks(w);
+        }    
+        void cbChecks(Fl_Widget*);
+
+        static void statShowListeners(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbShowListeners(w);
+        }    
+        void cbShowListeners(Fl_Widget*);
+
+        static void statAddListener(Fl_Widget* w, void* f){ 
+            AttributeWidget *tmpf = static_cast<AttributeWidget*>(f);
+            tmpf->cbAddListener(w);
+        }    
+        void cbAddListener(Fl_Widget*);
+
+        void updateAttributeValues(std::vector<float>& floatValues, 
+                                   std::vector<int>& intValues,
+                                   std::vector<bool>& boolValues,
+                                   std::vector<std::string>& stringValues);
+
+    private:
+        Attribute* m_attribute;
+        std::string m_name;
+        std::string m_fullName;
+        unsigned int m_nbValues;
+        std::vector<bool> m_stringIsChoice;
+        Fl_Toggle_Button* m_listenersBut;
+        std::vector<Fl_Value_Input*> m_valueInputs;
+        std::vector<Fl_Input*> m_inputs;
+        std::vector<Fl_Choice*> m_choices;
+        std::vector<Fl_Toggle_Button*> m_checks;
+        Fl_Button* m_button;
+        Fl_Output* m_output;
+        Fl_Button* m_addListenerBut;
+        GuiListener* m_guiListener;
+};
+
+#endif
+
diff --git a/src/gui/GuiListener.cpp b/src/gui/GuiListener.cpp
new file mode 100644
index 0000000..5178610
--- /dev/null
+++ b/src/gui/GuiListener.cpp
@@ -0,0 +1,45 @@
+/***************************************************************************
+ *  GuiListener.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "GuiListener.hpp"
+#include <iostream>
+#include <sstream>
+#include "AttributeWidget.hpp"
+
+using namespace std;
+
+GuiListener::GuiListener(AttributeWidget* wid):Listener(), 
+                                               m_attributeWidget(wid) {
+    m_listenerType="GuiListener";
+}
+
+void GuiListener::update(vector<float>& floatValues, 
+                         vector<int>& intValues,
+                         vector<bool>& boolValues,
+                         vector<string>& stringValues) {
+
+    m_attributeWidget->updateAttributeValues(floatValues, 
+                                             intValues, 
+                                             boolValues, 
+                                             stringValues);
+}
+
diff --git a/src/gui/GuiListener.hpp b/src/gui/GuiListener.hpp
new file mode 100644
index 0000000..8faa2d8
--- /dev/null
+++ b/src/gui/GuiListener.hpp
@@ -0,0 +1,45 @@
+/***************************************************************************
+ *  GuiListener.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef GuiListener_h
+#define GuiListener_h
+
+#include "../modules/Listener.hpp"
+
+class AttributeWidget;
+
+class GuiListener: public Listener {
+    public:
+        GuiListener(AttributeWidget*);
+        virtual ~GuiListener(){}
+
+        virtual void update(std::vector<float>& floatValues, 
+                            std::vector<int>& intValues,
+                            std::vector<bool>& boolValues,
+                            std::vector<std::string>& stringValues);
+
+    protected:
+        AttributeWidget* m_attributeWidget;
+};
+
+#endif
diff --git a/src/gui/ListenerWidget.cpp b/src/gui/ListenerWidget.cpp
new file mode 100644
index 0000000..dd51b7e
--- /dev/null
+++ b/src/gui/ListenerWidget.cpp
@@ -0,0 +1,109 @@
+/***************************************************************************
+ *  ListenerWidget.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "ListenerWidget.hpp"
+#include <iostream>
+#include <FL/fl_draw.H>
+#include <FL/Fl.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Input_Choice.H>
+#include <FL/Fl_Native_File_Chooser.H>
+#include <FL/filename.H>
+
+using namespace std;
+
+ListenerWidget::ListenerWidget(int x, int y, 
+                               int w, int h, 
+                               Listener* listener): 
+                                                  Fl_Group(x,y,w,h,""),
+                                                  m_listener(listener) {
+    align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+    color(FL_SELECTION_COLOR);
+    box(FL_BORDER_BOX);
+    end();
+
+    int margin=5;
+    int pos=x+margin;
+    vector<string>& lisParams = m_listener->editParameters();
+    vector<vector<string> >& lisParVals = m_listener->editParametersValues();
+    vector<string>::iterator itPar = lisParams.begin();
+    vector<vector<string> >::iterator itVal = lisParVals.begin();
+    for(; itPar!=lisParams.end(); ++itPar, ++itVal) {
+        if((*itVal).size()>0) {
+            Fl_Choice* inp = new Fl_Choice(pos, y+margin, 
+                                           (w-40)/lisParams.size(), h-2*margin,
+                                           "");
+            for(string &value : (*itVal)) {
+                inp->add(value.c_str());
+            }
+
+            pos+=inp->w()+margin;
+            inp->value(0);
+            inp->callback(statParams, this);
+            inp->when(FL_WHEN_CHANGED);
+            inp->box(FL_FLAT_BOX);
+            inp->color(FL_BACKGROUND_COLOR, FL_SELECTION_COLOR);
+            m_choices.push_back(inp);
+            add(inp);
+        }
+        else {
+            Fl_Input* inp = new Fl_Input(pos, y+margin, 
+                                         (w-40)/lisParams.size(), h-2*margin,
+                                         "");
+            pos+=inp->w()+margin;
+            inp->value((*itPar).c_str());
+            inp->callback(statParams, this);
+            inp->when(FL_WHEN_CHANGED);
+            inp->box(FL_FLAT_BOX);
+            inp->color(FL_BACKGROUND_COLOR, FL_SELECTION_COLOR);
+            add(inp);
+            m_parameters.push_back(inp);
+        }
+    }
+
+    m_removeBut = new Fl_Button(pos, y+margin, 
+                                20, h-2*margin, "X");
+    m_removeBut->callback(statRemove, this);
+    m_removeBut->box(FL_FLAT_BOX);
+    m_removeBut->color(FL_BACKGROUND_COLOR, FL_SELECTION_COLOR);
+    add(m_removeBut);
+}
+
+void ListenerWidget::cbParams(Fl_Widget*) {
+    vector<string> params;
+    for(Fl_Input* inp : m_parameters) {
+        params.push_back(inp->value());
+    }
+    for(Fl_Choice* inp : m_choices) {
+        params.push_back(inp->text(inp->value()));
+    }
+    m_listener->setParameters(params);
+}
+
+void ListenerWidget::cbRemove(Fl_Widget*) {
+    m_listener->deleteListener();
+}
+
+
diff --git a/src/gui/ListenerWidget.hpp b/src/gui/ListenerWidget.hpp
new file mode 100644
index 0000000..519714a
--- /dev/null
+++ b/src/gui/ListenerWidget.hpp
@@ -0,0 +1,57 @@
+/***************************************************************************
+ *  ListenerWidget.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef ListenerWidget_h 
+#define ListenerWidget_h
+
+#include "../modules/Listener.hpp"
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Choice.H>
+#include <FL/Fl_Value_Input.H>
+#include <FL/Fl_Button.H>
+
+class ListenerWidget : public Fl_Group {
+    public:
+        ListenerWidget(int x, int y, int w, int h, Listener* listener);
+        virtual ~ListenerWidget() {}
+
+        static void statParams(Fl_Widget* w, void* f){ 
+            ListenerWidget *tmpf = static_cast<ListenerWidget*>(f);
+            tmpf->cbParams(w);
+        }    
+        void cbParams(Fl_Widget*);
+        static void statRemove(Fl_Widget* w, void* f){ 
+            ListenerWidget *tmpf = static_cast<ListenerWidget*>(f);
+            tmpf->cbRemove(w);
+        }    
+        void cbRemove(Fl_Widget*);
+
+    private:
+        Listener* m_listener;
+        std::vector<Fl_Input*> m_parameters;
+        std::vector<Fl_Choice*> m_choices;
+        Fl_Button* m_removeBut;
+};
+
+#endif
+
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
new file mode 100755
index 0000000..b43d080
--- /dev/null
+++ b/src/gui/MainWindow.cpp
@@ -0,0 +1,250 @@
+/***************************************************************************
+ *  MainWindow.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "MainWindow.hpp"
+
+#include <iostream>
+#include <FL/Fl.H>                          
+#include <FL/Fl_Native_File_Chooser.H>
+#include <FL/fl_draw.H>
+
+#include "../Reveal.hpp"
+
+using namespace std;
+
+
+void MyDraw(const Fl_Label *o, int X, int Y, int W, int H, Fl_Align a) {
+    fl_font(o->font, o->size);
+    fl_color((Fl_Color)o->color);
+    fl_draw(o->value, X, Y, W, H, a, o->image, 0);
+}
+
+void MyMeasure(const Fl_Label *o, int &W, int &H) {
+    fl_font(o->font, o->size);
+    fl_measure(o->value, W, H, 0);
+}
+
+MainWindow::MainWindow(): Fl_Double_Window(600, 327, "Revil - Configuration"),
+                          m_treeWidth(200),
+                          m_attributesWidth(400) {
+    //resizable(this);
+    Fl::option(Fl::OPTION_FNFC_USES_GTK, false);
+    Fl::option(Fl::OPTION_VISIBLE_FOCUS, false);
+    Fl::scheme("gtk+");
+    Fl::set_color(FL_BACKGROUND_COLOR, 200, 200, 200);
+    Fl::set_color(FL_BACKGROUND2_COLOR, 150, 150, 150);
+    Fl::set_color(FL_SELECTION_COLOR, 250, 250, 250);
+    Fl::set_labeltype(FL_NORMAL_LABEL, MyDraw, MyMeasure);
+    end();
+}
+
+void MainWindow::init() {
+    
+    this->color(FL_BLACK);
+
+    m_scrollModules = new Fl_Scroll(0,0,m_treeWidth,h(),"");
+        m_modules= new Fl_Pack(0, 
+                               0, 
+                               m_treeWidth, 
+                               h(), "Modules");
+        m_modules->color(FL_SELECTION_COLOR);
+        m_modules->resizable(NULL);
+    m_scrollModules->end();
+    m_scrollModules->color(FL_BLACK, FL_BLACK);
+    m_scrollModules->align(FL_ALIGN_LEFT);
+
+    add(m_scrollModules);
+
+    m_scrollAttributes = new Fl_Scroll(m_treeWidth,0,m_attributesWidth,h(),"");
+        m_attributes= new Fl_Pack(m_treeWidth, 
+                                  0, 
+                                  m_attributesWidth, 
+                                  h(), "Attributes");
+        m_attributes->color(FL_SELECTION_COLOR);
+    m_scrollAttributes->end();
+    m_scrollAttributes->color(FL_BLACK);
+    add(m_scrollAttributes);
+
+    m_scrollListeners = new Fl_Scroll(m_treeWidth+m_attributesWidth, 0, 
+                                      m_treeWidth*2, h(),
+                                      "Listeners");
+        m_listeners= new Fl_Pack(m_treeWidth+m_attributesWidth, 0, 
+                                 m_treeWidth*2, h(), 
+                                 "");
+        m_listeners->color(FL_SELECTION_COLOR);
+    m_scrollListeners->end();
+    m_scrollListeners->color(FL_BLACK);
+    add(m_scrollListeners);
+
+    callback(statQuit);
+
+    redraw();
+}
+
+MainWindow::~MainWindow() {
+}
+
+MainWindow* MainWindow::getInstance() {
+    static MainWindow instance;
+    return &instance;
+}
+
+void MainWindow::cbQuit() {
+    int res = fl_choice("Save before quit ?", "Don't quit", 
+                        "Save first", "Quit without saving");
+    switch(res) {
+        case 0: break;
+        case 1: {
+            cbSave();
+            Reveal::getInstance()->quit();
+        }
+        case 2: {
+            Reveal::getInstance()->quit();
+        }
+    }
+}
+
+void MainWindow::refreshModules(bool clearAttributes, bool clearListeners) {
+    if(clearAttributes) {
+        m_attributes->clear();
+    }
+    if(clearListeners) {
+        m_listeners->clear();
+    }
+    //refresh modules
+    m_modules->clear();
+    m_moduleButtonsMap.clear();
+    vector<Module*> modules;
+    Reveal::getInstance()->getSubTree(modules);
+    vector<Module*>::iterator itMod = modules.begin();
+    for(; itMod!=modules.end(); ++itMod) {
+        ModuleWidget* newMod = new ModuleWidget(m_modules->x(), 10, 
+                                                m_modules->w(), 30, 
+                                                *itMod);
+        m_moduleButtonsMap[(*itMod)->getFullName()]=newMod;
+        newMod->callback(statTree, this);
+        m_modules->add(newMod);
+    }
+
+    //select previously selected button if possible
+    if(m_moduleButtonsMap.find(m_selectedModulePath)!=m_moduleButtonsMap.end()){
+        m_moduleButtonsMap[m_selectedModulePath]->value(1);
+        displayAttributes(m_moduleButtonsMap[m_selectedModulePath]);
+    }
+
+    //redraw all
+    this->redraw();
+}
+
+void MainWindow::displayAttributes(ModuleWidget* mod) {
+    m_attributes->clear();
+    m_scrollAttributes->scroll_to(0,0);
+    mod->fillGroupWithAttributes(m_attributes);
+    m_listeners->clear();
+}
+
+void MainWindow::cbTree(Fl_Widget* w) {
+    m_selectedModulePath="";
+    int childID = m_modules->find(w);
+    for(int c=0; c<m_modules->children(); ++c) {
+        if(c==childID) {
+            ModuleWidget* selWid 
+                = static_cast<ModuleWidget*>(m_modules->child(c));
+            selWid->value(1);
+            m_selectedModulePath = selWid->getModule()->getFullName();
+            displayAttributes(selWid);
+            redraw();
+        }
+        else {
+            static_cast<Fl_Toggle_Button*>(m_modules->child(c))->value(0);
+        }
+    }
+}
+
+int MainWindow::handle(int event) {
+    switch(event) {
+        case FL_SHORTCUT:
+        case FL_KEYDOWN : {
+            if(Fl::event_command()) {
+                switch(Fl::event_key()) {
+                    case 'o': cbOpen(); return 1;
+                    case 's': cbSave(); return 1;
+                    case 'q': cbQuit(); return 1;
+                }
+            }
+            else if(Fl::event_key()==FL_Escape) {
+                cbQuit(); 
+                return 1;
+            }
+        }break;
+        case FL_CLOSE: {
+            cbQuit();
+            return 1;
+        }break;
+        default: break;
+    }
+    return Fl_Group::handle(event);
+}
+
+void MainWindow::cbOpen() {
+    Fl_Native_File_Chooser fnfc;
+    fnfc.title("Open .rev file");
+    fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);
+    if(fnfc.show()==0) {
+        Reveal::getInstance()->open(fnfc.filename());
+    }
+}
+
+void MainWindow::cbSave() {
+    const string& fileStr = Reveal::getInstance()
+                                    ->getAttribute("save")->getFile();
+    if(fileStr.compare("save")!=0 && fileStr.compare("")!=0) {
+        Reveal::getInstance()->save(fileStr);
+    }
+    else {
+        cbSaveAs();
+    }
+}
+
+void MainWindow::cbSaveAs() {
+    Fl_Native_File_Chooser fnfc;
+    fnfc.title("Save to .rev file");
+    fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
+    if(fnfc.show()==0) {
+        Reveal::getInstance()->getAttribute("save")->setFile(fnfc.filename());
+    }
+}
+
+void MainWindow::showListeners() {
+    m_scrollListeners->show();
+    m_scrollListeners->resize(m_treeWidth+m_attributesWidth,0, 
+                              m_treeWidth*2,h());
+    size(m_treeWidth+m_attributesWidth+m_treeWidth*2, h()); 
+    redraw();
+}
+
+void MainWindow::hideListeners() {
+    m_scrollListeners->hide();
+    size(m_treeWidth+m_attributesWidth,h()); 
+    redraw();
+}
+
diff --git a/src/gui/MainWindow.hpp b/src/gui/MainWindow.hpp
new file mode 100755
index 0000000..f76f685
--- /dev/null
+++ b/src/gui/MainWindow.hpp
@@ -0,0 +1,90 @@
+/***************************************************************************
+ *  MainWindow.hpp
+ *  Part of Rouages
+ *  2013  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef MainWindow_h
+#define MainWindow_h
+
+#include <string>
+#include <map>
+
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Tile.H>
+#include <FL/Fl_Pack.H>
+#include <FL/Fl_Scroll.H>
+#include <FL/Fl_Toggle_Button.H>
+#include <FL/Fl_Shared_Image.H>
+#include <FL/Fl.H>
+#include <FL/fl_ask.H>
+
+#include "ModuleWidget.hpp"
+
+class MainWindow: public Fl_Double_Window {
+    public:
+        static MainWindow* getInstance();
+        ~MainWindow();
+        void init();
+        void refreshModules(bool clearAttributes=false, 
+                            bool clearListeners=false);
+        void displayAttributes(ModuleWidget*);
+
+        static void statTree(Fl_Widget* w,void* f){ 
+            MainWindow *tmpf = static_cast<MainWindow *>(f);
+            tmpf->cbTree(w);
+        }    
+        void cbTree(Fl_Widget*);
+
+        void cbOpen();
+        void cbSave();
+        void cbSaveAs();
+
+        static void statQuit(Fl_Widget* w,void* f){ 
+            MainWindow *tmpf = static_cast<MainWindow *>(f);
+            tmpf->cbQuit();
+        }    
+        void cbQuit();
+        int handle(int event);
+
+        inline Fl_Pack* getListenersGroup(){return m_listeners;}
+        void showListeners();
+        void hideListeners();
+
+    private:
+        MainWindow();
+
+    private:
+        int m_treeWidth;
+        int m_attributesWidth;
+        Fl_Scroll* m_scrollModules;
+        Fl_Pack* m_modules;
+        Fl_Scroll* m_scrollAttributes;
+        Fl_Pack* m_attributes;
+        Fl_Scroll* m_scrollListeners;
+        Fl_Pack* m_listeners;
+
+        std::string m_fileName;
+        std::string m_selectedModulePath;
+        std::map<std::string, ModuleWidget*> m_moduleButtonsMap;
+};
+
+#endif
+
diff --git a/src/gui/ModuleWidget.cpp b/src/gui/ModuleWidget.cpp
new file mode 100644
index 0000000..86ba71b
--- /dev/null
+++ b/src/gui/ModuleWidget.cpp
@@ -0,0 +1,58 @@
+/***************************************************************************
+ *  ModuleWidget.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "ModuleWidget.hpp"
+#include "AttributeWidget.hpp"
+#include <vector>
+
+using namespace std;
+
+ModuleWidget::ModuleWidget(int x, int y, 
+                           int w, int h, 
+                           Module* module): Fl_Toggle_Button(x,y,w,h,""),
+                                            m_module(module) {
+    m_label = "";
+    for(int d=0; d<int(m_module->getDepth())-1; ++d) {
+        m_label+="  ";
+    }
+    if(m_module->getDepth()>0) {
+        m_label+="|-";
+    }
+    m_label+=m_module->getName();
+    label(m_label.c_str());
+    align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
+    box(FL_BORDER_BOX);
+    color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR);
+}
+
+void ModuleWidget::fillGroupWithAttributes(Fl_Pack* group) {
+    vector<Attribute*>& attributes = m_module->editAttributes();
+    vector<Attribute*>::iterator itAtt = attributes.begin();
+    for(; itAtt!=attributes.end(); ++itAtt) {
+       if((*itAtt)->getAccessibility()!=Attribute::HIDDEN) {
+            group->add(new AttributeWidget(0, 0, group->w(), 30, *itAtt));
+       }
+    }
+}
+
+
diff --git a/src/gui/ModuleWidget.hpp b/src/gui/ModuleWidget.hpp
new file mode 100644
index 0000000..f2aaaac
--- /dev/null
+++ b/src/gui/ModuleWidget.hpp
@@ -0,0 +1,44 @@
+/***************************************************************************
+ *  ModuleWidget.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef ModuleWidget_h 
+#define ModuleWidget_h
+
+#include "../modules/Module.hpp"
+#include <FL/Fl_Toggle_Button.H>
+#include <FL/Fl_Pack.H>
+
+class ModuleWidget : public Fl_Toggle_Button {
+    public:
+        ModuleWidget(int x, int y, int w, int h, Module* module);
+        virtual ~ModuleWidget() {}
+        void fillGroupWithAttributes(Fl_Pack*);
+        inline Module* getModule(){return m_module;}
+
+    private:
+        Module* m_module;
+        std::string m_label;
+
+};
+
+#endif
+
diff --git a/src/modules/Attribute.cpp b/src/modules/Attribute.cpp
new file mode 100644
index 0000000..b6644f0
--- /dev/null
+++ b/src/modules/Attribute.cpp
@@ -0,0 +1,316 @@
+/***************************************************************************
+ *  Attribute.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "Attribute.hpp"
+
+#include <sstream>
+#include <iostream>
+#include <FL/fl_utf8.h>
+
+#include "../Reveal.hpp"
+#include "Module.hpp"
+
+using namespace std;
+
+Attribute::~Attribute() {
+    vector<Listener*>::iterator itLis = m_listeners.begin();
+    for(; itLis!=m_listeners.end(); ++itLis) {
+        Reveal::getInstance()->deleteListener((*itLis));
+    }
+    m_listeners.clear();
+    m_listenersMap.clear();
+}
+
+void Attribute::load(xmlNodePtr node) {
+    vector<float> floatVals;
+    vector<int> intVals;
+    vector<bool> boolVals;
+    vector<string> strVals;
+    xmlNodePtr valNode;
+    for(valNode=node->children; valNode; valNode=valNode->next){
+        if(valNode->type == XML_ELEMENT_NODE) {
+            if(!xmlStrcmp(valNode->name, (const xmlChar *)"Float")) {
+                char* value = (char*)xmlGetProp(valNode,(xmlChar*)"value");
+                if(value!=NULL) {
+                    floatVals.push_back(atof(value));
+                }
+            }
+            else if(!xmlStrcmp(valNode->name, (const xmlChar *)"Int")) {
+                char* value = (char*)xmlGetProp(valNode,(xmlChar*)"value");
+                if(value!=NULL) {
+                    intVals.push_back(atoi(value));
+                }
+            }
+            else if(!xmlStrcmp(valNode->name, (const xmlChar *)"Bool")) {
+                char* value = (char*)xmlGetProp(valNode,(xmlChar*)"value");
+                if(value!=NULL) {
+                    boolVals.push_back(atoi(value));
+                }
+            }
+            else if(!xmlStrcmp(valNode->name, (const xmlChar *)"String")) {
+                char* value = (char*)xmlGetProp(valNode,(xmlChar*)"value");
+                if(value!=NULL) {
+                    strVals.push_back(string(value));
+                }
+            } //Listeners
+            else if((!xmlStrcmp(valNode->name, (const xmlChar *)"Listeners"))) {
+                xmlNodePtr lisNode;
+                for(lisNode=valNode->children;lisNode;lisNode=lisNode->next) {
+                    if(lisNode->type == XML_ELEMENT_NODE) {
+                        string typeStr((char*) lisNode->name);
+                        Listener* lis = Reveal::getInstance()
+                                                    ->createListener(typeStr);
+                        if(lis!=NULL) {
+                            lis->load(lisNode);
+                            addListener(lis);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if(floatVals.size()>0 && m_type==FLOAT_ATTRIBUTE) {
+        if(m_loadable) {
+            setFloats(floatVals);
+        }
+        else {
+            initFloats(floatVals);
+        }
+    }
+    else if(intVals.size()>0 && m_type==INT_ATTRIBUTE) {
+        if(m_loadable) {
+            setInts(intVals);
+        }
+        else {
+            initInts(intVals);
+        }
+    }
+    else if(boolVals.size()>0 && m_type==BOOL_ATTRIBUTE) {
+        if(m_loadable) {
+            setBools(boolVals);
+        }
+        else {
+            initBools(boolVals);
+        }
+    }
+    else if(strVals.size()>0 && m_type==STRING_ATTRIBUTE) {
+        if(m_loadable) {
+            setStrings(strVals);
+        }
+        else {
+            initStrings(strVals);
+        }
+    }
+    else if(strVals.size()>0 && m_type==FILE_OPEN_ATTRIBUTE) {
+
+        if(FILE *file = fopen(strVals[0].c_str(), "r")) {
+            fclose(file);
+        } else if(strVals.size()>1) {
+            getAbsPathFromRev(strVals[1], strVals[0]);
+        }  
+
+        if(m_loadable) {
+            setFile(strVals[0]);
+        }
+        else {
+            initFile(strVals[0]);
+        }
+    }
+    else if(strVals.size()>0 && m_type==FOLDER_OPEN_ATTRIBUTE) {
+        if(FILE *file = fopen(strVals[0].c_str(), "r")) {
+            fclose(file);
+        } else if(strVals.size()>1) {
+            getAbsPathFromRev(strVals[1], strVals[0]);
+        }  
+
+        if(m_loadable) {
+            setFile(strVals[0]);
+        }
+        else {
+            initFile(strVals[0]);
+        }
+    }
+    else if(strVals.size()>0 && m_type==FILE_SAVE_ATTRIBUTE) {
+        initFile(strVals[0]);
+    }
+}
+
+void Attribute::save(xmlNodePtr parentNode) {
+    xmlNodePtr newNode = xmlNewChild(parentNode, NULL, 
+                                     BAD_CAST m_name.c_str(), NULL);
+    if(m_accessibility!=OUTPUT) {
+        vector<float>::iterator itFloat = m_floatValues.begin();
+        for(; itFloat!=m_floatValues.end(); ++itFloat) {
+            xmlNodePtr valNode = xmlNewChild(newNode, NULL, 
+                                             BAD_CAST "Float", NULL);
+            ostringstream oss;
+            oss<<(*itFloat);
+            xmlNewProp(valNode, BAD_CAST "value", BAD_CAST oss.str().c_str());
+        }
+        vector<int>::iterator itInt = m_intValues.begin();
+        for(; itInt!=m_intValues.end(); ++itInt) {
+            xmlNodePtr valNode = xmlNewChild(newNode, NULL, 
+                                             BAD_CAST "Int", NULL);
+            ostringstream oss;
+            oss<<(*itInt);
+            xmlNewProp(valNode, BAD_CAST "value", BAD_CAST oss.str().c_str());
+        }
+        vector<bool>::iterator itBool = m_boolValues.begin();
+        for(; itBool!=m_boolValues.end(); ++itBool) {
+            xmlNodePtr valNode = xmlNewChild(newNode, NULL, 
+                                             BAD_CAST "Bool", NULL);
+            ostringstream oss;
+            oss<<(*itBool);
+            xmlNewProp(valNode, BAD_CAST "value", BAD_CAST oss.str().c_str());
+        }
+        //if file or folder, save path relative to current rev file
+        if(m_type==FILE_OPEN_ATTRIBUTE || m_type==FOLDER_OPEN_ATTRIBUTE) {
+            if(m_stringValues.size()>0) {
+                if(m_stringValues[0].compare("")!=0) {
+                    std::string relPath;
+                    getRelPathToRev(m_stringValues[0], relPath);
+                    if(m_stringValues.size()<2) {
+                        m_stringValues.push_back("");
+                    }
+                    m_stringValues[1]=relPath;
+                }
+            }
+        }
+        vector<string>::iterator itStr = m_stringValues.begin();
+        for(; itStr!=m_stringValues.end(); ++itStr) {
+            xmlNodePtr valNode = xmlNewChild(newNode, NULL, 
+                                             BAD_CAST "String", NULL);
+            if(fl_utf8test((*itStr).c_str(),(*itStr).length())>0) {
+                xmlNewProp(valNode, BAD_CAST "value", 
+                           xmlCharStrdup((*itStr).c_str()));
+            }
+        }
+    }
+
+    //save listeners
+    if(m_listeners.size()>0) {
+        xmlNodePtr lisNode = xmlNewChild(newNode,NULL,BAD_CAST"Listeners",NULL);
+        vector<Listener*>::iterator itLis = m_listeners.begin();
+        for(; itLis!=m_listeners.end(); ++itLis) {
+            if((*itLis)->getListenerType().compare("GuiListener")!=0 &&
+                    (*itLis)->getListenerType().compare("PathListener")!=0) {
+                (*itLis)->save(lisNode);
+            }
+        }
+    }
+}
+
+void Attribute::addListener(Listener* lis) {
+    unsigned int newLisID = 0;
+    while(m_listenersMap.find(newLisID)!=m_listenersMap.end()) {
+        newLisID++;
+    }
+    m_listenersMap[newLisID] = lis;
+    lis->setID(newLisID);
+    lis->setAttribute(this);
+    updateListenersVec();
+}
+
+void Attribute::removeListener(Listener* lis) {
+    m_listenersMap.erase(lis->getID());
+    updateListenersVec();
+}
+
+void Attribute::updateListenersVec() {
+    m_listeners.clear();
+    map<int, Listener*>::iterator itLis = m_listenersMap.begin();
+    for(; itLis!=m_listenersMap.end(); ++itLis) {
+        m_listeners.push_back(itLis->second);
+    }
+    m_module->gotAttributeListenersUpdate(this);
+}
+
+void Attribute::clearListeners() {
+    m_listeners.clear();
+    m_listenersMap.clear();
+}
+
+void Attribute::sendValuesToListeners(const int& lisID) {
+    vector<Listener*>::iterator itLis = m_listeners.begin();
+    for(; itLis!=m_listeners.end(); ++itLis) {
+        if((*itLis)->getID()!=lisID) { //do not send to origin listener
+            (*itLis)->update(m_floatValues, 
+                             m_intValues,
+                             m_boolValues,
+                             m_stringValues);
+        }
+    }
+}
+
+
+
+void Attribute::getRelPathToRev(const string& abs, 
+                                string& rel) {
+    string revDir = Reveal::getInstance()->getCurrentFile();
+
+    revDir = revDir.substr(0, revDir.find_last_of("/\\"));
+    string absDir=abs.substr(0, abs.find_last_of("/\\"));
+    string name=abs.substr(abs.find_last_of("/\\")+1);
+
+    bool equal=true;
+    while(equal) {
+        size_t pos1,pos2;
+        std::string subRev, subAbs;
+        pos1 = revDir.find_first_of('/');
+        subRev = revDir.substr(0, pos1);
+        pos2 = absDir.find_first_of('/');
+        subAbs = absDir.substr(0, pos2);
+        if(subAbs.compare(subRev)!=0) {	//reached the different path
+            equal=false;
+        }
+        else if(pos2==string::npos) {
+            absDir="";
+            equal=false;
+        }
+        else {
+            revDir = revDir.substr(pos1+1);
+            absDir = absDir.substr(pos2+1);
+        }
+    }
+
+    //test if we need to go up (../)
+    size_t pos3=revDir.find_first_of('/');
+    while(pos3!=string::npos) {
+        pos3 = revDir.find_first_of('/');
+        if(pos3!=string::npos) {
+            revDir=revDir.substr(pos3+1);
+            absDir="../"+absDir;
+        }
+    }
+    rel=absDir+"/"+name;
+}
+
+
+void Attribute::getAbsPathFromRev(const string& rel, 
+                                  string& abs) {
+    string revDir = Reveal::getInstance()->getCurrentFile();
+
+    revDir = revDir.substr(0, revDir.find_last_of("/\\"));
+    abs = revDir+"/"+rel;
+}
diff --git a/src/modules/Attribute.hpp b/src/modules/Attribute.hpp
new file mode 100644
index 0000000..ab9ca17
--- /dev/null
+++ b/src/modules/Attribute.hpp
@@ -0,0 +1,330 @@
+/***************************************************************************
+ *  Attribute.hpp
+ *  Part of Revil
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef Attribute_h
+#define Attribute_h
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <map>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include "Listener.hpp"
+
+class Module;
+
+class Attribute {
+
+    public:
+        enum TYPE {FLOAT_ATTRIBUTE, 
+                   INT_ATTRIBUTE, 
+                   STRING_ATTRIBUTE, 
+                   BOOL_ATTRIBUTE, 
+                   FILE_OPEN_ATTRIBUTE, 
+                   FOLDER_OPEN_ATTRIBUTE, 
+                   FILE_SAVE_ATTRIBUTE, 
+                   FOLDER_SAVE_ATTRIBUTE, 
+                   ACTION_ATTRIBUTE, 
+                   ACTION_INT_ATTRIBUTE,
+                   ACTION_FLOAT_ATTRIBUTE,
+                   ACTION_STRING_ATTRIBUTE,
+                   BLOB_ATTRIBUTE};
+
+        typedef void (ActionCallback) (Module*);
+        typedef void (FileCallback) (Module*, const std::string&);
+        typedef void (FloatCallback) (Module*, const std::vector<float>&);
+        typedef void (IntCallback) (Module*, const std::vector<int>&);
+        typedef void (StringCallback) (Module*,const std::vector<std::string>&);
+        typedef void (BoolCallback) (Module*,const std::vector<bool>&);
+        typedef void (BlobCallback) (Module*, const std::string&, void*);
+
+        enum ACCESSIBILITY {HIDDEN, OUTPUT, LOCAL, GLOBAL};
+
+    public:
+        Attribute(const std::string& name, const TYPE& type, 
+                  ActionCallback* callback, Module* mod, 
+                  ACCESSIBILITY acc=GLOBAL, bool loadable=true): 
+                                             m_name(name), 
+                                             m_type(type),
+                                             m_module(mod),
+                                             m_nbValues(0),
+                                             m_loadable(loadable),
+                                             m_accessibility(acc),
+                                             m_actionCallback(callback){
+        }
+        Attribute(const std::string& name, const TYPE& type, 
+                  FileCallback* callback, Module* mod,
+                  ACCESSIBILITY acc=GLOBAL, bool loadable=true): 
+                                             m_name(name), 
+                                             m_type(type),
+                                             m_module(mod),
+                                             m_nbValues(1),
+                                             m_loadable(loadable),
+                                             m_accessibility(acc),
+                                             m_fileCallback(callback){
+            m_stringValues.resize(1, "");
+        }
+        Attribute(const std::string& name, const TYPE& type, 
+                  FloatCallback* callback, Module* mod, 
+                  const unsigned int& nbValues, 
+                  ACCESSIBILITY acc=GLOBAL, bool loadable=true): 
+                                             m_name(name), 
+                                             m_type(type),
+                                             m_module(mod),
+                                             m_nbValues(nbValues),
+                                             m_loadable(loadable),
+                                             m_accessibility(acc),
+                                             m_floatCallback(callback){
+            m_floatValues.resize(nbValues,0);
+        }
+        Attribute(const std::string& name, const TYPE& type, 
+                  BoolCallback* callback, Module* mod, 
+                  const unsigned int& nbValues, 
+                  ACCESSIBILITY acc=GLOBAL, bool loadable=true): 
+                                             m_name(name), 
+                                             m_type(type),
+                                             m_module(mod),
+                                             m_nbValues(nbValues),
+                                             m_loadable(loadable),
+                                             m_accessibility(acc),
+                                             m_boolCallback(callback){
+            m_boolValues.resize(nbValues,false);
+        }
+        Attribute(const std::string& name, const TYPE& type, 
+                  IntCallback* callback, Module* mod,
+                  const unsigned int& nbValues, 
+                  ACCESSIBILITY acc=GLOBAL, bool loadable=true): 
+                                             m_name(name), 
+                                             m_type(type),
+                                             m_module(mod),
+                                             m_nbValues(nbValues),
+                                             m_loadable(loadable),
+                                             m_accessibility(acc),
+                                             m_intCallback(callback){
+            m_intValues.resize(nbValues,0);
+        }
+        Attribute(const std::string& name, const TYPE& type, 
+                  StringCallback* callback, Module* mod,
+                  const unsigned int& nbValues, 
+                  ACCESSIBILITY acc=GLOBAL, bool loadable=true): 
+                                             m_name(name), 
+                                             m_type(type),
+                                             m_module(mod),
+                                             m_nbValues(nbValues),
+                                             m_loadable(loadable),
+                                             m_accessibility(acc),
+                                             m_stringCallback(callback){ 
+            m_stringValues.resize(nbValues,"");
+        }
+
+        ~Attribute();
+
+        inline const std::string& getName(){return m_name;}
+        inline const TYPE& getType(){return m_type;}
+        inline void setFullName(const std::string& fn){m_fullName=fn;}
+        inline const std::string& getFullName(){return m_fullName;}
+
+        void load(xmlNodePtr node);
+        void save(xmlNodePtr parentNode);
+
+        inline const unsigned int& getNbValues(){return m_nbValues;}
+
+        void setStrings(const std::vector<std::string>& strings, 
+                        const int& lisID=-1) {
+            m_stringValues.assign(strings.begin(), 
+                                  strings.begin()+m_stringValues.size());
+            m_stringCallback(m_module, m_stringValues);
+            sendValuesToListeners(lisID);
+        }
+        void setStringsIfChanged(const std::vector<std::string>& strings) {
+            if(strings!=m_stringValues) {
+                setStrings(strings);
+            }
+        }
+        void initStrings(const std::vector<std::string>& strings) {
+            m_stringValues.assign(strings.begin(), 
+                                  strings.begin()+m_stringValues.size());
+            sendValuesToListeners(-1);
+        }
+        const std::string& getString(const unsigned int& s) { 
+            return m_stringValues[s];
+        }
+
+        void setFloats(const std::vector<float>& floats, 
+                       const int& lisID=-1) {
+            m_floatValues.assign(floats.begin(), 
+                                 floats.begin()+m_floatValues.size());
+            m_floatCallback(m_module, m_floatValues);
+            sendValuesToListeners(lisID);
+        }
+        void setFloatsIfChanged(const std::vector<float>& floats) {
+            if(floats!=m_floatValues) {
+                setFloats(floats);
+            }
+        }
+        void setFloatsIfChangedOrCount(const std::vector<float>& floats) {
+			m_changeCounter++;
+			if(m_changeCounter>m_count || floats!=m_floatValues) {
+                setFloats(floats);
+				m_changeCounter=0;
+            }
+        }
+        void initFloats(const std::vector<float>& floats) {
+            m_floatValues.assign(floats.begin(), 
+                                 floats.begin()+m_floatValues.size());
+            sendValuesToListeners(-1);
+        }
+        const float& getFloat(const unsigned int& f) {return m_floatValues[f];}
+        const std::vector<float>& getFloats(){return m_floatValues;}
+
+        void setInts(const std::vector<int>& ints,
+                     const int& lisID=-1) {
+            m_intValues.assign(ints.begin(), 
+                               ints.begin()+m_intValues.size());
+            m_intCallback(m_module, m_intValues);
+            sendValuesToListeners(lisID);
+        }
+        void initInts(const std::vector<int>& ints) {
+            m_intValues.assign(ints.begin(), 
+                               ints.begin()+m_intValues.size());
+            sendValuesToListeners(-1);
+        }
+        const int& getInt(const unsigned int& i) {return m_intValues[i];}
+
+        void setBools(const std::vector<bool>& bools,
+                      const int& lisID=-1) {
+            m_boolValues.assign(bools.begin(), 
+                                bools.begin()+m_boolValues.size());
+            m_boolCallback(m_module, m_boolValues);
+            sendValuesToListeners(lisID);
+        }
+        void initBools(const std::vector<bool>& bools) {
+            m_boolValues.assign(bools.begin(), 
+                                bools.begin()+m_boolValues.size());
+            sendValuesToListeners(-1);
+        }
+        bool getBool(const unsigned int& i) {return m_boolValues[i];}
+
+        void setFile(const std::string& f,
+                     const int& lisID=-1) {
+            m_stringValues[0]=f;
+            m_fileCallback(m_module, f);
+            sendValuesToListeners(lisID);
+        }
+        void initFile(const std::string& f) {m_stringValues[0]=f;}
+        const std::string& getFile() {return m_stringValues[0];}
+
+        void setAction() { m_actionCallback(m_module);}
+
+        inline const std::vector<std::string>& getValueLabels() {
+            return m_valuesLabels;
+        }
+        inline std::vector<std::string>& editValueLabels() {
+            return m_valuesLabels;
+        }
+
+		inline void setChangeCount(const int& count) {m_count=count;}
+        inline const std::vector<float>& getValuesMin() {return m_valuesMin;}
+        inline std::vector<float>& editValuesMin() {return m_valuesMin;}
+        inline const std::vector<float>& getValuesMax() {return m_valuesMax;}
+        inline std::vector<float>& editValuesMax() {return m_valuesMax;}
+
+        inline std::vector<std::vector<std::string> >& 
+                                        editStringValuesChoices() {
+            return m_stringValuesChoices;
+        }
+        inline const std::vector<std::vector<std::string> >& 
+                                        getStringValuesChoices() {
+            return m_stringValuesChoices;
+        }
+
+        inline std::vector<Listener*>& editListeners(){return m_listeners;}
+        void clearListeners();
+        void addListener(Listener*);
+        void removeListener(Listener* lis);
+        void updateListenersVec();
+        void sendValuesToListeners(const int& lisID=-1);
+
+        ACCESSIBILITY getAccessibility(){return m_accessibility;}
+        void setAccessibility(ACCESSIBILITY acc){m_accessibility=acc;}
+        void setLoadable(bool loadable){m_loadable=loadable;}
+
+    private: 
+        void getRelPathToRev(const std::string& abs, 
+                             std::string& rel);
+        void getAbsPathFromRev(const std::string& rel, 
+                               std::string& abs);
+    protected:
+        std::string m_name; 
+        std::string m_fullName;
+        TYPE m_type;
+        Module* m_module;
+        unsigned int m_nbValues;
+        bool m_loadable;
+        ACCESSIBILITY m_accessibility;
+        std::vector<float> m_floatValues;
+        std::vector<int> m_intValues;
+        std::vector<bool> m_boolValues;
+        std::vector<std::string> m_stringValues;
+		int m_changeCounter;
+		int m_count;
+
+        std::vector<std::string> m_valuesLabels;
+
+        std::vector<std::vector<std::string> > m_stringValuesChoices;
+        std::vector<float> m_valuesMin;
+        std::vector<float> m_valuesMax;
+
+        ActionCallback* m_actionCallback;
+        FileCallback* m_fileCallback;
+        FloatCallback* m_floatCallback;
+        IntCallback* m_intCallback;
+        BoolCallback* m_boolCallback;
+        StringCallback* m_stringCallback;
+
+        std::vector<Listener*> m_listeners;
+        std::map<int, Listener*> m_listenersMap;
+};
+
+class AttributeValue {
+    public: 
+        enum {ACTION, FLOAT_VALUE, INT_VALUE, STRING_VALUE} m_type;
+
+
+
+
+    private:
+        std::string m_label;
+
+        std::vector<std::string >m_values;
+
+        float m_floatValue;
+        int m_intValue;
+        std::string m_strValue;
+};
+
+
+#endif
+
diff --git a/src/modules/ContextHandler.hpp b/src/modules/ContextHandler.hpp
new file mode 100644
index 0000000..c792005
--- /dev/null
+++ b/src/modules/ContextHandler.hpp
@@ -0,0 +1,50 @@
+/***************************************************************************
+ *  ContextHandler.hpp
+ *  Part of Revil
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef ContextHandler_h
+#define ContextHandler_h
+
+#include <glm/mat4x4.hpp> 
+
+class ContextHandler {
+    public:
+        void setContextHandlerID(const int& id) {m_contextHandlerID=id;}
+        const int& getContextHandlerID(){return m_contextHandlerID;}
+		
+		inline glm::mat4& getProjMat(){return m_projMat;}
+		inline glm::mat4& getViewProjMat(){return m_viewProjMat;}
+
+		inline const float& getWidth(){return m_width;}
+		inline const float& getHeight(){return m_height;}
+
+    protected:
+        int m_contextHandlerID;
+        float m_width, m_height;
+        glm::mat4 m_projMat;
+        glm::mat4 m_viewProjMat;
+        glm::mat4 m_viewMat;
+};
+
+
+#endif
+
diff --git a/src/modules/DepthCamModule.cpp b/src/modules/DepthCamModule.cpp
new file mode 100644
index 0000000..ec9eb29
--- /dev/null
+++ b/src/modules/DepthCamModule.cpp
@@ -0,0 +1,1805 @@
+/***************************************************************************
+ *	DepthCamModule.cpp
+ *	Part of Reveal
+ *	2015-  Florent Berthaut, Alan Menit
+ *	hitmuri.net
+ ****************************************************************************/
+/*
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+/* Filtering is done using the 1€ filter by Gery Casiez et al. : 
+ * http://cristal.univ-lille.fr/~casiez/1euro */
+
+
+#include "DepthCamModule.hpp"
+
+#include "../Reveal.hpp"
+#include "SpaceModule.hpp"
+
+#include "ProjectorModule.hpp"
+
+#include "../geoms/CamGeometry.hpp"
+
+#include <glm/gtx/matrix_decompose.hpp>
+#include <glm/gtx/matrix_operation.hpp>
+#include <glm/gtx/quaternion.hpp>
+#include <glm/gtx/polar_coordinates.hpp>
+#include <glm/gtx/rotate_vector.hpp>
+#include <glm/gtx/euler_angles.hpp> 
+
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+using namespace cv;
+
+
+void* processFramesThreadFunction(void* pvParam) {
+	DepthCamModule *pThis=(DepthCamModule*)pvParam;
+	pThis->processFrames();
+	return NULL;
+}
+
+DepthCamModule::DepthCamModule():	GroupModule(),
+	DepthModule(),
+	m_deviceID(""),
+	m_open(false),
+	m_defaultWidth(1280),
+	m_defaultHeight(720),
+	m_defaultFps(60),
+	m_horizontalFOV(1),
+	m_verticalFOV(1),
+	m_mirrored(false),
+	m_notVoronoi(false)
+{
+
+	m_type="DepthCam";
+	m_name="depthcam";
+
+	m_calibrating=false;
+	m_depthType=0;
+	m_width=m_defaultWidth;
+	m_height=m_defaultHeight;
+	m_fps=m_defaultFps;
+	m_contourThreshold=30;
+	m_procSize.width=m_width;
+	m_procSize.height=m_height;
+
+	m_defaultDepthFrame = new unsigned short[m_defaultWidth*m_defaultHeight];
+	for(int i=0;i<m_defaultWidth*m_defaultHeight; ++i) {
+		m_defaultDepthFrame[i]=1000;
+	}
+
+	//geometry
+	m_camGeom = new CamGeometry(640, 480);
+	m_camGeom->registerModule(this);
+
+	//frames processing
+	m_framesThread=NULL;
+
+	//filtered frame
+	m_filterSpat=3;
+	m_maxFilterSize=51;
+	m_filterIndex=0;
+	m_prevDepthFrames = new unsigned short*[m_maxFilterSize]; 
+	for(int i=0; i<m_maxFilterSize; ++i) {
+		m_prevDepthFrames[i] 
+			= new unsigned short[m_defaultWidth*m_defaultHeight];
+		for(int j=0; j<m_defaultWidth*m_defaultHeight; ++j) {
+			m_prevDepthFrames[i][j] = 0;
+		}
+	}
+	m_filtDepthFrame = new unsigned short[m_defaultWidth*m_defaultHeight];
+	m_sumDepthFrame = new int[m_defaultWidth*m_defaultHeight];
+	for(int i=0;i<m_defaultWidth*m_defaultHeight; ++i) {
+		m_filtDepthFrame[i]=0;
+		m_sumDepthFrame[i]=0;
+	}
+
+	//one euro filter
+	m_oefXFrame = new float[m_defaultWidth*m_defaultHeight];
+	m_oefDXFrame = new float[m_defaultWidth*m_defaultHeight];
+	m_oefRate=60;
+	m_oefDCutoff=1;
+	m_oefMinCutoff=1; //decrease to remove jitter
+	m_oefBeta=0.1; //increase to remove lag
+	m_oefInit=false;
+
+
+	//initialize marker detection
+	Size imageSize(1280, 720);
+	m_detRgbImg = Mat::zeros(imageSize, CV_8UC3);
+	m_detMarkImg = Mat::zeros(imageSize, CV_8UC3);
+	m_detectingMarkers=false;
+	m_markerPosY=0;
+	m_markerRotX=0;
+	m_markerRotY=0;
+	m_maxNbMarkers=10;
+	m_fillingMarkers=false;
+	m_arucoTracker = new ArucoTracker();
+	m_imageTracker = new ImageTracker();
+	m_currentTracker = m_arucoTracker;
+	m_debuggingMarkers=false;
+	/*
+	   namedWindow("rgbcam");
+	   namedWindow("filtercam");
+	   */
+
+	//background capture
+	m_capturedBackground=false;
+	m_capturingBackground=0;
+	m_backgroundActive=false;
+
+	//attributes
+	addAttribute(new Attribute("name",
+				Attribute::STRING_ATTRIBUTE,
+				nameCallback, this, 1, Attribute::LOCAL));
+	m_attributesMap["name"]->setStrings(vector<string>(1, m_name));
+	addAttribute(new Attribute("remove",
+				Attribute::ACTION_ATTRIBUTE,
+				removeCallback, this,
+				Attribute::LOCAL));
+	addVisibleAttribute();
+	addAttribute(new Attribute("refresh_devices",
+				Attribute::ACTION_ATTRIBUTE,
+				refreshCallback, this,
+				Attribute::LOCAL));
+	addAttribute(new Attribute("open_device",
+				Attribute::STRING_ATTRIBUTE,
+				deviceCallback, this, 1,
+				Attribute::LOCAL));
+	refreshDeviceList();
+
+	addAttribute(new Attribute("close_device",
+				Attribute::ACTION_ATTRIBUTE,
+				closeCallback, this,
+				Attribute::LOCAL));
+
+	addAttribute(new Attribute("mode",
+				Attribute::STRING_ATTRIBUTE,
+				modeCallback, this, 1,
+				Attribute::LOCAL));
+	vector<string> devStr(1, "");
+	m_attributesMap["mode"]->editStringValuesChoices().assign(1,devStr);
+	m_attributesMap["mode"]->initStrings(devStr);
+
+	addAttribute(new Attribute("filter",
+				Attribute::STRING_ATTRIBUTE,
+				filterCallback, this, 1,
+				Attribute::LOCAL));
+
+	m_filters.push_back("none");
+	m_filters.push_back("lowpass");
+	m_filters.push_back("one_euro");
+	m_filters.push_back("one_euro_spatial");
+	m_attributesMap["filter"]
+		->editStringValuesChoices().assign(1, m_filters);
+	m_attributesMap["filter"]
+		->initStrings(vector<string>(1, m_filters[2]));
+	m_filter=m_filters[2];
+	m_filtering=true;
+
+	addAttribute(new Attribute("lowpass_smooth",
+				Attribute::FLOAT_ATTRIBUTE,
+				filterSizeCallback, this, 1,
+				Attribute::LOCAL));
+	m_attributesMap["lowpass_smooth"]->initFloats(vector<float>(1,10));
+
+	addAttribute(new Attribute("one_euro_jitter",
+				Attribute::FLOAT_ATTRIBUTE,
+				filterMCOCallback, this, 1,
+				Attribute::LOCAL));
+	m_attributesMap["one_euro_jitter"]->initFloats(vector<float>(1,
+				m_oefMinCutoff));
+	addAttribute(new Attribute("one_euro_reactivity",
+				Attribute::FLOAT_ATTRIBUTE,
+				filterBetaCallback, this, 1,
+				Attribute::LOCAL));
+	m_attributesMap["one_euro_reactivity"]->initFloats(vector<float>(1, 
+				m_oefBeta));
+	addAttribute(new Attribute("spatial_size",
+				Attribute::INT_ATTRIBUTE,
+				filterSpatCallback, this, 1,
+				Attribute::LOCAL));
+	m_attributesMap["spatial_size"]->initInts(vector<int>(1, m_filterSpat));
+
+	addAttribute(new Attribute("contour_threshold",
+				Attribute::FLOAT_ATTRIBUTE,
+				contourThresholdCallback, this, 1,
+				Attribute::LOCAL));
+	m_attributesMap["contour_threshold"]->initFloats(vector<float>(1,
+				m_contourThreshold));
+
+	addAttribute(new Attribute("calibrate_with_marker",
+				Attribute::ACTION_ATTRIBUTE,
+				calibrationCallback, this,
+				Attribute::LOCAL));
+
+	addTransformationAttributes();
+	m_attributesMap["scale"]->setAccessibility(Attribute::HIDDEN);
+	vector<float> posVec(3,0);
+	posVec[2]=-700;
+	m_attributesMap["position"]->setFloats(posVec);
+
+	/*
+	   addAttribute(new Attribute("capture_background",
+	   Attribute::BOOL_ATTRIBUTE,
+	   captureBackgroundCallback, this, 1,
+	   Attribute::LOCAL));
+	   */
+	addAttribute(new Attribute("markers_detection",
+				Attribute::STRING_ATTRIBUTE,
+				markersDetectionCallback, this, 1,
+				Attribute::LOCAL));
+	vector<string> detection;
+	detection.push_back("none");
+	detection.push_back("aruco");
+	detection.push_back("image");
+	m_attributesMap["markers_detection"]
+		->editStringValuesChoices().assign(1, detection);
+	m_attributesMap["markers_detection"]
+		->initStrings(vector<string>(1, detection[0]));
+	addAttribute(new Attribute("image_markers_folder", 
+				Attribute::FOLDER_OPEN_ATTRIBUTE, 
+				imageMarkersFolderCallback, this));
+
+	addAttribute(new Attribute("marker_fill_method",
+				Attribute::STRING_ATTRIBUTE,
+				markersFillMethodCallback, this, 1,
+				Attribute::LOCAL));
+	vector<string> methods;
+	methods.push_back("none");
+	methods.push_back("flood");
+	methods.push_back("voronoi");
+	m_attributesMap["marker_fill_method"]
+		->editStringValuesChoices().assign(1, methods);
+	m_attributesMap["marker_fill_method"]
+		->initStrings(vector<string>(1, methods[0]));
+	addAttribute(new Attribute("marker_output",
+				Attribute::FLOAT_ATTRIBUTE,
+				outputMarkersCallback, this, 9,
+				Attribute::OUTPUT));
+	addAttribute(new Attribute("debug_markers",
+				Attribute::BOOL_ATTRIBUTE,
+				debugMarkersCallback, this, 1,
+				Attribute::LOCAL));
+
+	Reveal::getInstance()->addUpdateObserver(this);
+
+
+	//start processing thread
+	m_framesThread = new std::thread(processFramesThreadFunction, this);
+}
+
+DepthCamModule::~DepthCamModule() {
+	if(m_framesThread) {
+		m_framesThread->join();
+		delete m_framesThread;
+	}
+	Reveal::getInstance()->removeUpdateObserver(this);
+	closeDevice();
+}
+
+void DepthCamModule::refreshDeviceList() {
+	openni::Array<openni::DeviceInfo> deviceList;
+	openni::OpenNI::enumerateDevices(&deviceList);
+	for(int d=0; d<deviceList.getSize(); ++d) {
+		cout<<"Found OpenNI device "<<deviceList[d].getUri()<<endl;
+	}
+
+	m_serialsVec.clear();
+	m_serialsMap.clear();
+	char serialNumber[1024];
+	for(int d=0; d<deviceList.getSize(); ++d) {
+		//ad-hoc code for libfreenect2
+		if(string(deviceList[d].getUri()).find("freenect")!=string::npos) {
+			string serialStr = string(deviceList[d].getUri());
+			serialStr=serialStr.substr(string("freenect2://0?serial=").size());
+			if(serialStr.find("?")==string::npos) {
+				m_serialsMap[serialStr] = deviceList[d].getUri();
+				m_serialsVec.push_back(serialStr);
+			}
+		}
+		else {
+			ostringstream oss;
+			oss<<d;
+			openni::Device dev;
+			dev.open(deviceList[d].getUri());
+			dev.getProperty(ONI_DEVICE_PROPERTY_SERIAL_NUMBER, &serialNumber);
+			m_serialsMap[string(serialNumber)] = deviceList[d].getUri();
+			m_serialsVec.push_back(string(serialNumber));
+			dev.close();
+		}
+	}
+	m_attributesMap["open_device"]
+		->editStringValuesChoices().assign(1, m_serialsVec);
+}
+
+void DepthCamModule::updateModelMatrix() {
+	GroupModule::updateModelMatrix();
+	map<int, ProjectorModule*>::iterator itProj=m_attachedProjs.begin();
+	for(; itProj!=m_attachedProjs.end(); ++itProj) {
+		itProj->second->setModelMat(m_modelMat);
+	}
+}
+
+void DepthCamModule::deleteModule() {
+	if(m_space) {
+		m_space->removeCam(this);
+	}
+	Reveal::getInstance()->unregisterOutputDepthCam(this);
+	Module::deleteModule();
+}
+
+void DepthCamModule::draw(const int& contextID,
+		const Reveal::REVIL_PROGRAM& prog,
+		map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+		const unsigned int& component) {
+
+
+	if(m_camTexMap.find(contextID)==m_camTexMap.end()) {
+		GLuint texID;
+		glGenTextures(1, &texID);
+		m_camTexMap[contextID]=texID;
+		m_upCamCounter[contextID]=0;
+		glGenTextures(1, &texID);
+		m_filtTexMap[contextID]=texID;
+		m_filtTexUpMap[contextID]=false;
+		glGenTextures(1, &texID);
+		m_markTexMap[contextID]=texID;
+		m_markTexUpMap[contextID]=false;
+		if(m_open) {
+			m_camTexUpMap[contextID]=false;
+		}
+		else {
+			m_camTexUpMap[contextID]=true;
+		}
+	}
+
+
+	/*
+	//captured background
+	if(m_backgroundActive) {
+	glActiveTexture(GL_TEXTURE1);
+	glUniform1i(uniforms[Reveal::CAMTEX2], 1);
+	glBindTexture(GL_TEXTURE_2D, m_camTexMap2[contextID]);
+	if(m_capturedBackground) {
+	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
+	m_width, m_height, 0,
+	GL_RGB, GL_UNSIGNED_BYTE,
+	m_backImg.data);
+	m_capturedBackground=false;
+	}
+	}
+	*/
+
+	if(m_filtering) {
+		glActiveTexture(GL_TEXTURE1);
+		glUniform1i(uniforms[Reveal::CAMTEXFIL], 1);
+		glBindTexture(GL_TEXTURE_2D, m_filtTexMap[contextID]);
+		if(m_framesLock.try_lock()) {
+			if(m_filtTexUpMap[contextID]) {
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+				if(m_open) {
+					if(m_filtDepthFrame!=NULL) {
+						glTexImage2D(GL_TEXTURE_2D, 0, GL_R16,
+								m_width, m_height, 0,
+								GL_RED, GL_UNSIGNED_SHORT,
+								m_filtDepthFrame);
+					}
+				}
+				m_filtTexUpMap[contextID]=false;
+			}
+			m_framesLock.unlock();
+		}
+	}
+	glActiveTexture(GL_TEXTURE0);
+	glUniform1i(uniforms[Reveal::CAMTEX], 0);
+	glBindTexture(GL_TEXTURE_2D, m_camTexMap[contextID]);
+	if(m_camTexUpMap[contextID]) {
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		if(m_open) {
+			glTexImage2D(GL_TEXTURE_2D, 0, GL_R16,
+					m_width, m_height, 0,
+					GL_RED, GL_UNSIGNED_SHORT,
+					(unsigned char*)m_depthFrame.getData());
+		}
+		m_camTexUpMap[contextID]=false;
+	}
+	glActiveTexture(GL_TEXTURE2);
+	glUniform1i(uniforms[Reveal::MARKTEX], 2);
+	glBindTexture(GL_TEXTURE_2D, m_markTexMap[contextID]);
+	if(m_detectingMarkers) {
+		if(m_framesLock.try_lock()) {
+			if(m_markTexUpMap[contextID]) {
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+				glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+				if(m_open) {
+					if(m_markersFrame!=NULL) {
+						glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,
+								m_width, m_height, 0,
+								GL_RGB, GL_UNSIGNED_BYTE,
+								m_markersFrame);
+					}
+				}
+				m_markTexUpMap[contextID]=false;
+			}
+
+			vector<float> mark;
+			vector<s_markerAndTime>::iterator it=m_sentDetectedMarkers.begin();
+			for(; it != m_sentDetectedMarkers.end(); it++) {
+				mark.push_back(m_depthID+it->id);
+				mark.push_back(1);
+				/*
+				   float depth = m_rgbDepthImg.at<cv::Vec3w>
+				   (it->y, 
+				   it->x)[2];
+				   glm::vec4 pos((it->x/m_width-0.5)
+				 *depth*tan(m_horizontalFOV/2.0)*2.0, 
+				 (0.5-it->y/m_height)
+				 *depth*tan(m_verticalFOV/2.0)*2.0,
+				 depth, 1.0);
+				 pos = m_modelMat * pos;
+				 pos[0]*=-1;
+				 mark.push_back(pos[0]);
+				 mark.push_back(pos[1]);
+				 mark.push_back(pos[2]);
+				 */
+
+				glm::vec3 pos(0, 0, 0);
+				for(int c=0; c<4; c++) {
+					float depth = m_rgbDepthImg.at<cv::Vec3w>
+						(it->corners[c].y, 
+						 it->corners[c].x)[2];
+					glm::vec4 cpos((it->corners[c].x/m_width-0.5)
+							*depth*tan(m_horizontalFOV/2.0)*2.0, 
+							(0.5-it->corners[c].y/m_height)
+							*depth*tan(m_verticalFOV/2.0)*2.0,
+							depth, 1.0);
+					cpos = m_modelMat * cpos;
+					cpos[0]*=-1;
+					for(int i=0; i<3; ++i) {
+						it->corners3D[c][i]=cpos[i];
+						pos[i]+=cpos[i]/4.0;
+					}
+				}
+
+				//compute position
+				mark.push_back(pos[0]);
+				mark.push_back(pos[1]);
+				mark.push_back(pos[2]);
+
+				//compute rotation
+				glm::vec3 markUp = glm::normalize(it->corners3D[1] 
+						- it->corners3D[2]);
+				glm::vec3 markR = glm::normalize(it->corners3D[1] 
+						- it->corners3D[0]);
+				glm::vec3 markN = glm::normalize(glm::cross(markR, markUp));
+				glm::mat4x4 markM( //r,up,n
+						markR[0], markR[1], markR[2], 0.0, //inverser
+						markUp[0], markUp[1], markUp[2],0.0,
+						markN[0], markN[1], markN[2], 0.0,
+						0.0, 0.0, 0.0, 1.0
+						);
+				float rx, ry, rz;
+				glm::extractEulerAngleXYZ(markM, rx, ry, rz);
+				float tmprx = rx;
+				rx=-rz;
+				rz=-tmprx;
+				markM = glm::eulerAngleXYZ(rx,ry,rz);
+
+				glm::quat markQ = glm::toQuat(markM);
+				/*
+				   cout<<"Up:"<<markUp.x<<" "<<markUp.y<<" "<<markUp.z<<endl;
+				   cout<<"R:"<<markR.x<<" "<<markR.y<<" "<<markR.z<<endl;
+				   cout<<"N:"<<markN.x<<" "<<markN.y<<" "<<markN.z<<endl;
+				   cout<<markQ[0]<<" "<<markQ[1]<<" "<<markQ[2]<<" "<<markQ[2]<<endl;
+				   */
+				mark.push_back(markQ[0]);
+				mark.push_back(markQ[1]);
+				mark.push_back(markQ[2]);
+				mark.push_back(markQ[3]);
+				m_attributesMap["marker_output"]->setFloats(mark);
+				mark.clear();
+			}
+			m_sentDetectedMarkers.clear();
+			it=m_sentRemovedMarkers.begin();
+			for(; it!= m_sentRemovedMarkers.end(); it++) {
+				mark.push_back(m_depthID+it->id);
+				mark.push_back(0);
+				mark.push_back(0);
+				mark.push_back(0);
+				mark.push_back(0);
+				mark.push_back(0);
+				mark.push_back(0);
+				mark.push_back(0);
+				mark.push_back(0);
+				m_attributesMap["marker_output"]->setFloats(mark);
+				mark.clear();
+			}
+			m_sentRemovedMarkers.clear();
+			m_framesLock.unlock();
+		}
+	}
+	glUniform1i(uniforms[Reveal::CAMFILTER], m_filtering);
+	glUniform1f(uniforms[Reveal::CAMCONTOURTHRESH], m_contourThreshold);
+	glUniform1f(uniforms[Reveal::CAMXRESO], m_width);
+	glUniform1f(uniforms[Reveal::CAMYRESO], m_height);
+	glUniform1f(uniforms[Reveal::CAMXZFACTOR], tan(m_horizontalFOV/2.0)*2.0);
+	glUniform1f(uniforms[Reveal::CAMYZFACTOR], tan(m_verticalFOV/2.0)*2.0);
+	glUniform1f(uniforms[Reveal::CAMMARKERS], m_fillingMarkers);
+	glUniform1i(uniforms[Reveal::BACKGROUND], m_backgroundActive);
+	DepthModule::draw(contextID, prog, uniforms, component);
+}
+
+void DepthCamModule::setSpace(SpaceModule* spa) {
+	DepthModule::setSpace(spa);
+	m_space->registerGeom(m_camGeom);
+}
+
+void DepthCamModule::setMode(const std::string& mode) {
+	m_defaultWidth=m_depthModes[mode].width;
+	m_defaultHeight=m_depthModes[mode].height;
+	m_defaultFps=m_depthModes[mode].fps;
+	if(m_open) {
+		openDevice(m_deviceID);
+	}
+}
+
+void DepthCamModule::openDevice(const std::string& devStr, bool calib) {
+	if(devStr.size()==0) {
+		return;
+	}
+
+	if(m_open) {
+		closeDevice();
+	}
+
+	openni::Status rc;
+
+	if(m_serialsMap.find(devStr)==m_serialsMap.end()) {
+		cout<<"Could not open OpenNI device "<<devStr<<endl;
+		return;
+	}
+
+	rc = m_device.open(m_serialsMap[devStr].c_str());
+	if(rc != openni::STATUS_OK) {
+		cout<<"Could not open OpenNI device "<<devStr<<endl;
+		return;
+	}
+
+	openni::VideoMode depthVideoMode;
+
+	//create streams
+	rc = m_depth.create(m_device, openni::SENSOR_DEPTH);
+	if(rc!=openni::STATUS_OK) {
+		cout<<"Could not create depth stream for device "<<devStr<<endl;
+		return;
+	}
+
+	//list and store video modes for this device
+	m_depthModes.clear();
+	m_modes.clear();
+	const openni::Array<openni::VideoMode>& modes = m_depth.getSensorInfo()
+		.getSupportedVideoModes();
+	for(int m=0; m<modes.getSize(); ++m) {
+		if(modes[m].getPixelFormat()==openni::PIXEL_FORMAT_DEPTH_1_MM) {
+			string name = to_string(modes[m].getResolutionX())
+				+"x"+to_string(modes[m].getResolutionY())
+				+"@"+to_string(modes[m].getFps());
+			m_modes.push_back(name);
+			m_depthModes[name]=DepthMode();
+			m_depthModes[name].width=modes[m].getResolutionX();
+			m_depthModes[name].height=modes[m].getResolutionY();
+			m_depthModes[name].fps=modes[m].getFps();
+		}
+	}
+
+	if(m_deviceID.compare("")==0) { //no already opened device
+		//open a default mode
+		int defaultMode = 0;
+		m_defaultWidth=m_depthModes[m_modes[defaultMode]].width;
+		m_defaultHeight=m_depthModes[m_modes[defaultMode]].height;
+		m_defaultFps=m_depthModes[m_modes[defaultMode]].fps;
+		m_attributesMap["mode"]->editStringValuesChoices().assign(1,m_modes);
+		m_attributesMap["mode"]->initStrings(vector<string>(1,
+					m_modes[defaultMode]));
+		Reveal::getInstance()->refreshModules();
+	}
+
+	if(calib) { //fixed reso if calibrating FIXME pick the first / highest one ?
+		m_width=640;
+		m_height=480;
+		m_fps=30;
+	}
+	else {
+		m_width=m_defaultWidth;
+		m_height=m_defaultHeight;
+		m_fps=m_defaultFps;
+	}
+
+	//set depth stream size
+	depthVideoMode.setResolution(m_width, m_height);
+	depthVideoMode.setFps(m_fps);
+	depthVideoMode.setPixelFormat(openni::PIXEL_FORMAT_DEPTH_1_MM);
+	openni::Status rc1 = m_depth.setVideoMode(depthVideoMode);
+	if(rc1!=openni::STATUS_OK) {
+		cout<<"Could not set depth video mode"<<endl;
+		return;
+	}
+
+	//refresh geom size
+	m_camGeom->setSize(m_width, m_height);
+
+	//color stream
+	rc = m_color.create(m_device, openni::SENSOR_COLOR);
+	openni::VideoMode colorVideoMode;
+	if(rc==openni::STATUS_OK) {
+		colorVideoMode.setResolution(m_width, m_height);
+		colorVideoMode.setFps(m_fps);
+		colorVideoMode.setPixelFormat(openni::PIXEL_FORMAT_RGB888);
+		rc = m_color.setVideoMode(colorVideoMode);
+		if(rc!=openni::STATUS_OK) {
+			cout<<"Could not set color video mode"<<endl;
+		}
+	}
+	else {
+		m_color.stop();
+		cout<<"Could not create color stream"<<endl;
+		/*
+		   rc = m_color.create(m_device, openni::SENSOR_IR);
+		   if(rc==openni::STATUS_OK) {
+		   colorVideoMode.setResolution(m_width, m_height);
+		   colorVideoMode.setFps(m_fps);
+		   colorVideoMode.setPixelFormat(openni::PIXEL_FORMAT_RGB888);
+		   rc = m_color.setVideoMode(colorVideoMode);
+		   if(rc!=openni::STATUS_OK) {
+		   cout<<"Could not set ir video mode"<<endl;
+		   }
+		   }
+		   else {
+		   cout<<"Could not create ir stream"<<endl;
+		   return;
+		   }
+		   */
+	}
+
+	//start only depth for now
+	rc = m_depth.start();
+	if(!m_depth.isValid()) {
+		cout<<"Depth Cam: No valid streams"<<endl;
+		return;
+	}
+
+	m_horizontalFOV = m_depth.getHorizontalFieldOfView();
+	m_verticalFOV = m_depth.getVerticalFieldOfView();
+	cout<<m_horizontalFOV<<" "<<m_verticalFOV<<endl;
+
+	m_depth.setMirroringEnabled(false);
+	m_color.setMirroringEnabled(false);
+	m_device.setImageRegistrationMode(
+			openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR);
+	m_streams = new openni::VideoStream*[2];
+	m_streams[0] = &m_depth;
+
+	m_gotColor=false;
+	m_gotDepth=false;
+	m_colorActivated=false;
+
+	m_open=true;
+	m_deviceID=devStr;
+	cout<<"Opened OpenNI device "<<m_deviceID
+		<<" of "<<m_width<<"x"<<m_height
+		<<" @ "<<m_fps<<"FPS"<<endl;
+}
+
+void DepthCamModule::closeDevice(const bool& clear) {
+	if(m_open) {
+		m_open=false;
+		m_depth.destroy();
+		m_color.destroy();
+		delete [] m_streams;
+		m_device.close();
+
+		if(clear) {
+			vector<string> devStr(1, "");
+			m_attributesMap["open_device"]->initStrings(devStr);
+			m_attributesMap["mode"]->initStrings(devStr);
+			m_deviceID="";
+		}
+	}
+}
+
+void DepthCamModule::setModuleName(const std::string& val) {
+	Module::setModuleName(val);
+	if(m_space) {
+		m_space->refreshDepthCamList();
+	}
+}
+
+void DepthCamModule::activateColor() {
+	if(m_open) {
+		openni::Status rc = m_color.start();
+		if(!m_color.isValid()) {
+			cout<<"Color Cam: No valid streams"<<endl;
+			return;
+		}
+		m_colorActivated=true;
+		m_color.setMirroringEnabled(false);
+		m_streams[1] = &m_color;
+		m_device.setImageRegistrationMode(
+				openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR);
+		m_device.setDepthColorSyncEnabled(false);
+	}
+}
+
+void DepthCamModule::deactivateColor() {
+	if(m_open) {
+		m_color.stop();
+		m_colorActivated=false;
+	}
+}
+
+bool DepthCamModule::getFrames() {
+	bool res=false;
+
+	openni::VideoStream *tab[1];
+	if(m_open){
+		tab[0] = &m_depth;
+		int changedIndex=-1;
+		openni::OpenNI::waitForAnyStream(tab,1,&changedIndex,0);
+		if(changedIndex == 0) {
+			m_depth.readFrame(&m_depthFrame);
+			if(m_framesLock.try_lock()) {
+				m_gotDepth=true;
+
+				createMatDepth();
+				m_framesLock.unlock();
+			}
+			if(m_capturingBackground>0) {
+				captureBackground();
+			}
+		}
+		if(m_colorActivated){
+			tab[0] = &m_color;
+			openni::OpenNI::waitForAnyStream(tab,1,&changedIndex,0);
+			if(changedIndex == 0) {
+				m_color.readFrame(&m_colorFrame);	
+				if(m_framesLock.try_lock()) {
+					m_gotColor=true;
+					createMatColor();
+					m_framesLock.unlock();
+				}
+			}
+		}
+		res = m_gotDepth && (m_gotColor || !m_colorActivated);
+	}
+	return res;
+}
+
+void DepthCamModule::attachProj(ProjectorModule* proj) {
+	int i=0;
+	while(m_attachedProjs.find(i)!=m_attachedProjs.end()) {
+		++i;
+	}
+	m_attachedProjs[i]=proj;
+	proj->setProjID(i);
+	updateModelMatrix();
+}
+
+void DepthCamModule::detachProj(ProjectorModule* proj) {
+	m_attachedProjs.erase(proj->getProjID());
+}
+
+void DepthCamModule::setCaptureBackground(const bool& cap) {
+	if(cap) {
+		m_capturingBackground=50;
+		m_capturedBackground=false;
+		m_backgroundActive=true;
+		cv::Size imageSize(m_width, m_height);
+		m_backImg = cv::Mat::zeros(imageSize, CV_16UC1);
+	}
+	else {
+		m_capturingBackground=0;
+		m_capturedBackground=false;
+		m_backgroundActive=false;
+	}
+}
+
+void DepthCamModule::captureBackground() {
+	cv::Size imageSize(m_width, m_height);
+	for(int j=0; j<imageSize.height; ++j) {
+		for(int i=0; i<imageSize.width; ++i) {
+			ushort& dPix = m_backImg.at<ushort>(j,i);
+			int coord=j*imageSize.width+i;
+			openni::DepthPixel depthPix =
+				((openni::DepthPixel*) m_depthFrame.getData())[coord];
+			if(depthPix>dPix) {
+				dPix=depthPix;
+			}
+		}
+	}
+	m_capturingBackground--;
+	if(m_capturingBackground<=0) {
+		m_capturedBackground=true;
+	}
+}
+
+void DepthCamModule::setMarkersDetection(const string& val) {
+	if(m_open) {
+		m_framesLock.lock();
+		m_framesLock.unlock();
+
+		if(val.compare("none")!=0) {
+			m_detectingMarkers=true;
+			activateColor();
+			if(val.compare("aruco")==0) {
+				m_currentTracker = m_arucoTracker;
+			}
+			else {
+				m_currentTracker = m_imageTracker;
+			}
+			m_currentTracker->init();
+		}
+		else {
+			m_detectingMarkers=false;
+			deactivateColor();
+		}
+	}
+}
+
+void DepthCamModule::setImageMarkersFolder(const std::string& fol) {
+	m_imageTracker->setImgFolder(fol);
+	m_imageTracker->init();
+}
+
+void DepthCamModule::setMarkersFillMethod(const std::string& val) {
+	if(!val.compare("none")) {
+		m_fillingMarkers=false;
+	}
+	else {
+		m_fillingMarkers=true;
+		if(!val.compare("voronoi")) {
+			m_notVoronoi=false;
+		}
+		else {
+			m_notVoronoi=true;
+		}
+	}
+}
+
+void DepthCamModule::update(const int& timeDiffMs) {
+	if(getFrames()) {
+		map<int, bool>::iterator itUp = m_camTexUpMap.begin();
+		for(; itUp!=m_camTexUpMap.end(); ++itUp) {
+			itUp->second = true;
+		}
+	}
+}
+
+
+void DepthCamModule::gotAttributeListenersUpdate(Attribute* att) {
+	/*
+	   int nbLis = m_attributesMap["cursor"]->editListeners().size();
+	   if(nbLis>0) {
+	//		  m_outCursUniform->set(float(1));
+	Reveal::getInstance()->registerOutputDepthCam(this);
+	}
+	else {
+	//		  m_outCursUniform->set(float(0));
+	Reveal::getInstance()->unregisterOutputDepthCam(this);
+	}
+	*/
+}
+
+void DepthCamModule::processCursor(const std::vector<float>& pos) {
+	/*
+	//filter cursor position
+	unsigned int v=0;
+	for(unsigned int mv=0; mv<m_filterCursorValues.size(); ++mv) {
+	m_filterCursorSums[mv]-=m_filterCursorValues[mv].front();
+	m_filterCursorValues[mv].pop_front();
+	m_filterCursorValues[mv].push_back(pos[v]);
+	m_filterCursorSums[mv]+=m_filterCursorValues[mv].back();
+	m_cursorValues[mv]=m_filterCursorSums[mv]/m_filterCursorSize;
+	if(v+1<pos.size()) {
+	++v;
+	}
+	}
+
+	//set attribute
+	m_attributesMap["cursor"]->setFloatsIfChanged(m_cursorValues);
+	*/
+}
+
+void DepthCamModule::refreshProjList(const vector<ProjectorModule*> projs) {
+	vector<string> labels;
+	labels.push_back("none");
+	vector<ProjectorModule*>::const_iterator itProj=projs.begin();
+	for(; itProj!=projs.end(); ++itProj) {
+		labels.push_back((*itProj)->getName());
+	}
+}
+
+
+//-----------------------Calibration------------------------------------
+
+static void cbMarkerPosY(int y, void* mod) {
+	static_cast<DepthCamModule*>(mod)->setCalibMarkerPosY(y);
+}
+
+void DepthCamModule::setCalibMarkerPosY(const int& y) {
+	m_markerPosY=y;
+}
+
+static void cbMarkerRotX(int x, void* mod) {
+	static_cast<DepthCamModule*>(mod)->setCalibMarkerRotX(x);
+}
+
+void DepthCamModule::setCalibMarkerRotX(const int& x) {
+	m_markerRotX=x;
+}
+
+static void cbMarkerRotY(int y, void* mod) {
+	static_cast<DepthCamModule*>(mod)->setCalibMarkerRotY(y);
+}
+
+void DepthCamModule::setCalibMarkerRotY(const int& y) {
+	m_markerRotY=y;
+}
+
+static void cbCalib(int c, void* mod) {
+	DepthCamModule* cam = static_cast<DepthCamModule*>(mod);
+	cam->setCalib(c);
+}
+
+void DepthCamModule::setCalib(const int& c) {
+	m_calibrating=c;
+	if(c==0) {
+		m_calibrationStopped=true;
+	}
+}
+
+void DepthCamModule::calibrate() {
+	if(!m_open) {
+		return;
+	}
+	m_calibrating=0;
+	m_calibrationStopped=false;
+
+	namedWindow("DepthCamRGB");
+	namedWindow("Controls");
+	createTrackbar("MarkerPosY", "Controls",
+			&m_markerPosY, 3000, cbMarkerPosY, this);
+	createTrackbar("MarkerRotX", "Controls",
+			&m_markerRotX, 360, cbMarkerRotX, this);
+	createTrackbar("MarkerRotY", "Controls",
+			&m_markerRotY, 360, cbMarkerRotY, this);
+	createTrackbar("Calibrate (1:Start, 0:Cancel)", "Controls",
+			&m_calibrating, 1, cbCalib, this);
+
+
+	Size imageSize(m_width, m_height);
+	Mat kinectRgbImg = Mat::zeros(imageSize, CV_8UC3);
+	Mat kinectDepthImg = cv::Mat::zeros(imageSize, CV_32FC1);
+
+	activateColor();
+
+	while(!m_calibrationStopped ) {
+		for(int j=0; j<imageSize.height; ++j) {
+			for(int i=0; i<imageSize.width; ++i) {
+				kinectDepthImg.at<float>(j,i)=0;
+			}
+		}
+		int nbFrames=10;
+		int framesCnt=0;
+		while(framesCnt<nbFrames) {
+			if(getFrames()) {
+				//copy to opencv mat
+				for(int j=0; j<imageSize.height; ++j) {
+					for(int i=0; i<imageSize.width; ++i) {
+						cv::Vec3b& pix = kinectRgbImg.at<cv::Vec3b>(j,i);
+						float& dPix = kinectDepthImg.at<float>(j,i);
+						int coord=j*imageSize.width+i;
+						openni::RGB888Pixel colorPix =
+							((openni::RGB888Pixel*)m_colorFrame.getData())[coord];
+						pix[0]=colorPix.r;
+						pix[1]=colorPix.g;
+						pix[2]=colorPix.b;
+
+						openni::DepthPixel depthPix =
+							((openni::DepthPixel*)m_depthFrame.getData())[coord];
+						dPix += float(depthPix)/float(nbFrames);;
+					}
+				}
+				framesCnt++;
+			}
+		}
+
+		//find marker
+		vector<vector<cv::Point2f> > corners;
+		vector<int> ids;
+		cv::aruco::detectMarkers(kinectRgbImg, 
+				cv::aruco::getPredefinedDictionary(cv::aruco::DICT_ARUCO_ORIGINAL),
+				corners,
+				ids);
+		cv::aruco::drawDetectedMarkers(kinectRgbImg, corners);
+		imshow("DepthCamRGB", kinectRgbImg);
+		waitKey(10);
+
+		glm::vec3 cornersD[4];
+		glm::vec3 center(0.0, 0.0, 0.0);
+		bool valid=false;
+		for(unsigned int m=0; m<ids.size(); ++m) {
+			if(ids[m]>=0) {
+				valid=true;
+				//retrieve cam space coordinates
+				for(int c=0; c<4; c++) {
+
+					glm::vec2 dCoord = glm::vec2(corners[m][c].x, 
+							corners[m][c].y);
+					float& dPix = kinectDepthImg.at<float>(corners[m][c].y,
+							corners[m][c].x);
+					if(dPix<500 || dPix>7000) {
+						valid=false;
+					}
+					openni::CoordinateConverter::convertDepthToWorld(
+							m_depth,
+							int(dCoord.x),
+							int(dCoord.y),
+							int(dPix),
+							&cornersD[c].x, 
+							&cornersD[c].y, 
+							&cornersD[c].z);
+					cornersD[c].z*=1.0;
+					center.x+=cornersD[c].x/4.0;
+					center.y+=cornersD[c].y/4.0;
+					center.z+=cornersD[c].z/4.0;
+				}
+			}
+		}
+
+		if(valid && m_calibrating) {
+			cout<<"center at "<<center.x<<" "
+				<<center.y<<" "
+				<<center.z<<endl;
+			for(int c=0;c<4;++c) {
+				cout<<"corner "<<c<<" "<<cornersD[c].x<<" "
+					<<cornersD[c].y<<" "<<cornersD[c].z<<endl;
+			}
+
+			//retrieve world marker rotation
+			double rotX = double(m_markerRotX)/180.0*M_PI;
+			double rotY = double(m_markerRotY)/180.0*M_PI;
+			glm::mat4 markRotMat = glm::eulerAngleYXZ(rotY, rotX, 0.0);
+
+			//cam space marker center translation
+			glm::mat4 markMat = glm::translate(glm::mat4(1.0), center);
+
+			//cam space marker rotation
+			glm::vec3 markUp = glm::normalize(cornersD[1] - cornersD[2]);
+			glm::vec3 markR = glm::normalize(cornersD[1] - cornersD[0]);
+			glm::vec3 markN = glm::normalize(glm::cross(markR, markUp));
+			cout<<"Up:"<<markUp.x<<" "<<markUp.y<<" "<<markUp.z<<endl;
+			cout<<"R:"<<markR.x<<" "<<markR.y<<" "<<markR.z<<endl;
+			cout<<"N:"<<markN.x<<" "<<markN.y<<" "<<markN.z<<endl;
+			glm::mat4x4 markM( //r,up,n
+					markR[0], markR[1], markR[2], 0.0,
+					markUp[0], markUp[1], markUp[2],0.0,
+					markN[0], markN[1], markN[2], 0.0,
+					0.0, 0.0, 0.0, 1.0
+					);
+			float rx, ry, rz;
+			glm::extractEulerAngleXYZ(markM, rx, ry, rz);
+			glm::mat4 rotMat = glm::eulerAngleXYZ(rx,ry,rz);
+
+			//get transform of cam in marker space 
+			glm::mat4 camMat = inverse(markMat*rotMat);
+
+			//apply physical marker rotation to retrieve world space transfo
+			camMat = inverse(markRotMat)*camMat;
+
+			//assign model matrix and update attached projectors
+			m_parentMat = glm::mat4(1.0);
+			setModelMat(camMat);
+			updateModelMatrix();
+
+			m_calibrationStopped=true; 
+		}
+		usleep(10000);
+	}
+	cout<<"Camera Calibration Done"<<endl;
+
+	deactivateColor();
+	destroyWindow("DepthCamRGB");
+	destroyWindow("Controls");
+	waitKey(10);
+}
+
+//---------------------Frames process-------------------------------
+
+void DepthCamModule::processFrames() {
+	bool done=false;
+	while(!done){
+		if(m_open) {
+			bool gotFrame = false;
+
+			m_framesLock.lock();
+
+			//update filtered frame texture
+			if(m_gotDepth) {
+				if(m_filtering) {
+					filterDepthFrame();
+				}
+
+				if(m_detectingMarkers) {
+					if(m_gotColor && m_gotDepth){
+						gotFrame = createMatDepthAndColor();
+						m_gotColor = m_gotDepth = false;
+					}
+					if(gotFrame) {
+						detectMarkers();
+					}
+				}
+				else {
+					m_gotDepth=false;
+				}
+				m_gotDepth=false;
+			}
+			m_framesLock.unlock();
+
+		}
+		usleep(50000);
+	}
+}
+
+bool DepthCamModule::createMatDepth(){
+
+	if(m_width!=m_procSize.width) {
+		m_procSize.width=m_width;
+		m_procSize.height=m_height;
+	}
+
+	m_depthImg = cv::Mat::zeros(m_procSize, CV_16UC1);
+
+	for(int j=0; j<m_procSize.height; ++j) {
+		for(int i=0; i<m_procSize.width; ++i) {
+			ushort& dPix = m_depthImg.at<ushort>(j,i);
+
+			int coord=j*m_procSize.width+i;
+
+			openni::DepthPixel depthPix =
+				((openni::DepthPixel*) m_depthFrame.getData())[coord];
+
+			dPix = depthPix;
+		}
+	}
+
+	return true;
+}
+
+bool DepthCamModule::createMatColor(){
+	if(m_width!=m_procSize.width) {
+		m_procSize.width=m_width;
+		m_procSize.height=m_height;
+	}
+
+	m_rgbImg = cv::Mat::zeros(m_procSize, CV_8UC3);
+
+	for(int j=0; j<m_procSize.height; ++j) {
+		for(int i=0; i<m_procSize.width; ++i) {
+			cv::Vec3b& cPix = m_rgbImg.at<cv::Vec3b>(j,i);
+
+			int coord=j*m_procSize.width+i;
+
+			openni::RGB888Pixel colorPix =
+				((openni::RGB888Pixel*) m_colorFrame.getData())[coord];
+
+			cPix[0]=colorPix.b;
+			cPix[1]=colorPix.g;
+			cPix[2]=colorPix.r;
+		}
+	}
+
+	return true;
+}
+
+bool DepthCamModule::createMatDepthAndColor(){
+	m_resImg = cv::Mat::zeros(m_procSize, CV_8UC3);
+	m_rgbDepthImg = cv::Mat::zeros(m_procSize, CV_16UC3);
+
+	for(int j=0; j<m_procSize.height; ++j) {
+		for(int i=0; i<m_procSize.width; ++i) {
+			cv::Vec3b cPix = m_rgbImg.at<cv::Vec3b>(j,i);
+			ushort dPix = m_depthImg.at<ushort>(j,i);
+			cv::Vec3b &gl_pix = m_resImg.at<cv::Vec3b>(j,i);
+			cv::Vec3w &color_depth_pix = m_rgbDepthImg.at<cv::Vec3w>(j,i);
+
+			color_depth_pix[0] = cPix[0]*255;
+			color_depth_pix[1] = cPix[1]*255;
+			color_depth_pix[2] = dPix;
+
+			gl_pix[0] = 0;
+			gl_pix[1] = 0;
+			gl_pix[2] = 0;
+		}
+	}
+
+	m_finalCombin = cv::Mat::zeros(m_procSize, CV_8UC3);
+	m_rgbDepthImg.convertTo(m_finalCombin, CV_8U, 255.0 / (5000));
+
+	return true;
+}
+
+//----------------------Filtering-----------------------------------
+
+void DepthCamModule::setFilter(const std::string& fil) {
+	m_filter=fil;
+	if(m_filter.compare("none")==0) {
+		m_filtering=false;
+	}
+	else {
+		m_filtering=true;
+	}
+}
+
+void DepthCamModule::setFilterSize(int siz) {
+	m_framesLock.lock();
+	if(siz<m_maxFilterSize && siz>=0) {
+		m_filterSize=siz;
+		for(int i=0; i<m_procSize.width*m_procSize.height; ++i) {
+			for(int f=0; f<m_filterSize; ++f) {
+				m_prevDepthFrames[f][i]=0;
+			}
+			m_sumDepthFrame[i]=0;
+		}
+	}
+	m_framesLock.unlock();
+}
+
+void DepthCamModule::setFilterSpat(int spat) {
+	m_framesLock.lock();
+	m_filterSpat=spat;
+	m_framesLock.unlock();
+}
+
+void DepthCamModule::setFilterMCO(float mco) {
+	m_framesLock.lock();
+	m_oefMinCutoff=mco;
+	m_framesLock.unlock();
+}
+
+void DepthCamModule::setFilterBeta(float beta) {
+	m_framesLock.lock();
+	m_oefBeta=beta;
+	m_framesLock.unlock();
+}
+
+void DepthCamModule::filterDepthFrame() {
+	if(m_filter.compare("lowpass")==0) {
+		for(int j=0; j<m_procSize.height; ++j) {
+			for(int i=0; i<m_procSize.width; ++i) {
+				ushort dPix = m_depthImg.at<ushort>(j,i);
+				int coord = j*m_procSize.width+i;
+				m_sumDepthFrame[coord]-=
+					int(m_prevDepthFrames[m_filterIndex][coord]);
+				m_prevDepthFrames[m_filterIndex][coord]=(unsigned short)dPix;
+				m_sumDepthFrame[coord]+=
+					int(m_prevDepthFrames[m_filterIndex][coord]);
+				m_filtDepthFrame[coord] = float(m_sumDepthFrame[coord])
+					/ float(m_filterSize);
+			}
+		}
+		m_filterIndex=(m_filterIndex+1)%m_filterSize;
+	}
+	else {
+		//1€ filter 
+		for(int j=0; j<m_procSize.height; ++j) {
+			for(int i=0; i<m_procSize.width; ++i) {
+				ushort dPix = m_depthImg.at<ushort>(j,i);
+				//spatial filter
+				if(m_filter.compare("one_euro_spatial")==0) {
+					float sum=0, count=0;
+					for(int dy=max<int>(j-m_filterSpat,0); 
+							dy<=min<int>(j+m_filterSpat,m_procSize.height-1); 
+							dy++) {
+						for(int dx=max<int>(i-m_filterSpat,0); 
+								dx<=min<int>(i+m_filterSpat,m_procSize.width-1); 
+								dx++) {
+							ushort aPix = m_depthImg.at<ushort>(dy,dx);
+							if(abs(aPix-dPix)<m_contourThreshold) {
+								sum+=aPix;
+								count+=1;
+							}
+						}
+					}
+					dPix = sum/count;
+				}
+
+				int coord = j*m_procSize.width+i;
+				float dx=0;
+				if(m_oefInit) {
+					dx=(float(dPix)-m_oefXFrame[coord])*m_oefRate;
+				}
+				float dalpha = 1.0 / (1.0 
+						+ (1.0/(2*M_PI*m_oefDCutoff))
+						/ (1.0/m_oefRate));
+				float edx = dx*dalpha 
+					+ (1-dalpha)*(!m_oefInit?dx:m_oefDXFrame[coord]); 
+				m_oefDXFrame[coord]=edx;
+				float cutoff = m_oefMinCutoff + m_oefBeta*fabs(edx);
+				float alpha = 1.0 / (1.0 
+						+ (1.0/(2*M_PI*cutoff))
+						/ (1.0/m_oefRate));
+
+				m_oefXFrame[coord] = float(dPix)*alpha 
+					+ (1-alpha)*(!m_oefInit?float(dPix):m_oefXFrame[coord]); 
+				m_filtDepthFrame[coord]=m_oefXFrame[coord];
+			}
+		}
+		if(!m_oefInit) {
+			m_oefInit=true;
+		}
+	}
+
+	map<int, bool>::iterator itUp = m_filtTexUpMap.begin();
+	for(; itUp!=m_filtTexUpMap.end(); ++itUp) {
+		itUp->second=true;
+	}
+}
+
+
+//-----------------------Markers------------------------------------
+
+void DepthCamModule::detectMarkers() {
+
+	vector<vector<cv::Point2f> > corners;
+	vector<int> ids;
+
+	m_currentTracker->track(m_rgbImg, corners, ids);
+
+	filterMarkers(corners, ids);
+
+	//if got any, do filling if needed
+	if(!m_aliveMarkers.empty() && m_fillingMarkers){
+		globalFunction(m_finalCombin);
+	}
+
+	m_sentDetectedMarkers = m_detectedMarkers;
+	m_sentRemovedMarkers = m_removedMarkers;
+	m_removedMarkers.clear();
+
+	m_markersFrame = m_resImg.data;
+	map<int, bool>::iterator itUp = m_markTexUpMap.begin();
+	for(; itUp!=m_markTexUpMap.end(); ++itUp) {
+		itUp->second=true;
+	}
+
+	if(m_debuggingMarkers){
+		showAliveMarkers();
+	}
+}
+
+
+void DepthCamModule::draw_point(cv::Mat& img, cv::Point2f fp){
+	return;
+}
+
+void DepthCamModule::filterMarkers(vector<vector<cv::Point2f> >& cor,
+		vector<int>& ids) {
+
+	//go through all detected markers, for each 
+	m_detectedMarkers.clear();
+	for(unsigned int m=0; m<ids.size(); ++m) {
+		if(ids[m]<10) {
+			//create a marker_time 
+			m_detectedMarkers.push_back(s_markerAndTime());
+			m_detectedMarkers.back().id=ids[m];
+			m_detectedMarkers.back().corners.assign(cor[m].begin(),cor[m].end());
+			m_detectedMarkers.back().corners3D.assign(4, glm::vec3(0));
+			m_detectedMarkers.back().detected=true;
+			cv::Point pt = calculationCenterOfMarker(m_detectedMarkers.back());
+			m_detectedMarkers.back().x=pt.x;
+			m_detectedMarkers.back().y=pt.y;
+
+			//add/update detection time in map
+			time(&m_detectedMarkers.back().detection);
+			m_aliveMarkers[ids[m]] = m_detectedMarkers.back();
+		}
+	}
+
+
+	//go through map elements, remove not detected and old ones
+	time_t now;
+	time(&now);
+	map<int, s_markerAndTime>::iterator itAl = m_aliveMarkers.begin();
+	for(; itAl!=m_aliveMarkers.end();) {
+		if(difftime(now, itAl->second.detection) > 1) {
+			m_removedMarkers.push_back(itAl->second);
+			itAl = m_aliveMarkers.erase(itAl);
+		}
+		else {
+			itAl++;
+		}
+	}
+}
+
+vector<cv::Point2f> DepthCamModule::newSetOfPoint(vector<cv::Point2f> points, 
+		bool readyToCoop){
+	vector<cv::Point2f> setOfPoint;
+	int cmp;
+
+	if(!readyToCoop)
+		return points;
+
+	for(int i = 0; i < (int)points.size(); i++){
+		cmp = jointly(points, points[i]);
+		if(cmp == -1 || cmp > i){
+			setOfPoint.push_back(points[i]);
+		}
+	}
+
+	return setOfPoint;
+}
+
+int DepthCamModule::jointly(vector<cv::Point2f> points, cv::Point2f pt){
+	int cpt = 0;
+
+	for(vector<cv::Point2f>::iterator it=points.begin(); it!=points.end();it++){
+		if(it->x - pt.x > -130 && it->x - pt.x < 130 && it->x != pt.x)
+			return cpt;
+
+		cpt++;
+	}
+
+	return -1;
+}
+
+void DepthCamModule::delimitation(cv::Mat& img) {
+	// Keep a copy around
+	//cv::Mat img_orig = img.clone();
+	// Rectangle to be used with Subdiv2D
+	cv::Rect rect(0, 0, img.size().width, img.size().height);
+	// Create an instance of Subdiv2D
+	cv::Subdiv2D subdiv(rect);
+	// Create a vector of points.
+	vector<cv::Point2f> points;
+
+	map<int, s_markerAndTime>::iterator it = m_aliveMarkers.begin();
+	for(; it!=m_aliveMarkers.end(); it++){
+		points.push_back(cv::Point2f(it->second.x, it->second.y));
+	}
+
+	vector<cv::Point2f> setOfPoint = newSetOfPoint(points, false);
+
+	// Insert points into subdiv
+	subdiv.insert(setOfPoint);
+
+	// Draw delaunay triangles
+	drawDelaunay(img, subdiv, cv::Scalar(13,240,231) );
+
+	// Draw points
+	for(vector<cv::Point2f>::iterator it = points.begin(); 
+			it != points.end(); it++){
+		draw_point(img, *it);
+	}
+
+
+
+
+	// Draw Voronoi diagram
+	drawVoronoi(m_resImg, subdiv);
+
+	return;
+}
+
+cv::Point DepthCamModule::calculationCenterOfMarker(s_markerAndTime& marker){
+	return cv::Point((marker.corners[0].x
+				+ marker.corners[1].x
+				+ marker.corners[2].x
+				+ marker.corners[3].x)/4.0,
+			(marker.corners[0].y
+			 + marker.corners[1].y
+			 + marker.corners[2].y
+			 + marker.corners[3].y)/4.0);
+}
+
+void DepthCamModule::globalFunction(cv::Mat &mat) {
+	cv::Size asize(mat.size().width, mat.size().height);
+	cv::Size maskSize(mat.size().width+2, mat.size().height+2);
+	int width = 0, height = 0;
+
+	if(!m_notVoronoi){		  
+		delimitation(mat);
+	}
+	else {
+		cv::Mat mask = cv::Mat::zeros(maskSize, CV_8UC1);
+		map<int, s_markerAndTime>::iterator it = m_aliveMarkers.begin();
+		for(; it!= m_aliveMarkers.end(); it++) {
+			//FIXME values ???
+			cv::floodFill(mat, mask, cv::Point(it->second.x,it->second.y), 
+					cv::Scalar(0), nullptr, cv::Scalar(255,255,5), 
+					cv::Scalar(255,255,5), 
+					4 | cv::FLOODFILL_MASK_ONLY 
+					| ((m_depthID+it->second.id) << 8 ));
+		}
+
+		for(int j=1; j<maskSize.height-1; ++j){
+			for(int i=1; i<maskSize.width-1; ++i){
+				cv::Vec3b &res_pix = m_resImg.at<cv::Vec3b>(j-1, i-1);
+				uchar mask_pix = mask.at<uchar>(j, i);
+				res_pix[0] = mask_pix;
+				res_pix[1] = mask_pix;
+				res_pix[2] = mask_pix;
+			}
+		}
+	}
+	return ;
+}
+
+void DepthCamModule::drawVoronoi( cv::Mat& img, cv::Subdiv2D& subdiv) {
+	vector<vector<cv::Point2f> > facets;
+	vector<cv::Point2f> centers;
+	subdiv.getVoronoiFacetList(vector<int>(), facets, centers);
+
+	vector<cv::Point> ifacet;
+	vector<vector<cv::Point> > pts(1);
+
+	map<int, s_markerAndTime>::iterator it = m_aliveMarkers.begin();
+	for(unsigned int f=0; 
+			f<facets.size() && it!=m_aliveMarkers.end(); f++, it++) {
+		ifacet.resize(facets[f].size());
+		for( size_t j = 0; j < facets[f].size(); j++ ) {
+			ifacet[j] = facets[f][j];
+		}
+		cv::Scalar color((it->second.id+m_depthID),
+				(it->second.id+m_depthID),
+				(it->second.id+m_depthID));
+
+		cv::fillConvexPoly(img, ifacet, color, 8, 0);
+
+		pts[0] = ifacet;
+		cv::polylines(img, pts, true, cv::Scalar(0,0,255), 1, LINE_AA, 0);
+		draw_point(img, centers[f]);
+	}
+}
+
+void DepthCamModule::drawDelaunay(cv::Mat& img, cv::Subdiv2D& subdiv, 
+		cv::Scalar delaunayColor ){
+
+	vector<cv::Vec6f> triangleList;
+	subdiv.getTriangleList(triangleList);
+	vector<cv::Point> pt(3);
+
+	cv::Rect rect(0,0, img.size().width, img.size().height);
+	for(int i = 0; i < (int)triangleList.size(); i++){
+		cv::Vec6f t = triangleList[i];
+		pt[0] = cv::Point(cvRound(t[0]), cvRound(t[1]));
+		pt[1] = cv::Point(cvRound(t[2]), cvRound(t[3]));
+		pt[2] = cv::Point(cvRound(t[4]), cvRound(t[5]));
+
+		// Draw rectangles completely inside the image.
+		if(rect.contains(pt[0]) &&rect.contains(pt[1]) &&rect.contains(pt[2])){
+			cv::line(img, pt[0], pt[1], delaunayColor, 1, LINE_AA, 0);
+			cv::line(img, pt[1], pt[2], delaunayColor, 1, LINE_AA, 0);
+			cv::line(img, pt[2], pt[0], delaunayColor, 1, LINE_AA, 0);
+		}
+	}
+}
+
+void DepthCamModule::debugMarkers(const bool& val) {
+	if(!val && m_debuggingMarkers) {
+		destroyWindow("markers");
+		destroyWindow("filled_markers");
+		waitKey(10);
+	}
+	m_debuggingMarkers=val;
+}
+
+void DepthCamModule::showAliveMarkers() {
+	cv::Mat markImg(m_rgbImg);
+	map<int, s_markerAndTime>::iterator itM = m_aliveMarkers.begin();
+	for(; itM!=m_aliveMarkers.end(); ++itM) {
+		ostringstream oss;
+		oss<<itM->second.id;
+		cv::putText(markImg, oss.str().c_str(), 
+				cv::Point2f(itM->second.x, itM->second.y),
+				cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(255,255,255));
+		for(int c=0; c<4; c++) {
+			cv::line(markImg, 
+					itM->second.corners[c], itM->second.corners[(c+1)%4], 
+					cv::Scalar(255), 2);
+		}
+	}
+	imshow("markers", markImg);
+	imshow("filled_markers", m_resImg*50);
+	waitKey(10);
+}
+
+void ArucoTracker::init() {
+
+
+}
+
+void ArucoTracker::track(cv::Mat& img,
+		std::vector<std::vector<cv::Point2f> >& corners, 
+		std::vector<int>& ids) {
+	cv::aruco::detectMarkers(img, 
+			cv::aruco::getPredefinedDictionary(
+				cv::aruco::DICT_ARUCO_ORIGINAL),
+			corners,
+			ids);
+
+}
+
+
+ImageTracker::ImageTracker():Tracker() {
+	//m_detector = cv::ORB::create();
+	//m_detector = cv::AKAZE::create();
+	m_detector = cv::BRISK::create();
+	m_matcher = cv::BFMatcher::create(NORM_HAMMING);
+}
+
+void ImageTracker::init() {
+	m_descriptors.clear();
+	m_keypoints.clear();
+	m_cols.clear();
+	m_rows.clear();
+
+	//read images from folder and compute descriptors for each
+	dirent** filesList;
+	int nbFiles = fl_filename_list(m_imgFolder.c_str(), 
+			&filesList, fl_alphasort);
+	for(int f=0; f<nbFiles; ++f) {
+		if(filesList[f]->d_name[0]!='.') {
+			string fullName = m_imgFolder+string(filesList[f]->d_name);
+			cv::Mat img = cv::imread(fullName);
+			if(img.data) {
+				std::vector<KeyPoint> keypoints;
+				cv::Mat descriptors;
+				m_detector->detectAndCompute(img,Mat(),keypoints,descriptors);
+				m_descriptors.push_back(descriptors);
+				m_keypoints.push_back(keypoints);
+				m_cols.push_back(img.cols);
+				m_rows.push_back(img.rows);
+
+				/*
+				   drawKeypoints(img, keypoints, img);
+				   imshow("marker", img);
+				   waitKey(10);
+				   */
+			}
+		}
+	}
+}
+
+void ImageTracker::track(cv::Mat& img, 
+		std::vector<std::vector<cv::Point2f> >& corners, 
+		std::vector<int>& ids) {
+
+	unsigned int minMatches=10;
+	float matchRatio=0.8;
+
+	//get descriptors for the captured image
+	std::vector<KeyPoint> keypoints;
+	cv::Mat descriptors;
+	m_detector->detectAndCompute(img, Mat(), keypoints, descriptors);
+	//drawKeypoints(img, keypoints, img);
+
+
+
+	//try to match with each image in the set
+	for(unsigned int m=0; m<m_descriptors.size(); m++) {
+		vector<cv::DMatch> matches;
+		vector<cv::DMatch> matches2;
+		vector<vector<cv::DMatch> > nn_matches;
+		try {
+			//m_matcher->match(m_descriptors[m], descriptors, matches);
+			//m_matcher->match(descriptors, m_descriptors[m], matches2);
+			m_matcher->knnMatch(m_descriptors[m], descriptors, nn_matches, 2);
+		}
+		catch(Exception& e) {
+			cout<<e.what()<<endl;
+		}
+
+		/*
+		   vector<DMatch> good_matches;
+		   for(int i=0; i<matches.size(); i++) {
+		   if(matches2[i].trainIdx == matches[matches[2].trainIdx].queryIdx) {
+		   good_matches.push_back(matches[i]);
+		   }
+		   }
+		   */
+		vector<DMatch> good_matches;
+		for(unsigned int i=0; i<nn_matches.size(); i++) {
+			if(nn_matches[i].size()>=2) {
+				if(nn_matches[i][0].distance 
+						<= matchRatio*nn_matches[i][1].distance) {
+					good_matches.push_back(nn_matches[i][0]);
+				}
+			}
+		}
+
+
+		/*
+		   double max_dist = 0; double min_dist = 100;
+		//for(int i=0; i<m_descriptors[m].rows; i++) { 
+		for(int i=0; i<matches.size(); i++) { 
+		double dist = matches[i].distance;
+		if(dist < min_dist) {min_dist = dist;}
+		if(dist > max_dist) {max_dist = dist;}
+		}
+
+		vector<DMatch> good_matches;
+		//for(int i=0; i<m_descriptors[m].rows; i++) { 
+		for(int i=0; i<matches.size(); i++) { 
+		if(matches[i].distance < 3*min_dist) { 
+		good_matches.push_back(matches[i]); 
+		}
+		}*/
+		if(good_matches.size()>minMatches) {
+			vector<Point2f> obj;
+			vector<Point2f> scene;
+
+			for(unsigned int i=0; i<good_matches.size(); i++) {
+				obj.push_back(m_keypoints[m][good_matches[i].queryIdx].pt);
+				scene.push_back(keypoints[good_matches[i].trainIdx].pt);
+			}
+
+			Mat H;
+
+			try {
+				H = findHomography(obj, scene, RANSAC);
+			}
+			catch(Exception& e) {
+				cout<<e.what()<<endl;
+			}
+
+			if(!H.empty()) {
+				vector<Point2f> objCorners(4);
+				objCorners[0] = Point(0, 0); 
+				objCorners[1] = Point(m_cols[m], 0);
+				objCorners[2] = Point(m_cols[m], m_rows[m]); 
+				objCorners[3] = Point(0, m_rows[m]);
+
+				vector<Point2f> sceneCorners(4);
+				perspectiveTransform(objCorners, sceneCorners, H);
+				bool valid=true;
+				for(int c=0; c<4; c++) {
+					if(sceneCorners[c].x<0 || sceneCorners[c].y<0 
+							|| sceneCorners[c].x>640 
+							|| sceneCorners[c].y>480) {
+						valid=false;
+					}
+				}
+
+				if(valid) {
+					ids.push_back(m);
+					corners.push_back(sceneCorners);
+				}
+			}
+		}
+	}
+
+	}
+
+
+
diff --git a/src/modules/DepthCamModule.hpp b/src/modules/DepthCamModule.hpp
new file mode 100644
index 0000000..ac9ee78
--- /dev/null
+++ b/src/modules/DepthCamModule.hpp
@@ -0,0 +1,406 @@
+/***************************************************************************
+ *  DepthCamModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DepthCamModule_h
+#define DepthCamModule_h
+
+#include "GroupModule.hpp"
+#include "DepthModule.hpp"
+
+#include <vector>
+#include <deque>
+#include <thread>
+#include <mutex>
+
+#include <OpenNI.h>
+#include <opencv2/core/core.hpp>
+#include <opencv2/highgui/highgui.hpp>
+#include <opencv2/imgproc/imgproc.hpp>
+#include <opencv2/calib3d/calib3d.hpp>
+#include <opencv2/features2d/features2d.hpp>
+#include <opencv2/aruco.hpp>
+#include <FL/filename.H>
+
+class SpaceModule;
+class ProjectorModule;
+class CamGeometry;
+
+struct s_markerAndTime;
+struct DepthMode;
+struct ColorMode;
+
+class Tracker;
+class ArucoTracker;
+class ImageTracker;
+
+class DepthCamModule : public GroupModule, public DepthModule {
+    public:
+        DepthCamModule();
+        virtual ~DepthCamModule();
+        void deleteModule();
+        void setModuleName(const std::string& val);
+        
+        inline virtual bool isDepthVisible(const unsigned int& id) { 
+            return m_open && m_visible && (m_detectingMarkers||id==m_depthID);
+        }
+
+        virtual void draw(const int& contextID,
+                          const Reveal::REVIL_PROGRAM& prog,
+                          std::map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                          const unsigned int& component);
+
+        virtual void setSpace(SpaceModule*);
+        inline virtual int getNbSubDepthIDs(){return m_maxNbMarkers;}
+
+        virtual void update(const int& timeDiffMs);
+        virtual void updateModelMatrix();
+
+        void refreshDeviceList();
+        void activateColor();
+        void deactivateColor();
+        bool getFrames();
+        inline openni::VideoFrameRef getDepthFrame(){return m_depthFrame;}
+        inline openni::VideoFrameRef getColorFrame(){return m_colorFrame;}
+        inline openni::VideoStream& getDepthStream(){return m_depth;}
+
+
+        static void refreshCallback(Module* mod) {
+            dynamic_cast<DepthCamModule*>(mod)->refreshDeviceList();
+        }
+        static void deviceCallback(Module* mod,
+                                   const std::vector<std::string>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->openDevice(vals[0]);
+        }
+        virtual void openDevice(const std::string& dev, bool calib=false);
+        static void closeCallback(Module* mod) {
+            dynamic_cast<DepthCamModule*>(mod)->closeDevice(true);
+        }
+        void closeDevice(const bool& clear=false);
+        static void modeCallback(Module* mod,
+                                   const std::vector<std::string>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->setMode(vals[0]);
+        }
+        virtual void setMode(const std::string& mode);
+
+        //filter callbacks
+        static void filterCallback(Module* mod,
+                                   const std::vector<std::string>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->setFilter(vals[0]);
+        }
+        void setFilter(const std::string& fil);
+        static void filterSizeCallback(Module* mod,
+                                       const std::vector<float>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->setFilterSize(vals[0]);
+        }
+        void setFilterSize(int siz);
+        static void filterSpatCallback(Module* mod,
+                                       const std::vector<int>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->setFilterSpat(vals[0]);
+        }
+        void setFilterSpat(int siz);
+        static void filterMCOCallback(Module* mod,
+                                      const std::vector<float>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->setFilterMCO(vals[0]);
+        }
+        void setFilterMCO(float mco);
+        static void filterBetaCallback(Module* mod,
+                                       const std::vector<float>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->setFilterBeta(vals[0]);
+        }
+        void setFilterBeta(float beta);
+
+        //contour callback
+        static void contourThresholdCallback(Module* mod,
+                                   const std::vector<float>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->setContourThresh(vals[0]);
+        }
+        inline void setContourThresh(float cont) {m_contourThreshold=cont;}
+
+        static void markersDetectionCallback(Module* mod,
+                                 const std::vector<std::string>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->setMarkersDetection(vals[0]);
+        }
+        void setMarkersDetection(const std::string& val);
+        static void imageMarkersFolderCallback(Module* mod, 
+                                               const std::string& f) {
+            dynamic_cast<DepthCamModule*>(mod)->setImageMarkersFolder(f);
+        }
+        virtual void setImageMarkersFolder(const std::string& f);
+
+        static void markersFillMethodCallback(Module* mod,
+                                 const std::vector<std::string>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->setMarkersFillMethod(vals[0]);
+        }
+        void setMarkersFillMethod(const std::string& val);
+        void detectMarkers();
+        static void outputMarkersCallback(Module* mod,
+                                          const std::vector<float>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->outputMarkers(vals);
+        }
+        inline void outputMarkers(const std::vector<float>& vals){}
+        static void debugMarkersCallback(Module* mod,
+                                         const std::vector<bool>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->debugMarkers(vals[0]);
+        }
+        void debugMarkers(const bool& val);
+
+        static void captureBackgroundCallback(Module* mod,
+                                             const std::vector<bool>& vals) {
+            dynamic_cast<DepthCamModule*>(mod)->setCaptureBackground(vals[0]);
+        }
+        void setCaptureBackground(const bool& cap);
+        void captureBackground();
+
+        static void calibrationCallback(Module* mod) {
+            dynamic_cast<DepthCamModule*>(mod)->calibrate();
+        }
+        void calibrate();
+        void refreshProjList(const std::vector<ProjectorModule*> projs);
+
+        static void cursCallback(Module* mod, const std::vector<float>& vals) {}
+
+        void setCalibMarkerPosY(const int&);
+        void setCalibMarkerRotX(const int&);
+        void setCalibMarkerRotY(const int&);
+        void setCalib(const int&);
+        inline double& getHorizontalFOV(){return m_horizontalFOV;}
+        inline double& getVerticalFOV(){return m_verticalFOV;}
+
+        bool isOpen(){return m_open;}
+
+        void processFrames();
+
+        void gotAttributeListenersUpdate(Attribute*);
+        void processCursor(const std::vector<float>& pos);
+        inline const std::string& getDeviceID(){return m_deviceID;}
+
+        void attachProj(ProjectorModule*);
+        void detachProj(ProjectorModule*);
+
+    private:
+
+        //filter
+        void filterDepthFrame();
+
+        //marker
+        void draw_point(cv::Mat& img, cv::Point2f fp);
+        void filterMarkers(std::vector<std::vector<cv::Point2f> >& cor,
+                           std::vector<int>& ids);
+        void showAliveMarkers();
+        std::vector<cv::Point2f> newSetOfPoint(std::vector<cv::Point2f> points, 
+                                               bool readyToCoop);
+        int jointly(std::vector<cv::Point2f> points, cv::Point2f pt);
+        void delimitation(cv::Mat& img);
+        cv::Point calculationCenterOfMarker(s_markerAndTime& marker);
+        void globalFunction(cv::Mat &mat);
+        cv::Scalar voronoiColor(cv::Mat mat, cv::Point2f pt);
+        void drawVoronoi(cv::Mat& img, cv::Subdiv2D& subdiv);
+        void drawDelaunay(cv::Mat& img, cv::Subdiv2D& subdiv, 
+                          cv::Scalar delaunay_color);
+        bool createMatDepth();
+        bool createMatColor();
+        bool createMatDepthAndColor();
+        
+    private:
+        std::string m_deviceID;
+        bool m_open;
+        std::vector<std::string> m_modes;
+        std::map<std::string, DepthMode> m_depthModes;
+
+        openni::Device m_device;
+        std::vector<std::string> m_serialsVec;
+        std::map<std::string, std::string> m_serialsMap;
+        openni::VideoStream m_depth, m_color;
+        openni::VideoStream** m_streams;
+        openni::VideoFrameRef m_depthFrame;
+        openni::VideoFrameRef m_colorFrame;
+        bool m_gotDepth, m_gotColor;
+        bool m_colorActivated;
+
+        unsigned short* m_defaultDepthFrame;
+
+        CamGeometry* m_camGeom;
+
+        std::map<int, GLuint> m_camTexMap;
+        std::map<int, GLuint> m_camTexMap1;
+        std::map<int, GLuint> m_camTexMap2;
+        std::map<int, int> m_upCamCounter;
+        std::map<int, bool> m_camTexUpMap;
+
+        std::map<int, GLuint> m_markTexMap;
+        std::map<int, bool> m_markTexUpMap;
+
+        uint16_t m_width, m_height, m_fps;
+        uint16_t m_defaultWidth, m_defaultHeight, m_defaultFps;
+        double m_horizontalFOV, m_verticalFOV;
+        bool m_mirrored;
+        float m_contourThreshold;
+
+        //frames processing
+        cv::Size m_procSize;
+        std::thread* m_framesThread;
+        std::mutex m_framesLock;
+
+        //filter
+        bool m_filtering;
+        std::string m_filter;
+        int m_filterSize;
+        std::vector<std::string> m_filters;
+        int m_maxFilterSize;
+        int m_filterIndex;
+        unsigned short** m_prevDepthFrames;
+        int* m_sumDepthFrame;
+        unsigned short* m_filtDepthFrame;
+        std::map<int, GLuint> m_filtTexMap;
+        std::map<int, bool> m_filtTexUpMap;
+        int m_filterSpat;
+
+        //one euro filter
+        float* m_oefXFrame;
+        float* m_oefDXFrame;
+        float m_oefRate;
+        float m_oefMinCutoff;
+        float m_oefBeta;
+        float m_oefDCutoff;
+        bool m_oefInit;
+
+        //background
+        int m_capturingBackground;
+        bool m_capturedBackground;
+        bool m_backgroundActive;
+        cv::Mat m_backImg;
+
+        //markers
+        bool m_detectingMarkers;
+        unsigned char *m_markersFrame;
+        cv::Mat m_detRgbImg;
+        cv::Mat m_detMarkImg;
+		cv::Mat m_detDepthImg;
+        int m_maxNbMarkers;
+        bool m_fillingMarkers;
+        Tracker* m_currentTracker;
+        ArucoTracker* m_arucoTracker;
+        ImageTracker* m_imageTracker;
+        bool m_debuggingMarkers;
+
+        //calibration
+        int m_calibrating;
+        bool m_calibrationStopped;
+        int m_redXmm, m_redYmm, m_redZmm;
+        int m_greenXmm, m_greenYmm, m_greenZmm;
+        int m_blueXmm, m_blueYmm, m_blueZmm;
+        int m_patternWidth;
+        int m_patternPositionX;
+        int m_patternPositionY;
+        int m_markerPosY;
+        int m_markerRotX;
+        int m_markerRotY;
+        ProjectorModule* m_calibrationProj;
+        std::vector<cv::Point3f> m_worldCorners;
+        cv::Size m_patternSize;
+
+        //projectors
+        std::map<int, ProjectorModule*> m_attachedProjs;
+
+        //cursor
+        float m_filterCursorSize;
+        std::vector<float> m_filterCursorSums;
+        std::vector<std::deque<float> > m_filterCursorValues;
+        std::vector<float> m_cursorValues;
+
+        //markerDetection
+        cv::Mat m_finalCombin;
+        cv::Mat m_rgbImg;
+        cv::Mat m_depthImg;
+        cv::Mat m_rgbDepthImg;
+        cv::Mat m_resImg;
+        std::vector<s_markerAndTime> m_detectedMarkers;
+        std::map<int, s_markerAndTime> m_aliveMarkers;
+        std::vector<s_markerAndTime> m_removedMarkers;
+        std::vector<s_markerAndTime> m_sentDetectedMarkers;
+        std::vector<s_markerAndTime> m_sentRemovedMarkers;
+        bool m_notVoronoi;
+};
+
+
+//------------------------------Trackers-------------------
+
+class Tracker {
+    public :
+        virtual ~Tracker(){}
+        virtual void init()=0;
+        virtual void track(cv::Mat&,
+                           std::vector<std::vector<cv::Point2f> >&, 
+                           std::vector<int>&)=0;
+};
+
+class ArucoTracker : public Tracker {
+    public:
+        ~ArucoTracker(){}
+        void init();
+        void track(cv::Mat&, 
+                   std::vector<std::vector<cv::Point2f> >&, 
+                   std::vector<int>&);
+
+};
+
+struct s_markerAndTime {
+    int id;
+    float x;
+    float y;
+    std::vector<cv::Point2f> corners;
+    std::vector<glm::vec3> corners3D;
+    int plan = -1;
+    time_t detection;
+    time_t timeLess;
+    glm::vec3 orientation;
+    bool detected;
+};
+
+class ImageTracker : public Tracker {
+    public:
+        ImageTracker();
+        ~ImageTracker(){}
+        void init();
+        void track(cv::Mat&,
+                   std::vector<std::vector<cv::Point2f> >&, 
+                   std::vector<int>&);
+        void setImgFolder(const std::string& fol){m_imgFolder=fol;}
+    private:
+        std::string m_imgFolder;
+        std::vector<cv::Mat> m_descriptors;
+        std::vector<std::vector<cv::KeyPoint> > m_keypoints;
+        cv::Ptr<cv::Feature2D> m_detector;
+        std::vector<int> m_rows;
+        std::vector<int> m_cols;
+        cv::Ptr<cv::DescriptorMatcher> m_matcher;
+};
+
+struct DepthMode {
+    int width;
+    int height;
+    int fps;
+};
+
+#endif
+
diff --git a/src/modules/DepthGroupModule.cpp b/src/modules/DepthGroupModule.cpp
new file mode 100644
index 0000000..50fb245
--- /dev/null
+++ b/src/modules/DepthGroupModule.cpp
@@ -0,0 +1,116 @@
+/***************************************************************************
+ *  DepthGroupModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "DepthGroupModule.hpp" 
+
+#include <iostream>
+
+#include "../Reveal.hpp"
+
+#include "ProjectorModule.hpp"
+#include "DepthCamModule.hpp"
+#include "DepthMeshModule.hpp"
+#include "DepthShapeModule.hpp"
+#include "SpaceModule.hpp"
+
+using namespace std;
+
+DepthGroupModule::DepthGroupModule(): GroupModule(), DepthModule() {
+    m_type="DepthGroup";
+    m_name="group";
+
+    addAttribute(new Attribute("name", 
+                                Attribute::STRING_ATTRIBUTE,
+                                nameCallback, this, 1, Attribute::LOCAL));
+    m_attributesMap["name"]->setStrings(vector<string>(1, m_name));
+
+    addRemoveAttribute();
+    addVisibleAttribute();
+    addAttribute(new Attribute("add_projector", 
+                                Attribute::ACTION_ATTRIBUTE,
+                                addProjCallback, this, Attribute::LOCAL));
+    addAttribute(new Attribute("add_depth_group", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addDepthGroupCallback, this, 1, 
+                                Attribute::LOCAL));
+    m_attributesMap["add_depth_group"]->initStrings(vector<string>(1,"group"));
+    addAttribute(new Attribute("add_depth_camera", 
+                                Attribute::ACTION_ATTRIBUTE,
+                                addCamCallback, this, Attribute::LOCAL));
+    addAttribute(new Attribute("add_depth_shape", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addDepthShapeCallback, this, 1));
+    m_attributesMap["add_depth_shape"]->initStrings(vector<string>(1,"shape"));
+    addAttribute(new Attribute("add_depth_mesh", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addDepthMeshCallback, this, 1));
+    m_attributesMap["add_depth_mesh"]->initStrings(vector<string>(1,"mesh"));
+
+    addTransformationAttributes();
+}
+
+DepthGroupModule::~DepthGroupModule() {
+}
+
+void DepthGroupModule::deleteModule() {
+    Module::deleteModule();
+}
+
+void DepthGroupModule::updateModelMatrix() {
+    GroupModule::updateModelMatrix();
+}
+
+void DepthGroupModule::addChild(Module* mod) {
+    GroupModule::addChild(mod);
+    m_space->addSpaceModule(mod);
+    Reveal::getInstance()->refreshModules();
+}
+
+void DepthGroupModule::addProj() {
+    ProjectorModule* proj = new ProjectorModule();
+    addChild(proj);
+}
+
+void DepthGroupModule::addCam() {
+    DepthCamModule* cam = new DepthCamModule();
+    addChild(cam);
+}
+
+void DepthGroupModule::addDepthShape(const string& name) {
+    DepthShapeModule* tmp = new DepthShapeModule();
+    tmp->setName(name);
+    addChild(tmp);
+}
+
+void DepthGroupModule::addDepthMesh(const string& name) {
+    DepthMeshModule* tmp = new DepthMeshModule();
+    tmp->setName(name);
+    addChild(tmp);
+}
+
+void DepthGroupModule::addDepthGroup(const string& name) {
+    DepthGroupModule* tmp = new DepthGroupModule();
+    tmp->setName(name);
+    addChild(tmp);
+}
+
diff --git a/src/modules/DepthGroupModule.hpp b/src/modules/DepthGroupModule.hpp
new file mode 100644
index 0000000..e99a0b6
--- /dev/null
+++ b/src/modules/DepthGroupModule.hpp
@@ -0,0 +1,83 @@
+/***************************************************************************
+ *  DepthGroupModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DepthGroupModule_h
+#define DepthGroupModule_h
+
+#include "GroupModule.hpp"
+#include "DepthModule.hpp"
+
+class DepthCamModule;
+class DepthMeshModule;
+class ProjectorModule;
+class DepthShapeModule;
+
+class DepthGroupModule : public GroupModule, public DepthModule {
+    public:
+        DepthGroupModule();
+        virtual ~DepthGroupModule();
+        void deleteModule();
+
+        virtual void addChild(Module*);
+
+        virtual void updateModelMatrix();
+
+        static void nameCallback(Module* mod, 
+                                 const std::vector<std::string>& vals) {
+            dynamic_cast<DepthGroupModule*>(mod)->setName(vals[0]);
+        }
+
+        static void addProjCallback(Module* mod) {
+            dynamic_cast<DepthGroupModule*>(mod)->addProj();
+        }
+        void addProj();
+
+        static void addCamCallback(Module* mod) {
+            dynamic_cast<DepthGroupModule*>(mod)->addCam();
+        }
+        void addCam();
+
+        static void addDepthShapeCallback(Module* mod, 
+                                      const std::vector<std::string>& vals) {
+            dynamic_cast<DepthGroupModule*>(mod)->addDepthShape(vals[0]);
+        }
+        void addDepthShape(const std::string& name);
+
+        static void addDepthMeshCallback(Module* mod,
+                                      const std::vector<std::string>& vals) {
+            dynamic_cast<DepthGroupModule*>(mod)->addDepthMesh(vals[0]);
+        }
+        void addDepthMesh(const std::string& name);
+
+        static void addDepthGroupCallback(Module* mod,
+                                      const std::vector<std::string>& vals) {
+            dynamic_cast<DepthGroupModule*>(mod)->addDepthGroup(vals[0]);
+        }
+        void addDepthGroup(const std::string& name);
+
+    private:
+};
+
+
+#endif
+
diff --git a/src/modules/DepthMeshModule.cpp b/src/modules/DepthMeshModule.cpp
new file mode 100644
index 0000000..76ad0c6
--- /dev/null
+++ b/src/modules/DepthMeshModule.cpp
@@ -0,0 +1,97 @@
+/***************************************************************************
+ *  DepthMeshModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "DepthMeshModule.hpp" 
+
+#include <iostream>
+
+#include "../Reveal.hpp"
+#include "SpaceModule.hpp"
+#include "../geoms/Geometry.hpp"
+
+using namespace std;
+
+DepthMeshModule::DepthMeshModule(): DepthModule() {
+    m_type="DepthMesh";
+    m_name="depthmesh";
+    m_depthType=1;
+
+    m_meshGeom = new Geometry();
+    m_meshGeom->registerModule(this);
+    m_meshGeom->editCompoSizes().push_back(0);
+    
+
+    addNameAttribute();
+    addRemoveAttribute();
+    addVisibleAttribute();
+
+    addAttribute(new Attribute("add_vertex", 
+                                Attribute::ACTION_FLOAT_ATTRIBUTE,
+                                addVertexCallback, this, 3));
+    addAttribute(new Attribute("clear_vertices", 
+                                Attribute::ACTION_ATTRIBUTE,
+                                clearVerticesCallback, this));
+
+    addTransformationAttributes();
+}
+
+DepthMeshModule::~DepthMeshModule() {
+}
+
+void DepthMeshModule::updateModelMatrix() {
+    DepthModule::updateModelMatrix();
+}
+
+void DepthMeshModule::setSpace(SpaceModule* space) {
+    DepthModule::setSpace(space);
+    m_space->registerGeom(m_meshGeom);
+    
+}
+
+void DepthMeshModule::addVertex(const float& x,   
+                                const float& y, 
+                                const float& z) {
+    vector<GLfloat>& vertices = m_meshGeom->editVertexBufferData();
+    vector<GLuint>& indices = m_meshGeom->editIndexBufferData();
+    vector<int>& sizes = m_meshGeom->editCompoSizes();
+
+    vertices.push_back(x);
+    vertices.push_back(y);
+    vertices.push_back(z);
+    indices.push_back(indices.size());
+    sizes[0]+=1;
+    m_meshGeom->refresh();
+}
+
+void DepthMeshModule::clearVertices() {
+    vector<GLfloat>& vertices = m_meshGeom->editVertexBufferData();
+    vector<GLuint>& indices = m_meshGeom->editIndexBufferData();
+    vector<int>& sizes = m_meshGeom->editCompoSizes();
+    indices.clear();
+    vertices.clear();
+    sizes[0]=0;
+
+}
+
+
+
diff --git a/src/modules/DepthMeshModule.hpp b/src/modules/DepthMeshModule.hpp
new file mode 100644
index 0000000..b29e614
--- /dev/null
+++ b/src/modules/DepthMeshModule.hpp
@@ -0,0 +1,55 @@
+/***************************************************************************
+ *  DepthMeshModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DepthMeshModule_h
+#define DepthMeshModule_h
+
+#include "DepthModule.hpp"
+
+class DepthMeshModule : public DepthModule {
+    public:
+        DepthMeshModule();
+        virtual ~DepthMeshModule();
+        virtual void updateModelMatrix();
+        virtual void setSpace(SpaceModule* space);
+
+        static void addVertexCallback(Module* mod,
+                                   const std::vector<float>& vals) {
+            dynamic_cast<DepthMeshModule*>(mod)->addVertex(vals[0], 
+                                                           vals[1],
+                                                           vals[2]);
+        }
+        void addVertex(const float& z, const float& y, const float& x);
+
+        static void clearVerticesCallback(Module* mod) {
+            dynamic_cast<DepthMeshModule*>(mod)->clearVertices();
+        }
+        void clearVertices();
+
+    private:
+        Geometry* m_meshGeom;
+};
+
+
+#endif
+
diff --git a/src/modules/DepthModule.cpp b/src/modules/DepthModule.cpp
new file mode 100644
index 0000000..486a47a
--- /dev/null
+++ b/src/modules/DepthModule.cpp
@@ -0,0 +1,63 @@
+/***************************************************************************
+ *  DepthModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "DepthModule.hpp" 
+
+#include <iostream>
+
+#include "../Reveal.hpp"
+#include "SpaceModule.hpp"
+
+using namespace std;
+
+DepthModule::DepthModule(): GeomModule(), m_space(NULL) {}
+
+DepthModule::~DepthModule() {}
+
+void DepthModule::deleteModule() {
+    if(m_space) {
+        m_space->removeDepthModule(this);
+    }
+    Module::deleteModule();
+}
+
+void DepthModule::setDepthID(const unsigned int& id) {
+    m_depthID=id;
+}
+
+void DepthModule::setSpace(SpaceModule* space) { 
+    m_space=space;
+}
+
+void DepthModule::draw(const int& contextID,
+                       const Reveal::REVIL_PROGRAM& prog, 
+                       map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                       const unsigned int& component) {
+
+    GeomModule::draw(contextID, prog, uniforms, component);
+    glUniform1i(uniforms[Reveal::DEPTHTYPE], m_depthType);
+    glUniform1i(uniforms[Reveal::DEPTHID], m_depthID);
+}
+
+
+
diff --git a/src/modules/DepthModule.hpp b/src/modules/DepthModule.hpp
new file mode 100644
index 0000000..b292f0e
--- /dev/null
+++ b/src/modules/DepthModule.hpp
@@ -0,0 +1,60 @@
+/***************************************************************************
+ *  DepthModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DepthModule_h
+#define DepthModule_h
+
+#include "ShapeModule.hpp"
+
+class SpaceModule;
+
+class DepthModule : public virtual GeomModule {
+    public:
+        DepthModule();
+        virtual ~DepthModule();
+        void deleteModule();
+
+        void setDepthID(const unsigned int&);
+        const unsigned int& getDepthID(){return m_depthID;}
+
+        virtual void setSpace(SpaceModule* space);
+
+        virtual void draw(const int& contextID,
+                          const Reveal::REVIL_PROGRAM& prog, 
+                          std::map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                          const unsigned int& component);
+        inline virtual int getNbSubDepthIDs(){return 1;}
+
+        inline virtual bool isDepthVisible(const unsigned int& id) { 
+            return m_visible;
+        }
+
+    protected:
+        unsigned int m_depthID;
+        int m_depthType;
+        SpaceModule* m_space;
+};
+
+
+#endif
+
diff --git a/src/modules/DepthShapeModule.cpp b/src/modules/DepthShapeModule.cpp
new file mode 100644
index 0000000..3f9438e
--- /dev/null
+++ b/src/modules/DepthShapeModule.cpp
@@ -0,0 +1,83 @@
+/***************************************************************************
+ *  DepthShapeModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "DepthShapeModule.hpp" 
+
+#include <iostream>
+
+#include "../Reveal.hpp"
+#include "SpaceModule.hpp"
+#include "../geoms/Geometry.hpp"
+
+using namespace std;
+
+DepthShapeModule::DepthShapeModule(): ShapeModule(), DepthModule() {
+    m_type="DepthShape";
+    m_name="depthshape";
+    m_depthType=1;
+
+    addNameAttribute();
+    addRemoveAttribute();
+    addVisibleAttribute();
+    addShapeAttributes();
+    addTransformationAttributes();
+	addFollowMarkerAttribute();
+
+    vector<float> dims(3,200.0);
+    dims[2]=1;
+    m_attributesMap["dimensions"]->setFloats(dims);
+}
+
+DepthShapeModule::~DepthShapeModule() {
+    m_space->getGeom(m_shapesMap[m_currentShape])
+                ->unregisterModule(this);
+}
+
+void DepthShapeModule::updateModelMatrix() {
+    ShapeModule::updateModelMatrix();
+}
+
+void DepthShapeModule::setSpace(SpaceModule* space) {
+    DepthModule::setSpace(space);
+    m_space->getGeom(m_shapesMap[m_currentShape])->registerModule(this);
+}
+
+void DepthShapeModule::setShape(const std::string& shape) {
+    bool found=false;
+    vector<string>::iterator itIns=m_shapes.begin();
+    for(; itIns!=m_shapes.end(); ++itIns) {
+        if((*itIns).compare(shape)==0) {
+            found=true;
+        }
+    }
+    if(found) {
+        if(m_currentShape.compare("")!=0) {
+            m_space->getGeom(m_shapesMap[m_currentShape])
+                        ->unregisterModule(this);
+        }
+        m_currentShape=shape;
+        m_space->getGeom(m_shapesMap[m_currentShape])
+                    ->registerModule(this);
+    }
+}
+
diff --git a/src/modules/DepthShapeModule.hpp b/src/modules/DepthShapeModule.hpp
new file mode 100644
index 0000000..f45adb9
--- /dev/null
+++ b/src/modules/DepthShapeModule.hpp
@@ -0,0 +1,42 @@
+/***************************************************************************
+ *  DepthShapeModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DepthShapeModule_h
+#define DepthShapeModule_h
+
+#include "ShapeModule.hpp"
+#include "DepthModule.hpp"
+
+class DepthShapeModule : public ShapeModule, public DepthModule {
+    public:
+        DepthShapeModule();
+        virtual ~DepthShapeModule();
+        virtual void updateModelMatrix();
+        virtual void setSpace(SpaceModule* space);
+        void setShape(const std::string& shape);
+    private:
+};
+
+
+#endif
+
diff --git a/src/modules/GeomModule.cpp b/src/modules/GeomModule.cpp
new file mode 100644
index 0000000..3ddaf6d
--- /dev/null
+++ b/src/modules/GeomModule.cpp
@@ -0,0 +1,63 @@
+/***************************************************************************
+ *  GeomModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "GeomModule.hpp" 
+#include "../geoms/Geometry.hpp"
+
+using namespace std;
+using namespace glm;
+
+GeomModule::GeomModule(): Module(), 
+                          m_localInsideAxes(true), 
+                          m_currentGeom(NULL) {
+	m_subShapeInvMats.push_back(glm::mat4(1));
+}
+
+GeomModule::~GeomModule() {}
+
+void GeomModule::draw(const int& contextID,
+                      const Reveal::REVIL_PROGRAM& prog, 
+                      map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                      const unsigned int& component) {
+    glUniformMatrix4fv(uniforms[Reveal::MODELMAT], 1, 
+                       GL_FALSE, value_ptr(m_modelMat));
+    if(prog==Reveal::RENDERPROG) {
+		glUniformMatrix4fv(uniforms[Reveal::INVMODELMAT], 1, 
+						   GL_FALSE, value_ptr(m_invModelMat));
+		glUniform3fv(uniforms[Reveal::MODELSCALE], 1, value_ptr(m_modelScale));
+
+        glUniformMatrix4fv(uniforms[Reveal::SUBSHAPEINVMAT], 1,
+						   GL_FALSE, value_ptr(m_subShapeInvMats[component]));
+        glUniform1f(uniforms[Reveal::SUBSHAPEID], component);
+        glUniform1f(uniforms[Reveal::SUBSHAPESNB], m_subShapeInvMats.size());
+    }
+}
+
+void GeomModule::deleteModule() {
+    if(m_currentGeom) {
+        m_currentGeom->unregisterModule(this);
+    }
+    Module::deleteModule();
+}
+
+
+
diff --git a/src/modules/GeomModule.hpp b/src/modules/GeomModule.hpp
new file mode 100644
index 0000000..0aa00bd
--- /dev/null
+++ b/src/modules/GeomModule.hpp
@@ -0,0 +1,57 @@
+/***************************************************************************
+ *  GeomModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef GeomModule_h
+#define GeomModule_h
+
+#include "Module.hpp"
+
+#include "../Reveal.hpp"
+
+class GeomModule : public virtual Module {
+    public:
+        GeomModule();
+        virtual ~GeomModule();
+        void deleteModule();
+
+        virtual void draw(const int& contextID,
+                          const Reveal::REVIL_PROGRAM& prog, 
+                          std::map<Reveal::REVIL_UNIFORM, GLint>& uniforms, 
+                          const unsigned int& component=0);
+
+        virtual void setGeomID(const unsigned int& id){m_geomID=id;}
+        virtual const unsigned int& getGeomID(){return m_geomID;}
+
+    protected:
+        unsigned int m_geomID;
+        bool m_localInsideAxes;
+        Geometry* m_currentGeom;
+		std::vector<glm::mat4> m_subShapeInvMats;
+        std::map<int, glm::vec4> m_boundingRect;
+		std::map<int, bool> m_boundingRectUpdate;
+        glm::vec3 m_bbPnts[2];
+};
+
+
+#endif
+
diff --git a/src/modules/GroupModule.cpp b/src/modules/GroupModule.cpp
new file mode 100644
index 0000000..805193d
--- /dev/null
+++ b/src/modules/GroupModule.cpp
@@ -0,0 +1,162 @@
+/***************************************************************************
+ *  GroupModule.cpp
+ *  Part of GroupModule
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "GroupModule.hpp" 
+
+#include <iostream>
+#include "../Reveal.hpp"
+
+using namespace std;
+
+GroupModule::GroupModule():Module() {
+    m_type="Group";
+}
+
+GroupModule::~GroupModule() {}
+
+void GroupModule::draw() {
+    vector<Module*>::iterator itChild = m_children.begin();
+    for(; itChild!=m_children.end(); ++itChild) {
+        (*itChild)->draw();
+    }
+}
+
+void GroupModule::deleteModule() {
+    deleteChildren();
+    Module::deleteModule();
+}
+
+void GroupModule::deleteChildren() {
+    while(m_children.size()>0) {
+        m_children.back()->deleteModule();
+    }
+    m_childrenMap.clear();
+}
+
+void GroupModule::addChild(Module* mod) {
+    unsigned int newChildID=0;
+    while(m_childrenMap.find(newChildID)!=m_childrenMap.end()) {
+        newChildID++;
+    }
+    m_childrenMap[newChildID]=mod;
+    m_children.push_back(mod);
+    mod->setChildID(newChildID);
+    mod->setParent(this);
+    mod->setDepth(m_depth+1);
+    updateModelMatrix();
+    setVisible(m_visible);
+}
+
+void GroupModule::removeChild(Module* mod) {
+    m_childrenMap.erase(mod->getChildID());
+    vector<Module*>::iterator itChild = m_children.begin();
+    for(; itChild!=m_children.end();) {
+        if((*itChild)->getChildID()==mod->getChildID()) {
+            itChild=m_children.erase(itChild);
+        }
+        else {
+            ++itChild;
+        }
+    }
+}
+
+void GroupModule::getSubTree(std::vector<Module*>& children) {
+    children.push_back(this);
+    vector<Module*>::iterator itChild = m_children.begin();
+    for(; itChild!=m_children.end(); ++itChild) {
+        (*itChild)->getSubTree(children);
+    }
+}
+
+void GroupModule::load(xmlNodePtr node) {
+    Module::load(node);
+    xmlNodePtr modsNode;
+    for(modsNode=node->children; modsNode; modsNode=modsNode->next){
+        if(modsNode->type == XML_ELEMENT_NODE &&
+                !xmlStrcmp(modsNode->name, (const xmlChar *) "Modules")) {
+            xmlNodePtr modNode;
+            for(modNode=modsNode->children; modNode; modNode=modNode->next){
+                if(modNode->type == XML_ELEMENT_NODE) {
+                    string typeStr((char*) modNode->name);
+                    Module* mod = Reveal::getInstance()->createModule(typeStr);
+                    if(mod) {
+                        addChild(mod);
+                        mod->load(modNode);
+                    }
+                }
+            }
+        }
+    }
+}
+
+xmlNodePtr GroupModule::save(xmlNodePtr parentNode) {
+    xmlNodePtr newNode = Module::save(parentNode);
+    xmlNodePtr modsNode = xmlNewChild(newNode, NULL, 
+                                      BAD_CAST "Modules", NULL);
+    vector<Module*>::iterator itChild = m_children.begin();
+    for(; itChild!=m_children.end(); ++itChild) {
+        (*itChild)->save(modsNode);
+    }
+    return newNode;
+}
+
+void GroupModule::listModulesAndAttributes(const std::string& parentName, 
+                                      std::map<std::string, Module*>& mods,
+                                      std::map<std::string, Attribute*>& atts) {
+    Module::listModulesAndAttributes(parentName, mods, atts);
+    vector<Module*>::iterator itChild = m_children.begin();
+    for(; itChild!=m_children.end(); ++itChild) {
+        (*itChild)->listModulesAndAttributes(parentName+"/"+m_name, mods, atts);
+    }
+}
+
+void GroupModule::updateModelMatrix() {
+    Module::updateModelMatrix();
+    vector<Module*>::iterator itChild = m_children.begin();
+    for(; itChild!=m_children.end(); ++itChild) {
+        (*itChild)->setParentMatrix(m_modelMat);
+        (*itChild)->updateModelMatrix();
+    }
+}
+
+void GroupModule::setVisible(bool vis) {
+    m_visible=vis;
+    vector<Module*>::iterator itChild = m_children.begin();
+    for(; itChild!=m_children.end(); ++itChild) {
+        (*itChild)->setParentVisible(m_parentVisible&&m_visible);
+    }
+}
+
+void GroupModule::setParentVisible(bool pvis) {
+    m_parentVisible=pvis;
+    setVisible(m_visible);
+}
+
+void GroupModule::getVisibleFromList(std::vector<string>& modVec, 
+                                     std::map<std::string, int>& modMap) { 
+    vector<Module*>::iterator itChild = m_children.begin();
+    for(; itChild!=m_children.end(); ++itChild) {
+        (*itChild)->getVisibleFromList(modVec, modMap);
+    }
+}
+
diff --git a/src/modules/GroupModule.hpp b/src/modules/GroupModule.hpp
new file mode 100644
index 0000000..ba06922
--- /dev/null
+++ b/src/modules/GroupModule.hpp
@@ -0,0 +1,59 @@
+/***************************************************************************
+ *  GroupModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef GroupModule_h
+#define GroupModule_h
+
+#include "Module.hpp"
+
+class GroupModule: public virtual Module {
+    public:
+        GroupModule();
+        virtual ~GroupModule();
+        virtual void draw();
+        virtual void addChild(Module* mod);
+        virtual void removeChild(Module* mod);
+        virtual void getSubTree(std::vector<Module*>& children); 
+        void deleteModule();
+        void deleteChildren();
+
+        virtual void load(xmlNodePtr node);
+        virtual xmlNodePtr save(xmlNodePtr parentNode);
+
+        void listModulesAndAttributes(const std::string& parentName, 
+                                      std::map<std::string, Module*>& mods,
+                                      std::map<std::string, Attribute*>& atts);
+        virtual void updateModelMatrix();
+        virtual void setVisible(bool vis);
+        virtual void setParentVisible(bool pvis);
+
+        virtual void getVisibleFromList(std::vector<std::string>& modVec, 
+                                        std::map<std::string, int>& modMap);
+
+    protected:
+        std::vector<Module*> m_children;
+        std::map<unsigned int, Module*> m_childrenMap;
+};
+
+#endif
+
diff --git a/src/modules/Listener.cpp b/src/modules/Listener.cpp
new file mode 100644
index 0000000..fa277b5
--- /dev/null
+++ b/src/modules/Listener.cpp
@@ -0,0 +1,73 @@
+/***************************************************************************
+ *  Listener.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "Listener.hpp"
+#include <iostream>
+#include <sstream>
+#include "Attribute.hpp"
+#include "../Reveal.hpp"
+
+using namespace std;
+
+Listener::Listener():m_saved(true){}
+
+void Listener::deleteListener() {
+    m_attribute->removeListener(this);
+    Reveal::getInstance()->deleteListener(this);
+}
+
+void Listener::setParameters(const vector<string>& params) { 
+    if(params.size()==m_parameters.size()) {
+        m_parameters=params;
+    }
+}
+
+void Listener::load(xmlNodePtr lisNode) {
+    vector<string> params;
+    xmlNodePtr paramNode;
+    for(paramNode=lisNode->children; paramNode; paramNode=paramNode->next){
+        if(paramNode->type == XML_ELEMENT_NODE) {
+            if(!xmlStrcmp(paramNode->name, (const xmlChar *)"Parameter")) {
+                char* value = (char*)xmlGetProp(paramNode,(xmlChar*)"value");
+                if(value!=NULL) {
+                    params.push_back(value);
+                }
+            }
+        }
+    }
+    setParameters(params);
+}
+
+void Listener::save(xmlNodePtr parentNode) {
+    if(m_saved) {
+        xmlNodePtr lisNode = xmlNewChild(parentNode, NULL, 
+                                          BAD_CAST m_listenerType.c_str(), 
+                                          NULL);
+        vector<string>::iterator itParam = m_parameters.begin();
+        for(; itParam!=m_parameters.end(); ++itParam) {
+            xmlNodePtr parNode = xmlNewChild(lisNode, NULL, 
+                                             BAD_CAST "Parameter", NULL);
+            xmlNewProp(parNode,BAD_CAST"value",BAD_CAST (*itParam).c_str());
+        }
+    }
+}
+
diff --git a/src/modules/Listener.hpp b/src/modules/Listener.hpp
new file mode 100644
index 0000000..8ed8c7b
--- /dev/null
+++ b/src/modules/Listener.hpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+ *  Listener.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef Listener_h
+#define Listener_h
+
+#include <string>
+#include <vector>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+class Attribute;
+
+class Listener {
+    public:
+        Listener();
+        virtual ~Listener(){}
+        void deleteListener();
+
+        virtual void load(xmlNodePtr node);
+        virtual void save(xmlNodePtr parentNode);
+
+        virtual void update(std::vector<float>& floatValues, 
+                            std::vector<int>& intValues,
+                            std::vector<bool>& boolValues,
+                            std::vector<std::string>& stringValues)=0;
+                            
+        inline const int& getID(){return m_listenerID;}
+        inline void setID(const int& id){m_listenerID=id;}
+        inline virtual void setAttribute(Attribute* att){m_attribute=att;}
+		inline Attribute* getAttribute(){return m_attribute;}
+
+        inline std::vector<std::string>& editParameters(){return m_parameters;}
+        inline std::vector<std::vector<std::string> >& editParametersValues() {
+            return m_parametersValues;
+        }
+        virtual void setParameters(const std::vector<std::string>& par);
+
+        inline const std::string& getListenerType(){return m_listenerType;}
+        inline std::string& editListenerType(){return m_listenerType;}
+
+
+    protected:
+        int m_listenerID;
+        Attribute* m_attribute;
+        std::string m_listenerType;
+        std::vector<std::string> m_parameters;
+        std::vector<std::vector<std::string> > m_parametersValues;
+        bool m_saved;
+};
+
+#endif
diff --git a/src/modules/ModelModule.cpp b/src/modules/ModelModule.cpp
new file mode 100644
index 0000000..6b3f746
--- /dev/null
+++ b/src/modules/ModelModule.cpp
@@ -0,0 +1,286 @@
+/***************************************************************************
+ *  ModelModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define AI_CONFIG_PP_SBP_REMOVE aiPrimitiveType_LINE|aiPrimitiveType_POINT
+
+#include "ModelModule.hpp" 
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include "../Reveal.hpp"
+#include <glm/gtx/matrix_decompose.hpp>
+#include <glm/gtx/quaternion.hpp>
+#include <glm/gtx/polar_coordinates.hpp>
+#include "opencv2/imgproc/imgproc.hpp"
+#include <opencv2/highgui/highgui.hpp>
+
+#include <assimp/Importer.hpp>
+#include <assimp/scene.h>
+#include <assimp/postprocess.h>
+
+#include "../geoms/Geometry.hpp"
+
+using namespace std;
+using namespace glm;
+
+ModelModule::ModelModule(): GeomModule() {
+    m_type="Model";
+    m_name="model";
+
+    m_modelGeom = new Geometry();
+    Reveal::getInstance()->registerGeom(m_modelGeom);
+    m_modelGeom->registerModule(this);
+
+    m_coordImage = new float[m_texWidth*m_texHeight*2];
+}
+
+ModelModule::~ModelModule() {}
+
+void ModelModule::addModelAttributes() {
+    addAttribute(new Attribute("model", 
+                                Attribute::FILE_OPEN_ATTRIBUTE,
+                                modelCallback, this));
+    addAttribute(new Attribute("dimensions", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                dimensionsCallback, this, 3));
+    m_attributesMap["dimensions"]->setFloats(vector<float>(3,100.0));
+}
+
+void ModelModule::updateModelMatrix() {
+    Module::updateModelMatrix();
+
+    mat4 dimMat = scale(m_dimensions);
+    m_modelMat = m_modelMat * dimMat;
+	m_invModelMat = inverse(m_modelMat);
+
+    vec3 decTrans, decSkew;
+    quat decRot;
+    vec4 decPers;
+    decompose(m_modelMat, m_modelScale, decRot, decTrans, decSkew, decPers);
+
+	/*
+    //update bounding box as well 
+	vec4 pnts[8];
+    vec4 locpnts[8];
+    int p=0;
+    for(float x=-0.5; x<1; x+=1.0) {
+        for(float y=-0.5; y<1; y+=1.0) {
+            for(float z=-0.5; z<1; z+=1.0) {
+                pnts[p] = m_modelMat*vec4(x, y, z, 1.0);
+                locpnts[p] = vec4(m_modelScale[0]*x, 
+                                  m_modelScale[1]*y, 
+                                  m_modelScale[2]*z, 
+                                  1.0);
+                ++p;
+            }
+        }
+    }
+    m_bbPnts[0]=pnts[0];
+    m_bbPnts[1]=pnts[0];
+    for(p=1; p<8; ++p) {
+        for(int c=0; c<3;++c) {
+            m_bbPnts[0][c]=std::min<float>(pnts[p][c], m_bbPnts[0][c]);
+            m_bbPnts[1][c]=std::max<float>(pnts[p][c], m_bbPnts[1][c]);
+        }
+    }
+
+	for(auto &up : m_boundingRectUpdate) {
+		up.second=true;
+	}
+*/
+
+    //update bounding box as well 
+	/*
+    vec4 pnts[8];
+    vec4 locpnts[8];
+    int p=0;
+    for(int x=0; x<2; x++) {
+        for(int y=0; y<2; y++) {
+            for(int z=0; z<2; z++) {
+                pnts[p] = m_modelMat*vec4(m_bbPnts[x].x, m_bbPnts[y].y, 
+                                          m_bbPnts[z].z, 1.0);
+                locpnts[p] = vec4(decScale[0]*m_bbPnts[x].x, 
+                                  decScale[1]*m_bbPnts[y].y, 
+                                  decScale[2]*m_bbPnts[z].z, 
+                                  1.0);
+                ++p;
+            }
+        }
+    }
+    m_bboxMins[0]=pnts[0];
+    vec4 bboxMax=pnts[0];
+    vec4 bboxLocMin=locpnts[0];
+    vec4 bboxLocMax=locpnts[0];
+    for(p=1; p<8; ++p) {
+        for(int c=0; c<3;++c) {
+            m_bboxMins[0][c]=std::min<float>(pnts[p][c], m_bboxMins[0][c]);
+            bboxMax[c]=std::max<float>(pnts[p][c], bboxMax[c]);
+            bboxLocMin[c]=std::min<float>(locpnts[p][c], bboxLocMin[c]);
+            bboxLocMax[c]=std::max<float>(locpnts[p][c], bboxLocMax[c]);
+        }
+    }
+
+    for(unsigned int c=0; c<m_modelGeom->editCompoSizes().size(); ++c) {
+        //store min and size (max-min)
+        m_bboxMins[c]=m_bboxMins[0];
+        m_bboxSizes[c] = bboxMax-m_bboxMins[c];
+        m_bboxLocalMin[c] = bboxLocMin;
+        m_bboxLocalSizes[c] = bboxLocMax-bboxLocMin;
+        
+        if(m_localInsideAxes) {
+			m_bboxRots[0] = glm::inverse(toMat4(decRot));
+        }
+        else {
+            m_bboxRots[c] = mat4(1.0);
+        }
+    }*/
+
+}
+
+void ModelModule::setDimensions(const float& x, const float& y,const float& z) {
+    m_dimensions=vec3(x, y, z);
+    updateModelMatrix();
+}
+
+void ModelModule::setModel(const std::string& fileName) {
+	m_modelStr = "";
+
+    vector<GLfloat>& vertices = m_modelGeom->editVertexBufferData();
+    vector<GLuint>& indices = m_modelGeom->editIndexBufferData();
+    vector<int>& sizes = m_modelGeom->editCompoSizes();
+    m_modelGeom->hasTexCoords(true);
+
+    vertices.clear();
+    indices.clear();
+    sizes.clear();
+
+    float fMax = std::numeric_limits<float>::max();
+    float fMin = -std::numeric_limits<float>::max();
+    m_bbPnts[0] = glm::vec3(fMax, fMax, fMax);
+    m_bbPnts[1] = glm::vec3(fMin, fMin, fMin);
+
+    memset(m_coordImage, 0, m_texWidth*m_texHeight*2*sizeof(float));
+
+
+    string dir = fileName.substr(0, fileName.find_last_of("/"))+"/";
+
+
+    Assimp::Importer importer;
+    const aiScene* scene = importer.ReadFile( fileName, 
+                 aiProcess_Triangulate            |
+                 aiProcess_JoinIdenticalVertices  |
+                 aiProcess_SortByPType); 
+    if(!scene) {
+        cout<<"Error opening model "<<fileName<<endl;
+        return;
+    }
+
+    if(scene->HasMeshes()) {
+        for(unsigned int ma=0;ma<scene->mNumMaterials;++ma) {
+            int nbTex=scene->mMaterials[ma]->GetTextureCount(
+                                                aiTextureType_DIFFUSE);
+            if(nbTex>0) {
+                aiString texName;
+                scene->mMaterials[ma]->GetTexture(aiTextureType_DIFFUSE,
+                                                  0, &texName);
+                if(m_attributesMap.find("surface_texture")
+                        !=m_attributesMap.end()) {
+                    string tName = texName.C_Str();
+                    m_attributesMap["surface_texture"]->setFile(dir+"/"+tName);
+                }
+            }
+        }
+
+		//compute bbox size
+		aiVector3D minV = aiVector3D(fMax, fMax, fMax);
+		aiVector3D maxV = aiVector3D(fMin, fMin, fMin);
+        for(unsigned int m=0; m<scene->mNumMeshes; ++m) {
+            aiMesh* mesh = scene->mMeshes[m];
+            for(unsigned int v=0; v<mesh->mNumVertices; ++v) {
+                aiVector3D& vert = mesh->mVertices[v];
+				for(int i=0; i<3; i++) {
+					minV[i] = std::min<float>(minV[i], vert[i]);
+					maxV[i] = std::max<float>(maxV[i], vert[i]);
+				}
+			}
+		}
+
+		vector<float> dims = {fabs(maxV[0]-minV[0]), 
+								fabs(maxV[1]-minV[1]),
+								fabs(maxV[2]-minV[2])};
+		vector<float> cnt = {(maxV[0]+minV[0])/2.0f, 
+							(maxV[1]+minV[1])/2.0f,
+							(maxV[2]+minV[2])/2.0f};
+
+        unsigned int meshCnt=0;
+        for(unsigned int m=0; m<scene->mNumMeshes; ++m) {
+            aiMesh* mesh = scene->mMeshes[m];
+            //write indices
+            for(unsigned int f=0; f<mesh->mNumFaces; ++f) {
+                aiFace& face = mesh->mFaces[f];
+                for(unsigned int i=0; i<face.mNumIndices; ++i) {
+                    indices.push_back(face.mIndices[i]+meshCnt);
+                }
+            }
+            sizes.push_back(mesh->mNumFaces*3);
+            meshCnt+=mesh->mNumVertices;
+
+            //write normalized vertices and texcoords
+            for(unsigned int v=0; v<mesh->mNumVertices; ++v) {
+                aiVector3D& vert = mesh->mVertices[v];
+                for(int i=0; i<3; ++i) {
+					vertices.push_back((vert[i]-minV[i])/(maxV[i]-minV[i])-0.5);
+                }
+                if(mesh->HasTextureCoords(0)) {
+                    vertices.push_back(mesh->mTextureCoords[0][v][0]);
+                    vertices.push_back(mesh->mTextureCoords[0][v][1]);
+                }
+                else {
+                    vertices.push_back(0);
+                    vertices.push_back(0);
+                }
+
+            }
+        }
+
+		//write bounding box
+		m_bbPnts[0].x = -0.5;
+		m_bbPnts[0].y = -0.5;
+		m_bbPnts[0].z = -0.5;
+		m_bbPnts[1].x = 0.5;
+		m_bbPnts[1].y = 0.5;
+		m_bbPnts[1].z = 0.5;
+
+		//write dimensions
+		m_attributesMap["dimensions"]->setFloats(dims);
+		m_attributesMap["position"]->setFloats(cnt);
+
+		m_modelStr = fileName;
+    }
+
+
+    m_modelGeom->refresh();
+    updateModelMatrix();            
+}
+
diff --git a/src/modules/ModelModule.hpp b/src/modules/ModelModule.hpp
new file mode 100644
index 0000000..32b0d21
--- /dev/null
+++ b/src/modules/ModelModule.hpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+ *  ModelModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef ModelModule_h
+#define ModelModule_h
+
+#include "GeomModule.hpp"
+
+class ModelModule : public virtual GeomModule {
+    public:
+        ModelModule();
+        virtual ~ModelModule();
+
+        static void modelCallback(Module* mod, 
+                                  const std::string& f) {
+            dynamic_cast<ModelModule*>(mod)->setModel(f);
+        }
+        virtual void setModel(const std::string&);
+        static void dimensionsCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            dynamic_cast<ModelModule*>(mod)->setDimensions(vals[0], 
+                                                           vals[1], 
+                                                           vals[2]);
+        }
+        void setDimensions(const float&, const float&, const float&);
+
+        virtual void updateModelMatrix();
+        void addModelAttributes();
+    
+    protected:
+        Geometry* m_modelGeom;
+        float* m_coordImage;
+        glm::vec3 m_dimensions;
+		std::string m_modelStr;
+
+    private:
+        struct ModelVertex {
+            glm::vec3 pos;
+            glm::vec2 tex;
+            bool compare(ModelVertex& v) {
+                if(v.pos.x==pos.x && v.pos.y==pos.y && v.pos.z==pos.z 
+                        && v.tex.x==tex.x && v.tex.y==tex.y) {
+                    return true; 
+                }
+                return false;
+            }
+        };
+};
+
+
+#endif
+
diff --git a/src/modules/Module.cpp b/src/modules/Module.cpp
new file mode 100644
index 0000000..2c4eea1
--- /dev/null
+++ b/src/modules/Module.cpp
@@ -0,0 +1,423 @@
+/***************************************************************************
+ *  Module.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "Module.hpp"
+#include <iostream>
+#include <limits>
+#include <sstream>
+
+#include <glm/gtx/euler_angles.hpp>
+#include <glm/gtx/quaternion.hpp>
+#include <glm/gtx/matrix_decompose.hpp>
+#include <glm/gtx/norm.hpp>
+
+#include "../Reveal.hpp"
+#include "SpaceModule.hpp"
+#include "DepthCamModule.hpp"
+
+using namespace std;
+using namespace glm;
+
+Module::Module() {
+    m_depth=0;
+    m_type="Module";
+    m_position=vec3(0.0, 0.0, 0.0);
+    m_scale=vec3(1.0, 1.0, 1.0);
+	m_modelScale = vec3(1.0, 1.0, 1.0);
+    m_parent=NULL;
+    m_parentMat = mat4(1.0);
+    m_modelMat = mat4(1.0);
+    m_rotMat = mat4(1.0);
+    m_visible=true;
+    m_parentVisible=true;
+    m_upID=-1;
+    m_visibilityMask=1;
+    m_texWidth=640;
+    m_texHeight=480;
+}
+
+void Module::deleteModule() {
+    vector<Attribute*>::iterator itAtt = m_attributesVec.begin();
+    for(; itAtt!=m_attributesVec.end(); ++itAtt) {
+        (*itAtt)->clearListeners();
+    }
+    if(m_parent!=NULL) {
+        m_parent->removeChild(this);
+    }
+    Reveal::getInstance()->deleteModule(this);
+}
+
+Module::~Module() { 
+    vector<Attribute*>::iterator itAtt = m_attributesVec.begin();
+    for(; itAtt!=m_attributesVec.end(); ++itAtt) {
+        delete (*itAtt);
+    }
+    m_attributesVec.clear();
+    m_attributesMap.clear();
+}
+
+void Module::load(xmlNodePtr node) {
+    //call load on each attribute, from their names
+    xmlNodePtr attsNode;
+    for(attsNode=node->children; attsNode; attsNode=attsNode->next){
+        if(attsNode->type == XML_ELEMENT_NODE &&
+                !xmlStrcmp(attsNode->name, (const xmlChar *) "Attributes")) {
+            xmlNodePtr attNode;
+            for(attNode=attsNode->children; attNode; attNode=attNode->next){
+                if(attNode->type == XML_ELEMENT_NODE) {
+                    string nameStr((char*) attNode->name);
+                    if(m_attributesMap.find(nameStr)!=m_attributesMap.end()) {
+                        m_attributesMap[nameStr]->load(attNode);
+                    }
+                }
+            }
+        }
+    }
+}
+
+xmlNodePtr Module::save(xmlNodePtr parentNode) {
+    xmlNodePtr newNode;
+    if(parentNode==NULL) {
+        newNode = xmlNewNode(NULL, BAD_CAST m_type.c_str());
+    }
+    else {
+         newNode = xmlNewChild(parentNode, NULL, 
+                               BAD_CAST m_type.c_str(), NULL);
+    }
+    xmlNodePtr attsNode = xmlNewChild(newNode, NULL, 
+                                      BAD_CAST "Attributes", NULL);
+    vector<Attribute*>::iterator itAtt = m_attributesVec.begin();
+    for(; itAtt!=m_attributesVec.end(); ++itAtt) {
+        (*itAtt)->save(attsNode);
+    }
+    return newNode;
+}
+
+void Module::setName(const std::string& name) {
+    m_name=name;
+    Reveal::getInstance()->refreshModules();
+}
+
+void Module::setVisibleFrom(const std::string& visibleFrom) {
+    //find space or proj, get visibility bit
+    setVisibilityMask(Reveal::getInstance()->getVisibilityMask(visibleFrom));
+}
+
+void Module::setVisibleFromList(vector<string>& modVec) {
+    map<string, Attribute*>::iterator itAtt 
+        = m_attributesMap.find("visible_from");
+    if(itAtt!=m_attributesMap.end()) {
+        itAtt->second->editStringValuesChoices().assign(1, modVec);
+    }
+}
+
+void Module::setRevealedBy(const std::string& by) {
+    m_revealedBy=0;
+    if(!by.compare("none") || !by.compare("0") || by.length()==0) {
+        m_revealedBy=0;
+    }
+    else if(!by.compare("all")) {
+        m_revealedBy=numeric_limits<int>::max();
+    }
+    else {
+        //get all markers 
+        string markStr=by;
+        while(markStr.length()>0) {
+            size_t pos=markStr.find_first_of('|');
+            string subStr = markStr.substr(0,pos);
+            istringstream iss(subStr);
+            int mark;
+            iss>>mark;
+            m_revealedBy |= 1 << (mark);
+            markStr = (pos==string::npos)?"":markStr.substr(pos+1);
+        }
+    }
+    m_revealedBy=std::max(0,m_revealedBy);
+}
+
+void Module::setPosition(const float& posX, 
+                         const float& posY, 
+                         const float& posZ) {
+    m_position = vec3(posX, posY, posZ);
+    updateModelMatrix();
+}
+
+void Module::setScale(const float& scaX, 
+                      const float& scaY, 
+                      const float& scaZ) {
+    m_scale= vec3(scaX, scaY, scaZ);
+    updateModelMatrix();
+}
+
+void Module::setRotation(const float& rotX, 
+                         const float& rotY, 
+                         const float& rotZ) {
+    m_rotEuler = vec3(rotX/180.0*M_PI, rotZ/180.0*M_PI, rotY/180.0*M_PI);
+    m_rotQuat = toQuat(orientate3(m_rotEuler));
+    m_rotMat = toMat4(m_rotQuat);
+    vector<float> quatVec(4, 0.0);
+    quatVec[0]=m_rotQuat[0];
+    quatVec[1]=m_rotQuat[1];
+    quatVec[2]=m_rotQuat[2];
+    quatVec[3]=m_rotQuat[3];
+    m_attributesMap["quaternion"]->initFloats(quatVec);
+    updateModelMatrix();
+}
+
+void Module::setQuaternion(const float& rotX, 
+                           const float& rotY, 
+                           const float& rotZ,
+                           const float& rotW) {
+    m_rotQuat = quat(rotX, rotY, rotZ, rotW);
+    m_rotEuler = eulerAngles(m_rotQuat);
+    m_rotMat = toMat4(m_rotQuat);
+    vector<float> rotVec(3, 0.0);
+    rotVec[0]=m_rotEuler[0]/M_PI*180.0;
+    rotVec[1]=m_rotEuler[1]/M_PI*180.0;
+    rotVec[2]=m_rotEuler[2]/M_PI*180.0;
+    m_attributesMap["rotation"]->initFloats(rotVec);
+    updateModelMatrix();
+}
+
+void Module::setFollowMarker(const int& markID) {
+	if(markID>0) { 
+		//if not already registered
+		//subscribe to marker update in all depthcams of all spaces
+		if(m_markerListeners.size()==0) { 
+			const std::vector<SpaceModule*>& spaces = Reveal::getInstance()
+													->getSpaces()->getSpaces();
+			for(SpaceModule* sp:spaces) {
+				unsigned int nbcams = sp->getNbDepthCamModules();
+				for(unsigned int i=0; i<nbcams; ++i) {
+					Attribute* attr 
+						= dynamic_cast<SpaceModule*>(sp)
+										->getDepthCamModule(i)
+											->getAttribute("marker_output");
+					if(attr) {
+						//create a listener for that camera
+						m_markerListeners.push_back(MarkerListener(this));
+
+						//register that listener
+						attr->addListener(&m_markerListeners.back());
+					}
+				}
+			}
+		}
+		//update marker number
+		for(auto& mark:m_markerListeners) {
+			mark.setMarkerID(markID);
+		}
+	}
+	else { //unsubscribe all
+		for(auto& mark:m_markerListeners) {
+			mark.getAttribute()->removeListener(&mark);
+		}
+		m_markerListeners.clear();
+	}
+}
+
+void Module::setModelMat(const glm::mat4& mat) { 
+    m_modelMat=mat;
+	m_invModelMat = inverse(m_modelMat);
+
+    glm::vec3 sk;
+    glm::vec4 pers;
+    glm::decompose(m_modelMat, m_scale, m_rotQuat, m_position, sk, pers);
+    m_rotMat = toMat4(m_rotQuat);
+    m_rotEuler = eulerAngles(m_rotQuat);
+	m_modelScale = m_scale;
+
+
+    vector<float> posVec(3, 0.0);
+    posVec[0]=m_position[0];posVec[1]=m_position[1];posVec[2]=m_position[2];
+    m_attributesMap["position"]->initFloats(posVec);
+    vector<float> rotVec(3, 0.0);
+    rotVec[0]=m_rotEuler[0]/M_PI*180.0;
+    rotVec[1]=m_rotEuler[1]/M_PI*180.0;
+    rotVec[2]=m_rotEuler[2]/M_PI*180.0;
+    m_attributesMap["rotation"]->initFloats(rotVec);
+    vector<float> quatVec(4, 0.0);
+    quatVec[0]=m_rotQuat[0];quatVec[1]=m_rotQuat[1];
+    quatVec[2]=m_rotQuat[2];quatVec[3]=m_rotQuat[3];
+    m_attributesMap["quaternion"]->initFloats(quatVec);
+}
+
+void Module::updateModelMatrix() {
+    mat4 transMat = translate(m_position);
+    mat4 scaleMat = scale(m_scale);
+    m_modelMat = m_parentMat * transMat * m_rotMat * scaleMat;
+	m_invModelMat = inverse(m_modelMat);
+	for(int i=0; i<3; i++) {
+		m_modelScale[i] = length(vec3(m_modelMat[i][0],
+									  m_modelMat[i][1],
+									  m_modelMat[i][2]));
+	}
+
+    if(m_attributesMap.find("absolute_position")!=m_attributesMap.end()) {
+        vector<float> absP(3,0);
+        absP[0]=m_modelMat[3][0];
+        absP[1]=m_modelMat[3][1];
+        absP[2]=m_modelMat[3][2];
+        m_attributesMap["absolute_position"]->setFloats(absP);
+    }
+}
+
+void Module::listModulesAndAttributes(const std::string& parentName, 
+                                      std::map<std::string, Module*>& mods,
+                                      std::map<std::string, Attribute*>& atts) {
+    m_fullName = parentName+"/"+m_name;
+    mods[m_fullName]=this;
+    vector<Attribute*>::iterator itAtt = m_attributesVec.begin();
+    for(; itAtt!=m_attributesVec.end(); ++itAtt) {
+        std::string fullName = parentName+"/"+m_name+"/"+(*itAtt)->getName();
+        atts[fullName] = (*itAtt);
+        (*itAtt)->setFullName(fullName);
+    }
+}
+
+void Module::addNameAttribute() {
+    addAttribute(new Attribute("name", 
+                                Attribute::STRING_ATTRIBUTE,
+                                nameCallback, this, 1));
+    m_attributesMap["name"]->setStrings(vector<string>(1, m_name));
+}
+
+void Module::addRemoveAttribute() {
+    addAttribute(new Attribute("remove", 
+                                Attribute::ACTION_ATTRIBUTE,
+                                removeCallback, this));
+}
+
+void Module::addTransformationAttributes() {
+    addAttribute(new Attribute("position", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                positionCallback, this, 3));
+    addAttribute(new Attribute("scale", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                scaleCallback, this, 3));
+    addAttribute(new Attribute("quaternion", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                quaternionCallback, this, 4));
+    addAttribute(new Attribute("rotation", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                rotationCallback, this, 3));
+    addAttribute(new Attribute("absolute_position", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                absPositionCallback, this, 3, 
+                                Attribute::HIDDEN));
+    m_attributesMap["scale"]->setFloats(vector<float>(3,1.0));
+}
+
+void Module::addVisibleAttribute() {
+    addAttribute(new Attribute("visible", 
+                                Attribute::BOOL_ATTRIBUTE,
+                                visibleCallback, this, 1));
+    m_attributesMap["visible"]->initBools(vector<bool>(1, true));
+}
+
+void Module::addVisibleFromAttribute() {
+    addAttribute(new Attribute("visible_from", 
+                                Attribute::STRING_ATTRIBUTE,
+                                visibleFromCallback, this, 1));
+    m_attributesMap["visible_from"]->initStrings(vector<string>(1, "all"));
+}
+
+void Module::addRevealedByAttribute() {
+    addAttribute(new Attribute("revealed_by", 
+                                Attribute::STRING_ATTRIBUTE,
+                                revealedByCallback, this, 1));
+/*
+    m_revealedBys.push_back("all");
+    m_revealedBys.push_back("1");
+    m_revealedBys.push_back("2");
+    m_revealedBys.push_back("3");
+    m_revealedBy=0;
+    m_attributesMap["revealed_by"]->editStringValuesChoices()
+                                        .assign(1,m_revealedBys);
+*/
+    m_attributesMap["revealed_by"]->setStrings(vector<string>(1, "all"));
+}
+
+void Module::addFollowMarkerAttribute() {
+    addAttribute(new Attribute("follow_marker", 
+                                Attribute::INT_ATTRIBUTE,
+                                followMarkerCallback, this, 1));
+
+}
+
+void Module::getQuatFromTwoVecs(glm::quat& q, glm::vec3& from, glm::vec3& to) {
+    glm::vec3 start = normalize(from);
+    glm::vec3 dest = normalize(to);
+
+    float cosTheta = dot(start, dest);
+    glm::vec3 rotationAxis;
+
+    if(cosTheta < -1 + 0.001f) {
+        rotationAxis = cross(glm::vec3(0.0f, 0.0f, 1.0f), start);
+        if(glm::length2(rotationAxis) < 0.01) {
+            rotationAxis = cross(glm::vec3(1.0f, 0.0f, 0.0f), start);
+        }
+        rotationAxis = normalize(rotationAxis);
+        q=glm::angleAxis(glm::radians(180.0f), rotationAxis);
+        return;
+    }
+
+    rotationAxis = cross(start, dest);
+
+    float s = sqrt( (1+cosTheta)*2 );
+    float invs = 1 / s;
+
+    q[0]=s * 0.5f;
+    q[1]=rotationAxis.x * invs;
+    q[2]=rotationAxis.y * invs;
+    q[3]=rotationAxis.z * invs;
+    return;
+}
+
+//----------------------------Marker Listener---------------------------------
+
+MarkerListener::MarkerListener(Module* mod) : Listener() {
+	m_mod=mod;
+	m_listenerType = "Marker";
+}
+
+MarkerListener::~MarkerListener() {
+
+}
+
+void MarkerListener::update(std::vector<float>& floatValues, 
+							std::vector<int>& intValues,
+							std::vector<bool>& boolValues,
+							std::vector<std::string>& stringValues) {
+	if(floatValues[0]==m_markerID && floatValues[1]>0) {
+		m_mod->getAttribute("position")
+			->setFloats(vector<float>{floatValues[2], 
+										floatValues[3], 
+										floatValues[4]});
+		m_mod->getAttribute("quaternion")
+			->setFloats(vector<float>{floatValues[5], 
+										floatValues[6], 
+										floatValues[7],
+										floatValues[8]});
+	}
+}
+
diff --git a/src/modules/Module.hpp b/src/modules/Module.hpp
new file mode 100644
index 0000000..8d91014
--- /dev/null
+++ b/src/modules/Module.hpp
@@ -0,0 +1,238 @@
+/***************************************************************************
+ *  Module.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef Module_h
+#define Module_h
+
+#include "Attribute.hpp"
+
+#define GLM_ENABLE_EXPERIMENTAL
+
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+#include <glm/vec3.hpp>
+#include <glm/vec4.hpp> 
+#include <glm/mat4x4.hpp> 
+#include <glm/gtc/quaternion.hpp> 
+#include <glm/gtc/matrix_transform.hpp>
+#include <glm/gtx/transform.hpp>
+#include <glm/gtc/type_ptr.hpp>
+
+class GroupModule;
+class MarkerListener;
+
+class Module {
+    public:
+        Module();
+        virtual ~Module();
+
+        virtual void draw(){}
+
+        virtual void load(xmlNodePtr node);
+        virtual xmlNodePtr save(xmlNodePtr parentNode);
+
+        void setParent(GroupModule* groupmod){m_parent=groupmod;}
+        void setChildID(const unsigned int& id){m_childID=id;}
+        const unsigned int& getChildID(){return m_childID;}
+        virtual void getSubTree(std::vector<Module*>& children) {
+            children.push_back(this);
+        }
+
+        inline unsigned int getNbAttributes(){return m_attributesVec.size();}
+        inline Attribute* getAttribute(const unsigned int& attr) { 
+            return m_attributesVec[attr];
+        }
+        inline Attribute* getAttribute(const std::string& attr) { 
+            return m_attributesMap[attr];
+        }
+        inline std::vector<Attribute*>& editAttributes() { 
+            return m_attributesVec;
+        }
+        inline void addAttribute(Attribute* attr) { 
+            m_attributesMap[attr->getName()]=attr;
+            m_attributesVec.push_back(attr);
+        }
+        static void nameCallback(Module* mod, 
+                                 const std::vector<std::string>& vals) {
+            static_cast<Module*>(mod)->setModuleName(vals[0]);
+        }
+        static void removeCallback(Module* mod) {
+            static_cast<Module*>(mod)->deleteModule();        
+        }
+        virtual void deleteModule();
+        static void positionCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            static_cast<Module*>(mod)->setPosition(vals[0], 
+                                                   vals[1], 
+                                                   vals[2]);
+        }
+        virtual void setPosition(const float& posX, 
+                                 const float& posY, 
+                                 const float& posZ);
+        static void absPositionCallback(Module* mod, 
+                                     const std::vector<float>& vals) {}
+
+        static void scaleCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            static_cast<Module*>(mod)->setScale(vals[0], 
+                                                vals[1], 
+                                                vals[2]);
+        }
+        virtual void setScale(const float& scaX, 
+                              const float& scaY, 
+                              const float& scaZ);
+        static void rotationCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            static_cast<Module*>(mod)->setRotation(vals[0], 
+                                                   vals[1], 
+                                                   vals[2]);
+        }
+        virtual void setRotation(const float& rotX, 
+                                 const float& rotY, 
+                                 const float& rotZ);
+        static void quaternionCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            static_cast<Module*>(mod)->setQuaternion(vals[0], 
+                                                     vals[1], 
+                                                     vals[2],
+                                                     vals[3]);
+        }
+        virtual void setQuaternion(const float& rotX, 
+                                   const float& rotY, 
+                                   const float& rotZ,
+                                   const float& rotW);
+
+        const glm::mat4& getModelMat(){return m_modelMat;}
+        virtual void setModelMat(const glm::mat4& mat);
+
+        static void followMarkerCallback(Module* mod, 
+                                     const std::vector<int>& vals) {
+            static_cast<Module*>(mod)->setFollowMarker(vals[0]);
+        }
+        virtual void setFollowMarker(const int& mark);
+
+        static void visibleCallback(Module* mod, 
+                                    const std::vector<bool>& vals) {
+            static_cast<Module*>(mod)->setVisible(vals[0]);
+        }
+
+        static void visibleFromCallback(Module* mod, 
+                                        const std::vector<std::string>& vals) {
+            static_cast<Module*>(mod)->setVisibleFrom(vals[0]);
+        }
+
+        static void revealedByCallback(Module* mod, 
+                                       const std::vector<std::string>& vals) {
+            static_cast<Module*>(mod)->setRevealedBy(vals[0]);
+        }
+        void setRevealedBy(const std::string& by);
+
+        inline const std::string& getName(){return m_name;}
+        void setName(const std::string& val);
+        inline virtual void setModuleName(const std::string& val){setName(val);}
+        inline const std::string& getType(){return m_type;}
+        inline void setDepth(const unsigned int& depth){m_depth=depth;}
+        inline const unsigned int& getDepth(){return m_depth;}
+        inline const std::string& getFullName(){return m_fullName;}
+
+        inline virtual void setVisible(bool vis){m_visible=vis;}
+        inline virtual void setParentVisible(bool pvis){m_parentVisible=pvis;}
+        inline bool isVisible(){return m_visible && m_parentVisible;}
+        void setVisibleFrom(const std::string& visibleFrom);
+        void setVisibleFromList(std::vector<std::string>& modVec);
+        virtual void getVisibleFromList(std::vector<std::string>& modVec, 
+                                        std::map<std::string, int>& modMap){}
+        inline const int& getVisibilityMask(){return m_visibilityMask;}
+        inline void  setVisibilityMask(int mask){m_visibilityMask=mask;}
+
+        virtual void listModulesAndAttributes(const std::string& parentName, 
+                                      std::map<std::string, Module*>& mods,
+                                      std::map<std::string, Attribute*>& atts);
+
+        inline void setParentMatrix(const glm::mat4& mat){m_parentMat=mat;} 
+        virtual void updateModelMatrix();
+
+        virtual void gotAttributeListenersUpdate(Attribute*){}
+
+        virtual void addNameAttribute();
+        virtual void addRemoveAttribute();
+        virtual void addTransformationAttributes();
+        virtual void addVisibleAttribute();
+        virtual void addVisibleFromAttribute();
+        virtual void addRevealedByAttribute();
+		virtual void addFollowMarkerAttribute();
+
+        inline void setUpID(const unsigned int& id){m_upID=id;}
+        inline const int& getUpID(){return m_upID;}
+        virtual void update(const int& timeDiffMs){}
+
+    protected:
+        void getQuatFromTwoVecs(glm::quat& q, glm::vec3& from, glm::vec3& to);
+
+    protected:
+        std::string m_name;
+        std::string m_fullName;
+        std::string m_type;
+        bool m_visible;
+        bool m_parentVisible;
+        int m_visibilityMask;
+        unsigned int m_depth;
+        GroupModule* m_parent;
+        unsigned int m_childID;
+        glm::mat4 m_transform;
+        std::map<std::string, Attribute*> m_attributesMap;
+        std::vector<Attribute*> m_attributesVec;
+        std::vector<std::string> m_revealedBys;
+        int m_revealedBy;
+        int m_upID;
+        glm::vec3 m_position;
+        glm::vec3 m_scale;
+        glm::quat m_rotQuat;
+        glm::vec3 m_rotEuler;
+        glm::mat4 m_rotMat;
+        glm::mat4 m_modelMat;
+        glm::mat4 m_invModelMat;
+        glm::mat4 m_parentMat;
+		glm::vec3 m_modelScale;
+        int m_texWidth;
+        int m_texHeight;
+
+		std::vector<MarkerListener> m_markerListeners;
+};
+
+class MarkerListener : public Listener {
+	public : 
+		MarkerListener(Module* mod);
+		virtual ~MarkerListener();
+        virtual void update(std::vector<float>& floatValues, 
+                            std::vector<int>& intValues,
+                            std::vector<bool>& boolValues,
+                            std::vector<std::string>& stringValues);
+		inline void setMarkerID(const int& m){m_markerID=m;}
+	private:
+		int m_markerID;
+		Module* m_mod;
+};
+
+
+#endif
diff --git a/src/modules/OutputManagerModule.cpp b/src/modules/OutputManagerModule.cpp
new file mode 100644
index 0000000..60fbd41
--- /dev/null
+++ b/src/modules/OutputManagerModule.cpp
@@ -0,0 +1,60 @@
+/***************************************************************************
+ *  OutputManagerModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "../Reveal.hpp"
+#include "OutputManagerModule.hpp"
+
+using namespace std;
+
+OutputManagerModule::OutputManagerModule():GroupModule() {
+    m_type="OutputManager";
+    m_name="outputs";
+    addAttribute(new Attribute("add_osc_output", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addOscOutputCallback, this, 1,
+                                Attribute::LOCAL));
+    m_attributesMap["add_osc_output"]->initStrings(vector<string>(1, "osc"));
+    addAttribute(new Attribute("add_pd_output", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addPdOutputCallback, this, 1,
+                                Attribute::LOCAL));
+    m_attributesMap["add_pd_output"]->initStrings(vector<string>(1, "patch"));
+}
+
+OutputManagerModule::~OutputManagerModule() {
+    
+}
+
+void OutputManagerModule::addOscOutput(const string& name) {
+    OutputOscModule *chi = new OutputOscModule();
+    addChild(chi);
+    chi->getAttribute("name")->setStrings(vector<string>(1,name));
+    Reveal::getInstance()->refreshModules();
+}
+
+void OutputManagerModule::addPdOutput(const string& name) {
+    OutputPdModule *chi = new OutputPdModule();
+    addChild(chi);
+    chi->getAttribute("name")->setStrings(vector<string>(1,name));
+    Reveal::getInstance()->refreshModules();
+}
+
diff --git a/src/modules/OutputManagerModule.hpp b/src/modules/OutputManagerModule.hpp
new file mode 100644
index 0000000..2bb7ed2
--- /dev/null
+++ b/src/modules/OutputManagerModule.hpp
@@ -0,0 +1,54 @@
+/***************************************************************************
+ *  OutputManagerModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef OutputManagerModule_h
+#define OutputManagerModule_h
+
+#include "GroupModule.hpp"
+
+#include "OutputOscModule.hpp"
+#include "OutputPdModule.hpp"
+
+class OutputManagerModule : public GroupModule {
+    public :
+        OutputManagerModule();
+        virtual ~OutputManagerModule();
+
+        static void addOscOutputCallback(Module* mod,
+                                         const std::vector<std::string>& vals) {
+            dynamic_cast<OutputManagerModule*>(mod)->addOscOutput(vals[0]);
+        }
+        void addOscOutput(const std::string&);
+        static void addPdOutputCallback(Module* mod,
+                                         const std::vector<std::string>& vals) {
+            dynamic_cast<OutputManagerModule*>(mod)->addPdOutput(vals[0]);
+        }
+        void addPdOutput(const std::string&);
+
+    private :
+
+
+};
+
+#endif
+
diff --git a/src/modules/OutputOscModule.cpp b/src/modules/OutputOscModule.cpp
new file mode 100644
index 0000000..819cdb0
--- /dev/null
+++ b/src/modules/OutputOscModule.cpp
@@ -0,0 +1,58 @@
+/***************************************************************************
+ *  OutputOscModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "OutputOscModule.hpp"
+#include <iostream>
+
+using namespace std;
+
+OutputOscModule::OutputOscModule(): Module() {
+    m_type="OutputOsc";
+    m_name="osc";
+    addNameAttribute();
+
+    //string attribute for ip adress
+    addAttribute(new Attribute("address",
+                                Attribute::STRING_ATTRIBUTE,
+                                addressCallback, this, 1, Attribute::LOCAL));
+    m_attributesMap["address"]->setStrings(vector<string>(1, "127.0.0.1"));
+
+    //int attribute for port
+    addAttribute(new Attribute("port",
+                                Attribute::INT_ATTRIBUTE,
+                                portCallback, this, 1, Attribute::LOCAL));
+    m_attributesMap["port"]->setInts(vector<int>(1, 7000));
+
+}
+
+OutputOscModule::~OutputOscModule() {
+
+}
+
+void OutputOscModule::setAddress(const string& add) {
+    m_address=add;
+}
+
+void OutputOscModule::setPort(const int& port) {
+    m_port=port;
+}
+
diff --git a/src/modules/OutputOscModule.hpp b/src/modules/OutputOscModule.hpp
new file mode 100644
index 0000000..247f01e
--- /dev/null
+++ b/src/modules/OutputOscModule.hpp
@@ -0,0 +1,53 @@
+/***************************************************************************
+ *  OutputOscModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef OutputOscModule_h
+#define OutputOscModule_h
+
+#include "Module.hpp"
+
+class OutputOscModule : public Module {
+    public :
+        OutputOscModule();
+        virtual ~OutputOscModule();
+
+        static void addressCallback(Module* mod,
+                                   const std::vector<std::string>& vals) {
+            dynamic_cast<OutputOscModule*>(mod)->setAddress(vals[0]);
+        }
+        void setAddress(const std::string& add);
+
+        static void portCallback(Module* mod,
+                                   const std::vector<int>& vals) {
+            dynamic_cast<OutputOscModule*>(mod)->setPort(vals[0]);
+        }
+        void setPort(const int& add);
+
+    private :
+        std::string m_address;
+        int m_port;
+
+};
+
+#endif
+
diff --git a/src/modules/OutputPdModule.cpp b/src/modules/OutputPdModule.cpp
new file mode 100644
index 0000000..3664601
--- /dev/null
+++ b/src/modules/OutputPdModule.cpp
@@ -0,0 +1,37 @@
+/***************************************************************************
+ *  OutputPdModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "OutputPdModule.hpp"
+
+using namespace std;
+
+OutputPdModule::OutputPdModule():Module() {
+    m_type="OutputPd";
+    m_name="pd";
+    addNameAttribute();
+
+    //add pd file attribute
+}
+
+OutputPdModule::~OutputPdModule() {
+
+}
diff --git a/src/modules/OutputPdModule.hpp b/src/modules/OutputPdModule.hpp
new file mode 100644
index 0000000..0957d5f
--- /dev/null
+++ b/src/modules/OutputPdModule.hpp
@@ -0,0 +1,39 @@
+/***************************************************************************
+ *  OutputPdModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef OutputPdModule_h
+#define OutputPdModule_h
+
+#include "Module.hpp"
+
+class OutputPdModule : public Module {
+    public :
+        OutputPdModule();
+        virtual ~OutputPdModule();
+
+    private :
+
+
+};
+
+#endif
diff --git a/src/modules/PreviewModule.cpp b/src/modules/PreviewModule.cpp
new file mode 100644
index 0000000..2335286
--- /dev/null
+++ b/src/modules/PreviewModule.cpp
@@ -0,0 +1,315 @@
+/***************************************************************************
+ *	PreviewModule.cpp
+ *	Part of PreviewModule
+ *	2015-  Florent Berthaut
+ *	hitmuri.net
+ ****************************************************************************/
+/*
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "PreviewModule.hpp" 
+
+#include <iostream>
+#include "../Reveal.hpp"
+#include "../geoms/BoxGeometry.hpp"
+#include "../geoms/SphereGeometry.hpp"
+#include <glm/gtc/matrix_transform.hpp>
+
+using namespace std;
+using namespace glm;
+
+PreviewModule::PreviewModule():Module() {
+	m_type="Preview";
+	m_name="preview";
+	m_active=true;
+
+	addAttribute(new Attribute("active", 
+								Attribute::BOOL_ATTRIBUTE,
+								activeCallback, this, 1, 
+								Attribute::LOCAL));
+	addAttribute(new Attribute("look_at", 
+								Attribute::FLOAT_ATTRIBUTE,
+								lookAtCallback, this, 3));
+	addAttribute(new Attribute("from", 
+								Attribute::FLOAT_ATTRIBUTE,
+								eyePositionCallback, this, 3));
+
+	m_attributesMap["active"]->initBools(vector<bool>(1, true));
+
+	//initialize matrices
+	vector<float> initPos(3,0);
+	m_attributesMap["look_at"]->setFloats(initPos);
+	initPos[2]=-700.0;
+	m_attributesMap["from"]->setFloats(initPos);
+	updateViewProjMatrix();
+
+	//create preview window
+	m_previewWindow = glfwCreateWindow(600, 480, "Revil - Preview", NULL, NULL);
+	if (!m_previewWindow) {
+		glfwTerminate();
+		exit(EXIT_FAILURE);
+	}
+	glfwPollEvents();
+	glfwSetWindowSize(m_previewWindow, 640, 480);
+
+	glfwSetWindowUserPointer(m_previewWindow, this);
+	glfwSetMouseButtonCallback(m_previewWindow, 
+							   (GLFWmousebuttonfun)previewMouseBtnCB);
+	glfwSetCursorPosCallback(m_previewWindow, 
+							 (GLFWcursorposfun)previewMousePosCB);
+	glfwSetScrollCallback(m_previewWindow, 
+							 (GLFWscrollfun)previewMouseScrollCB);
+
+	Reveal::getInstance()->addContextHandler(this);
+	
+	m_initialized=false;
+}
+
+PreviewModule::~PreviewModule() {}
+
+void PreviewModule::load(xmlNodePtr node) {
+	Module::load(node);
+}
+
+void PreviewModule::draw() {
+	//set context for window 
+	glfwMakeContextCurrent(m_previewWindow);
+
+	//initialize
+	if(!m_initialized) {
+		initGL();
+		m_initialized=true;
+	}
+
+	//clear window
+	int width, height;
+	glfwGetFramebufferSize(m_previewWindow, &width, &height);
+	glViewport(0, 0, width, height);
+	glClearColor(0.1, 0.1, 0.1, 1);
+	glEnable(GL_DEPTH_TEST);
+	glEnable(GL_CULL_FACE);
+	glCullFace(GL_BACK);
+	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+	
+	glEnable(GL_BLEND);
+	glBlendEquation(GL_FUNC_ADD);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	
+	//load preview shader 
+	glUseProgram(m_program);
+
+	//set view/projection uniforms 
+	glUniformMatrix4fv(m_uniforms[Reveal::VIEWPROJMAT], 1, 
+					   GL_FALSE, value_ptr(m_viewProjMat));
+
+	//draw all scene geometry and their connected shape/ modules 
+	const vector<Geometry*>& sceneGeoms = Reveal::getInstance()->getGeoms();
+	vector<Geometry*>::const_iterator itScGeom=sceneGeoms.begin();
+	for(; itScGeom!=sceneGeoms.end(); ++itScGeom) {
+		(*itScGeom)->draw(m_contextHandlerID, 
+						  Reveal::PREVIEWPROG, 
+						  m_uniforms, 
+						  1);
+	}
+
+
+	//for each space from reveal
+		//draw all projectors and depth cameras
+
+
+	glfwSwapBuffers(m_previewWindow);
+}
+
+void PreviewModule::mouseBtnCB(const int& btn, const int& action, 
+							   const int& mods) {
+	switch(action) {
+		case GLFW_PRESS : {
+			m_mouseStartPosX = m_mousePosX;
+			m_mouseStartPosY = m_mousePosY;
+			switch(btn) {
+				case 0: {
+					m_control=MOVING;
+				}break;
+				case 1: {
+					m_control=ORBITING;
+				}break;
+				case 2: {
+					m_control=TURNING;
+				}break;
+			}
+		}break;
+		case GLFW_RELEASE: {
+			m_control=NONE;
+		}break;
+		default:break;
+	}
+}
+
+void PreviewModule::mousePosCB(const double& x, const double& y) {
+	m_mousePosX=x;
+	m_mousePosY=y;
+	//FIXME recompute lookAt based on eye pos and vector
+	switch(m_control) {
+		case TURNING : {
+			
+		} break;
+		case MOVING : {
+			float diffX = (m_mousePosX-m_mouseStartPosX)/1;
+			float diffY = (m_mousePosY-m_mouseStartPosY)/1;
+			setEyePosition(m_eyePos[0]+diffX, m_eyePos[1]+diffY, m_eyePos[2]);
+			setLookAt(m_lookAt[0]+diffX, m_lookAt[1]+diffY, m_lookAt[2]);
+			m_mouseStartPosX=m_mousePosX;
+			m_mouseStartPosY=m_mousePosY;
+		} break;
+		case ORBITING : {
+
+		} break;
+		default:break;
+	}
+}
+
+void PreviewModule::mouseScrollCB(const double& x, const double& y) {
+
+}
+
+void PreviewModule::initGL() {
+	#ifdef OSX
+		glewExperimental = GL_TRUE; 
+	#endif
+	if(glewInit()!=GLEW_OK) {
+		cout<<"Could not initialize glew for Preview Window"<<endl;
+	}
+
+	const GLubyte* renderer = glGetString (GL_RENDERER); 
+	const GLubyte* version = glGetString (GL_VERSION);
+	cout<<"Renderer: "<<renderer<<endl;
+	cout<<"OpenGL version supported "<<version<<endl;
+
+
+
+	//create preview program
+	const char * vertSource = {
+	#ifdef GL42
+	"#version 430 \n"
+	#else 
+	"#version 410 \n"
+	#endif
+	"\n"
+	"in vec3 vertex;\n"
+	"in vec2 texCoords;\n"
+	"\n"
+	"uniform mat4 modelMat;\n"
+	"uniform mat4 viewProjMat;\n"
+	"\n"
+	"out vec2 uvCoords;\n"
+	"out float light;\n"
+	"\n"
+	"void main(void) {\n"
+	"	gl_Position = viewProjMat*modelMat*vec4(vertex, 1.0);\n"
+	"	light = distance(\n"
+	"				vec3(0,0,0),\n"
+	"				vec3(modelMat[3][0], modelMat[3][1], modelMat[3][2]));\n"
+	"	uvCoords=texCoords;\n"
+	"}\n"};
+	const char * fragSource = {
+#ifdef GL42
+	"#version 430 \n"
+#else 
+	"#version 410 \n"
+#endif
+	"\n"
+	"in vec2 uvCoords;\n"
+	"in float light;\n"
+	"\n"
+	"uniform vec3 shapeColor;\n"
+#ifdef GL42
+	"layout(binding=3) uniform sampler2D surfaceTex;\n"
+#else
+	"uniform sampler2D surfaceTex;\n"
+#endif
+	"\n"
+	"out vec4 color;\n"
+	"\n"
+	"void main(void) {\n"
+	"	float pixZ=pow(gl_FragCoord.z,3);\n"
+	//"   float pixZ=light;\n"
+	"	color = vec4(shapeColor.x*pixZ, shapeColor.y*pixZ,\n"
+	"				 shapeColor.z*pixZ, 1);\n"
+	//"   color = vec4(uvCoords,0,1);\n"
+	"}\n"};
+	m_program = Reveal::getInstance()->createProgram(vertSource, fragSource);
+	m_uniforms[Reveal::VIEWPROJMAT]
+		= glGetUniformLocation(m_program, "viewProjMat");
+	m_uniforms[Reveal::MODELMAT]
+		= glGetUniformLocation(m_program, "modelMat");
+	m_uniforms[Reveal::SHAPECOLOR]
+		= glGetUniformLocation(m_program, "shapeColor");
+	m_uniforms[Reveal::SURFACETEX]
+		= glGetUniformLocation(m_program, "surfaceTex");
+}
+
+void PreviewModule::setEyePosition(const float& x, 
+								   const float& y, 
+								   const float& z) {
+	m_eyePos = vec3(x, y, z);
+	updateViewProjMatrix();
+}
+
+void PreviewModule::setLookAt(const float& x, 
+							  const float& y,
+							  const float& z) {
+	m_lookAt = vec3(x, y, z);
+	updateViewProjMatrix();
+}
+
+
+void PreviewModule::updateViewProjMatrix() {
+	m_viewMat = lookAt(m_eyePos, 
+					   m_lookAt, 
+					   vec3(0.0, 1.0, 0.0));
+	m_projMat = perspective(45.0, 4.0/3.0, 100.0, 10000.0);
+	m_viewProjMat = m_projMat*m_viewMat;
+}
+
+/*
+	float width = m_screenDim.x();
+	float height = m_screenDim.y();
+	float dl=width/2.0+m_eyePos.x();
+	float db=m_eyePos.y();
+	float f=-m_near/(fabs(m_eyePos.z())+1);
+	Reveal::getInstance()->getPreviewCamera()
+				->setProjectionMatrixAsFrustum((width-dl)*f,-dl*f,	
+											   (height-db)*f, -db*f, 
+											   m_near, m_far);
+	Matrixf rotMat = Matrixf::rotate(m_screenRot[0], Vec3f(1, 0, 0), 
+									 m_screenRot[1], Vec3f(0, 1, 0), 
+									 m_screenRot[2], Vec3f(0, 0, 1));
+	Vec3f eyeToWPos = m_screenPos + m_eyePos*rotMat;
+	Vec3f lookAt = m_screenPos+(m_eyePos+Vec3f(0, 0, 1))*rotMat;
+	Matrixf viewMat;
+	viewMat.makeLookAt(eyeToWPos,
+					   lookAt,
+					   Vec3f(0,1,0));
+	osg::Matrixf glCoordsMat(1, 0, 0, 0, 
+							  0, 1, 0, 0,
+							  0, 0, 1, 0,
+							  0, 0, 0, 1);
+	viewMat=viewMat*glCoordsMat;
+	Reveal::getInstance()->getPreviewCamera()->setViewMatrix(viewMat);
+}
+*/
+
diff --git a/src/modules/PreviewModule.hpp b/src/modules/PreviewModule.hpp
new file mode 100644
index 0000000..3c41648
--- /dev/null
+++ b/src/modules/PreviewModule.hpp
@@ -0,0 +1,108 @@
+/***************************************************************************
+ *  PreviewModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef PreviewModule_h
+#define PreviewModule_h
+
+#include "Module.hpp"
+#include "../Reveal.hpp"
+
+class Geometry;
+
+class PreviewModule: public Module, public ContextHandler {
+    public:
+        PreviewModule();
+        virtual ~PreviewModule();
+        virtual void draw();
+
+        virtual void load(xmlNodePtr node);
+
+        static void previewMouseBtnCB(GLFWwindow* win, int btn, 
+                                   int action, int mods) {
+            static_cast<PreviewModule*>(glfwGetWindowUserPointer(win))
+                ->mouseBtnCB(btn, action, mods);
+        }
+        void mouseBtnCB(const int& btn, const int& action, const int& mods);
+
+        static void previewMousePosCB(GLFWwindow* win, int btn, 
+                                      double x, double y) {
+            static_cast<PreviewModule*>(glfwGetWindowUserPointer(win))
+                ->mousePosCB(x, y);
+        }
+        void mousePosCB(const double& x, const double& y);
+
+        static void previewMouseScrollCB(GLFWwindow* win, int btn, 
+                                      double x, double y) {
+            static_cast<PreviewModule*>(glfwGetWindowUserPointer(win))
+                ->mouseScrollCB(x, y);
+        }
+        void mouseScrollCB(const double& x, const double& y);
+
+        static void activeCallback(Module* mod, 
+                                           const std::vector<bool>& vals) {
+            static_cast<PreviewModule*>(mod)->setActive(vals[0]);
+        }
+        inline void setActive(bool active) {m_active=active;}
+        static void eyePositionCallback(Module* mod, 
+                                        const std::vector<float>& vals) {
+            static_cast<PreviewModule*>(mod)->setEyePosition(vals[0], 
+                                                             vals[1],
+                                                             vals[2]);
+        }
+        static void lookAtCallback(Module* mod, 
+                                   const std::vector<float>& vals) {
+            static_cast<PreviewModule*>(mod)->setLookAt(vals[0],
+                                                        vals[1],
+                                                        vals[2]);
+        }
+
+        void setEyePosition(const float& x, const float& y, const float& z);
+        void setLookAt(const float& x, const float& y, const float& z);
+        void updateViewProjMatrix();
+        inline GLFWwindow* getWindow(){return m_previewWindow;}
+
+    private:
+        void initGL();
+
+    protected:
+        bool m_active;
+        GLFWwindow* m_previewWindow;
+        glm::vec3 m_eyePos;
+        glm::vec3 m_lookAt;
+        float m_near;
+        float m_far;
+        glm::mat4 m_viewMat;
+        glm::mat4 m_projMat;
+        glm::mat4 m_viewProjMat;
+        GLint m_viewProjUniform;
+        bool m_initialized;
+        GLint m_program;
+        std::map<Reveal::REVIL_UNIFORM, GLint> m_uniforms;
+        std::vector<Geometry*> m_geometries;
+        enum {NONE, TURNING, ORBITING, MOVING} m_control;
+        float m_mousePosX, m_mousePosY;
+        float m_mouseStartPosX, m_mouseStartPosY;
+};
+
+#endif
+
diff --git a/src/modules/ProjectorModule.cpp b/src/modules/ProjectorModule.cpp
new file mode 100644
index 0000000..d337fd0
--- /dev/null
+++ b/src/modules/ProjectorModule.cpp
@@ -0,0 +1,2419 @@
+/***************************************************************************
+ *  ProjectorModule.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 130, Boston, MA 02111-1307, USA.
+ */
+
+/*////////////
+Calibration heavily relies on code from :
+https://github.com/Kj1/ofxProjectorKinectCalibration
+https://github.com/kylemcdonald/ofxCv
+*/////////////////////
+
+#include "ProjectorModule.hpp"
+
+#include <iostream>
+
+#include "opencv2/highgui/highgui.hpp"
+#include "opencv2/imgproc/imgproc.hpp"
+#include "opencv2/calib3d/calib3d.hpp"
+
+#include "../Reveal.hpp"
+#include "DepthCamModule.hpp"
+#include "SpaceModule.hpp"
+#include "RevealedModule.hpp"
+
+
+using namespace std;
+using namespace glm;
+using namespace cv;
+
+ProjectorModule::ProjectorModule(): Module() {
+    m_type="Projector";
+    m_name="projector";
+
+    m_space=NULL;
+    m_width=640;
+    m_height=480;
+    m_posX=0;
+    m_posY=0;
+    m_processOutput=true;
+    m_active=true;
+    m_postFilter=0;
+	m_transparentBackground=false;
+
+    //create window
+    m_projWindow = glfwCreateWindow(m_width, m_height,
+                                    "Revil - Projector", NULL, NULL);
+    if(!m_projWindow) {
+        glfwTerminate();
+        exit(EXIT_FAILURE);
+    }
+    m_rttWidth=1920;
+    m_rttHeight=1080;
+    glfwSetWindowUserPointer(m_projWindow, this);
+    glfwSetWindowSizeCallback(m_projWindow, windowSizeCallback);
+    glfwSetWindowPosCallback(m_projWindow, windowPositionCallback);
+    glfwSetFramebufferSizeCallback(m_projWindow, framebufferSizeCallback);
+	glfwSetInputMode(m_projWindow, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
+    addNameAttribute();
+    addRemoveAttribute();
+    addAttribute(new Attribute("active",
+                                Attribute::BOOL_ATTRIBUTE,
+                                activeCallback, this, 1,
+                                Attribute::LOCAL));
+    addAttribute(new Attribute("window_dimensions",
+                                Attribute::INT_ATTRIBUTE,
+                                windowDimensionsCallback, this, 4,
+                                Attribute::LOCAL));
+    addAttribute(new Attribute("fullscreen_monitor",
+                                Attribute::STRING_ATTRIBUTE,
+                                fullscreenMonitorCallback, this, 1,
+                                Attribute::LOCAL));
+    addAttribute(new Attribute("view_matrix",
+                                Attribute::FLOAT_ATTRIBUTE,
+                                viewMatrixCallback, this, 16,
+                                Attribute::HIDDEN));
+    addAttribute(new Attribute("projection_matrix",
+                                Attribute::FLOAT_ATTRIBUTE,
+                                projectionMatrixCallback, this, 16,
+                                Attribute::HIDDEN));
+
+    addAttribute(new Attribute("mirrored",
+                                Attribute::BOOL_ATTRIBUTE,
+                                mirroredCallback, this, 1,
+                                Attribute::LOCAL));
+
+    addTransformationAttributes();
+    m_attributesMap["scale"]->setAccessibility(Attribute::HIDDEN);
+    vector<float> posVec(3,0);
+    posVec[2]=-700;
+    m_attributesMap["position"]->setFloats(posVec);
+
+    addAttribute(new Attribute("attached_to_camera",
+                                Attribute::STRING_ATTRIBUTE,
+                                attachToCamCallback, this, 1,
+                                Attribute::LOCAL));
+    addAttribute(new Attribute("calibrate_with_camera",
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                calibrateCallback, this, 1,
+                                Attribute::LOCAL,
+                                false));
+    addAttribute(new Attribute("output_revealed",
+                                Attribute::BOOL_ATTRIBUTE,
+                                outputRevealedCallback, this, 1,
+                                Attribute::LOCAL));
+    addAttribute(new Attribute("post_filter",
+                                Attribute::INT_ATTRIBUTE,
+                                postFilterCallback, this, 1,
+                                Attribute::LOCAL));
+    addAttribute(new Attribute("transparent_window",
+                                Attribute::BOOL_ATTRIBUTE,
+                                transparentWindowCallback, this, 1,
+                                Attribute::LOCAL));
+
+    //initialize attributes
+    vector<string> labels;
+    labels.push_back("none");
+    m_attributesMap["attached_to_camera"]
+            ->editStringValuesChoices().assign(1, labels);
+    m_attributesMap["attached_to_camera"]
+            ->initStrings(vector<string>(1, labels[0]));
+    m_attributesMap["calibrate_with_camera"]
+            ->editStringValuesChoices().assign(1, labels);
+    m_attributesMap["calibrate_with_camera"]
+            ->initStrings(vector<string>(1, labels[0]));
+    refreshMonitors();
+    m_attributesMap["fullscreen_monitor"]
+            ->initStrings(vector<string>(1, "windowed"));
+    m_attachedToCam=NULL;
+    m_attributesMap["output_revealed"]->initBools(vector<bool>(1, true));
+    m_attributesMap["post_filter"]->initInts(vector<int>(1, 0));
+    m_attributesMap["active"]->initBools(vector<bool>(1, true));
+
+    m_mirrored=false;
+
+    //initialize matrices
+    m_viewMat = lookAt(vec3(0.0, 0.0, 0.0),
+                       vec3(0.0, 0.0, 1.0),
+                       vec3(0.0, 1.0, 0.0));
+    mat4 glCoordsMat(-1, 0, 0, 0,
+                      0, 1, 0, 0,
+                      0, 0, 1, 0,
+                      0, 0, 0, 1);
+    m_viewMat=glCoordsMat*m_viewMat;
+    m_attributesMap["view_matrix"]->setFloats(vector<float>(
+                                                      value_ptr(m_viewMat),
+                                                      value_ptr(m_viewMat)+16));
+    m_projMat = perspective(45.0, 4.0/3.0, 100.0, 10000.0);
+    m_attributesMap["projection_matrix"]->setFloats(vector<float>(
+                                                      value_ptr(m_projMat),
+                                                      value_ptr(m_projMat)+16));
+
+    vector<int> dims(4,0);
+    dims[0]=m_posX;
+    dims[1]=m_posY;
+    dims[2]=m_width;
+    dims[3]=m_height;
+    m_attributesMap["window_dimensions"]->setInts(dims);
+
+    //calibration
+    m_calibrated=false;
+    m_patternSquareWidth = 40;
+    m_patternPosition = Size(100, 200);
+    m_patternSize = Size(6,4);
+    m_patternBrightness = 100;
+    m_patternPosRange = Size(m_width, m_height);
+    m_patternPosOffset = Size(0,0);
+
+    Reveal::getInstance()->addContextHandler(this);
+
+    m_initialized=false;
+}
+
+ProjectorModule::~ProjectorModule() {}
+
+void ProjectorModule::draw() {
+    if(!m_active) {
+        return;
+    }
+
+    glfwMakeContextCurrent(m_projWindow);
+
+    if(!m_initialized) {
+        initGL();
+        m_initialized=true;
+    }
+
+    //slice to texture
+    glBindFramebuffer(GL_FRAMEBUFFER, m_sliceFBO);
+    glViewport(0, 0, m_rttWidth, m_rttHeight);
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_LESS);
+    glDisable(GL_CULL_FACE);
+    glDisable(GL_BLEND);
+    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glUseProgram(m_programs[Reveal::SLICEPROG]);
+    glUniform1f(m_uniforms[Reveal::SLICEPROG][Reveal::MIRRORED],
+                float(m_mirrored));
+    glUniformMatrix4fv(m_uniforms[Reveal::SLICEPROG][Reveal::VIEWPROJMAT], 1,
+                       GL_FALSE, value_ptr(m_viewProjMat));
+    glUniformMatrix4fv(m_uniforms[Reveal::SLICEPROG][Reveal::VIEWMAT], 1,
+                       GL_FALSE, value_ptr(m_transViewMat));
+    const vector<Geometry*>& depthGeoms = m_space->getGeoms();
+    vector<Geometry*>::const_iterator itDGeom=depthGeoms.begin();
+    for(; itDGeom!=depthGeoms.end(); ++itDGeom) {
+        (*itDGeom)->draw(m_contextHandlerID,
+                         Reveal::SLICEPROG,
+                         m_uniforms[Reveal::SLICEPROG],
+                         m_visibilityMask);
+    }
+
+	//select to texture for 3D models only (GEOM_MODEL)
+    glBindFramebuffer(GL_FRAMEBUFFER, m_selectFBO);
+    glViewport(0, 0, m_rttWidth, m_rttHeight);
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_ALWAYS);
+    glDisable(GL_CULL_FACE);
+    glEnable(GL_BLEND);
+    glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
+    glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
+    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glUseProgram(m_programs[Reveal::SELECTPROG]);
+    glUniform1f(m_uniforms[Reveal::SELECTPROG][Reveal::MIRRORED],
+                float(m_mirrored));
+    glUniformMatrix4fv(m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPROJMAT], 1,
+                       GL_FALSE, value_ptr(m_viewProjMat));
+    glUniformMatrix4fv(m_uniforms[Reveal::SELECTPROG][Reveal::VIEWMAT], 1,
+                       GL_FALSE, value_ptr(m_transViewMat));
+    glUniform1f(m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPORTWIDTH],
+                m_rttWidth);
+    glUniform1f(m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPORTHEIGHT],
+                m_rttHeight);
+    glUniform1i(m_uniforms[Reveal::SELECTPROG][Reveal::SLICETEX], 0);
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, m_sliceRttTex);
+    const vector<Geometry*>& sceneGeoms = Reveal::getInstance()->getGeoms();
+    for(auto& geom : sceneGeoms) {
+		if(geom->getGeomID()>=Reveal::GEOM_MODEL) {
+			geom->draw(m_contextHandlerID,
+					   Reveal::SELECTPROG,
+					   m_uniforms[Reveal::SELECTPROG],
+					   m_visibilityMask);
+		}
+    }
+
+
+    //RENDER TO SCREEN
+    if(m_postFilter>0) {
+        glBindFramebuffer(GL_FRAMEBUFFER, m_renderFBO);
+        glViewport(0, 0, m_rttWidth, m_rttHeight);
+    }
+    else {
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glViewport(0, 0, m_width, m_height);
+    }
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_ALWAYS);
+    glEnable(GL_CULL_FACE);
+	if(m_mirrored) {
+        glCullFace(GL_FRONT);
+    }
+    else {
+        glCullFace(GL_BACK);
+    }
+    glEnable(GL_BLEND);
+    glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
+    glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
+    glClearColor(0.0, 0.0, 0.0, !m_transparentBackground);
+    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+    glUseProgram(m_programs[Reveal::RENDERPROG]);
+    glUniform1f(m_uniforms[Reveal::RENDERPROG][Reveal::MIRRORED],
+                float(m_mirrored));
+    glUniformMatrix4fv(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPROJMAT], 1,
+                       GL_FALSE, value_ptr(m_viewProjMat));
+    glUniformMatrix4fv(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWMAT], 1,
+            GL_FALSE, value_ptr(m_transViewMat));
+    if(m_postFilter>0) {
+        glUniform1f(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTWIDTH],
+                    m_rttWidth);
+        glUniform1f(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTHEIGHT],
+                    m_rttHeight);
+    }
+    else {
+        glUniform1f(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTWIDTH],
+                    m_width);
+        glUniform1f(m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTHEIGHT],
+                    m_height);
+    }
+    glActiveTexture(GL_TEXTURE0);
+    glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::SLICETEX], 0);
+    glBindTexture(GL_TEXTURE_2D, m_sliceRttTex);
+    glActiveTexture(GL_TEXTURE1);
+    glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::SELECTTEX], 1);
+    glBindTexture(GL_TEXTURE_2D, m_selectTex);
+#ifdef GL42
+    glActiveTexture(GL_TEXTURE7);
+    glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::OUTPUTTEX], 7);
+    glBindImageTexture(7, m_outputTex, 0, GL_FALSE, 0,
+                       GL_READ_WRITE, GL_R32UI);
+    glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::OUTSHAPESIZE], 
+                m_outShapeSize);
+    glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::OUTDEPTHSIZE], 
+                m_outDepthSize);
+    glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::OUTNBDEPTH], 
+                m_outNbDepth);
+#endif
+    for(auto& geom : sceneGeoms) {
+        geom->draw(m_contextHandlerID,
+				   Reveal::RENDERPROG,
+				   m_uniforms[Reveal::RENDERPROG],
+				   m_visibilityMask);
+    }
+
+    //POST PROCESSING
+    if(m_postFilter>0) {
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glViewport(0, 0, m_width, m_height);
+        glEnable(GL_CULL_FACE);
+        glCullFace(GL_BACK);
+        glDisable(GL_BLEND);
+        glClearColor(0.0, 0.0, 0.0, !m_transparentBackground);
+        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+        glUseProgram(m_programs[Reveal::POSTPROG]);
+        glActiveTexture(GL_TEXTURE0);
+        glUniform1i(m_uniforms[Reveal::POSTPROG][Reveal::RENDERTEX], 0);
+        glBindTexture(GL_TEXTURE_2D, m_renderTex);
+        glUniform1f(m_uniforms[Reveal::POSTPROG][Reveal::VIEWPORTWIDTH],
+                    m_width);
+        glUniform1f(m_uniforms[Reveal::POSTPROG][Reveal::VIEWPORTHEIGHT],
+                    m_height);
+        glUniform1f(m_uniforms[Reveal::POSTPROG][Reveal::POSTFILTER],
+                    m_postFilter);
+        m_calibGeom->drawDirect(m_contextHandlerID);
+    }
+
+    //SWAP
+    glfwSwapInterval(0);
+    glfwSwapBuffers(m_projWindow);
+
+    //PROCESS OUTPUT
+#ifdef GL42
+    if(m_processOutput) {
+        processOutput();
+    }
+#endif
+}
+
+void ProjectorModule::initGL() {
+    #ifdef OSX
+        glewExperimental = GL_TRUE;
+    #endif
+    glewInit();
+
+
+    //POSTPROCESSING
+    {
+    const char * vertSource = {
+#ifdef GL42
+    "#version 430 \n"
+#else
+    "#version 410 \n"
+#endif
+    " \n"
+    "in vec3 vertex; \n"
+    " \n"
+    "void main(void) {\n"
+    "   gl_Position = vec4(vertex, 1.0);\n"
+    "}\n"};
+
+    const char * fragSource = {
+#ifdef GL42
+    "#version 430 \n"
+#else
+    "#version 410 \n"
+#endif
+    " \n"
+    "uniform float viewportWidth;\n"
+    "uniform float viewportHeight;\n"
+    "uniform float postFilter;\n"
+#ifdef GL42
+    "layout(binding=0) uniform sampler2D renderTex;\n"
+#else
+    "uniform sampler2D renderTex;\n"
+#endif
+    " \n"
+    "out vec4 color;\n"
+    " \n"
+    "void main(void) {\n"
+    "   float coordX = gl_FragCoord.x;\n"
+    "   float coordY = gl_FragCoord.y;\n"
+    "   ivec2 patSize = textureSize(renderTex, 0);\n"
+    "   vec3 sumCol = vec3(0,0,0);\n"
+    "   float cnt=0;\n"
+    "   for(float dX = coordX-postFilter; dX <= coordX+postFilter; ++dX) {\n"
+    "       for(float dY = coordY-postFilter; dY <= coordY+postFilter; ++dY) {\n"
+    "           if(dX>=0 && dX<viewportWidth \n"
+    "                   && dY>=0 && dY<viewportHeight) {\n"
+    "               sumCol+=texelFetch(renderTex, \n"
+    "                                  ivec2((dX-0.5)/viewportWidth*patSize.x,\n"
+    "                                     (dY-0.5)/viewportHeight*patSize.y),\n"
+    "                                  0).xyz; \n"
+    "               cnt+=1;\n"
+    "           }\n"
+    "       }\n"
+    "   }\n"
+    "   color=vec4(sumCol.xyz/cnt, 1.0);\n"
+    "}\n"};
+    m_programs[Reveal::POSTPROG]
+        = Reveal::getInstance()->createProgram(vertSource, fragSource);
+    m_uniforms[Reveal::POSTPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
+    m_uniforms[Reveal::POSTPROG][Reveal::VIEWPORTWIDTH]
+        = glGetUniformLocation(m_programs[Reveal::POSTPROG],"viewportWidth");
+    m_uniforms[Reveal::POSTPROG][Reveal::VIEWPORTHEIGHT]
+        = glGetUniformLocation(m_programs[Reveal::POSTPROG],"viewportHeight");
+    m_uniforms[Reveal::POSTPROG][Reveal::POSTFILTER]
+        = glGetUniformLocation(m_programs[Reveal::POSTPROG],"postFilter");
+    m_uniforms[Reveal::POSTPROG][Reveal::RENDERTEX]
+        = glGetUniformLocation(m_programs[Reveal::POSTPROG],"renderTex");
+    }
+
+
+
+    //RENDER
+    {
+    const char * vertSource = {
+    #ifdef GL42
+    "#version 430 \n"
+    #else
+    "#version 410 \n"
+    #endif
+    " \n"
+    "in vec3 vertex; \n"
+    "in vec2 texCoords;\n"
+    " \n"
+    "uniform mat4 modelMat;\n"
+    "uniform mat4 viewMat;\n"
+    "uniform mat4 viewProjMat;\n"
+    "uniform float mirrored;\n"
+    " \n"
+    "out vec3 viewRay;\n"
+    "out vec2 uvCoords;\n"
+    " \n"
+    "void main(void) {\n"
+    "   vec4 posWS = modelMat * vec4(vertex, 1.0);\n"
+    "   if(mirrored<1) {\n"
+    "       posWS.x = -posWS.x;\n"
+    "   }\n"
+    "   gl_Position = viewProjMat * posWS;\n"
+    "   viewRay = posWS.xyz - vec3(viewMat[3][0],\n"
+    "                              viewMat[3][1],\n"
+    "                              viewMat[3][2]);\n"
+    "   uvCoords=texCoords;\n"
+    "}\n"};
+
+    const char * fragSource = {
+#ifdef GL42
+    "#version 430 \n"
+#else
+    "#version 410 \n"
+#endif
+    "\n"//defined in Reveal.hpp
+	"const int BOX=0;\n"
+	"const int SPHERE=1;\n"
+	"const int TUBE=2;\n"
+	"const int CONE=3;\n"
+	"const int FRAME=4;\n"
+	"const int PATH=5;\n"
+	"const int MODEL=10;\n"
+	"\n"
+    "in vec3 viewRay;\n"
+    "in vec2 uvCoords;\n"
+    " \n"
+#ifdef GL42
+    "layout(binding=0) uniform sampler2D sliceTex;\n"
+    "layout(binding=1) uniform sampler2D selectTex;\n"
+    "layout(binding=2) uniform sampler3D insideTex;\n"
+    "layout(binding=3) uniform sampler2D surfaceTex;\n"
+    "layout(binding=4) uniform sampler3D reactTex;\n"
+    "layout(binding=5) uniform sampler3D surfDistTex;\n"
+    "layout(binding=6) uniform sampler2D gradientTex;\n"
+    "layout(r32ui, binding=7) uniform coherent uimage2D outputTex;\n"
+#else
+    "uniform sampler2D sliceTex;\n"
+    "uniform sampler2D selectTex;\n"
+    "uniform sampler3D insideTex;\n"
+    "uniform sampler2D surfaceTex;\n"
+    "uniform sampler3D reactTex;\n"
+    "uniform sampler3D surfDistTex;\n"
+    "uniform sampler2D gradientTex;\n"
+#endif
+    "uniform float viewportWidth;\n"
+    "uniform float viewportHeight;\n"
+    "uniform float mirrored;\n"
+    "uniform float shapeID;\n"
+    "uniform float shapeIDBit;\n"
+	"uniform int shapeGeom;\n"
+    "uniform float subShapeID;\n"
+    "uniform float subShapesNb;\n"
+    "uniform mat4 subShapeInvMat;\n"
+    "uniform mat4 viewMat;\n"
+    "uniform mat4 modelMat;\n"
+    "uniform mat4 invModelMat;\n"
+    "uniform vec3 modelScale;\n"
+    "uniform int revealedBy;\n"
+	"\n"
+    "uniform vec3 shapeColor;\n"
+    //0: none, 1:color, 2:texture
+    "uniform int surface;\n"
+    "uniform vec3 surfaceColor;\n"
+	"uniform int insideOutputOnly;\n"
+	"uniform int reactivity;\n"
+    "uniform float thickness;\n"
+	"\n"
+    "uniform int insideVisible;\n"
+    //0:from center, 1:along x, 2: along y, 3:along z, 4 :from surface
+    "uniform int insideStructure;\n"
+    "uniform float structureRatio;\n"
+	"\n"
+    "uniform float gradientAlpha;\n"
+    //0:greyscale, 1:texture
+    "uniform int gradientType;\n"
+    "uniform int gradientSteps;\n"
+    "uniform float gradientCurveRatio;\n"
+	"\n"
+    "uniform float densityAlpha;\n"
+    //0:layers, 1:grid, 2:pointcloud
+    "uniform int densityType;\n"
+    "uniform float densityRatio;\n"
+    "uniform float densitySize;\n"
+    "uniform float densityCurveRatio;\n"
+	"\n"
+    "uniform float texAlpha;\n"
+    "uniform vec3 texOffset;\n"
+    "uniform vec3 texScale;\n"
+    "uniform int texGray;\n"
+#ifdef GL42
+    "uniform int revSize;\n"
+    "uniform int revSurface;\n"
+    "uniform int revInside;\n"
+    "uniform int revCenter;\n"
+    "uniform int revCursor;\n"
+    "uniform int revColor;\n"
+    "uniform int revHisto;\n"
+    "uniform int revVoxels;\n"
+    "uniform float revSubShapeID;\n"
+    "uniform int shapeOutSize;\n"
+    "uniform int histoOutSize;\n"
+    "uniform int voxelOutSize;\n"
+    "uniform int depthOutSize;\n"
+    "uniform int depthOutNb;\n"
+	"uniform vec4 boundingRect;\n"
+#endif
+    " \n"
+    "vec3 rgb2hsv(vec3 c) {\n"
+    "	vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"
+    "	vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n"
+    "	vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"
+	"	float d = q.x - min(q.w, q.y);\n"
+    "	float e = 1.0e-10;\n"
+    "	return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),d/(q.x + e), q.x);\n"
+	"}\n"
+
+	"float random (vec3 st) {\n"
+    "	return fract(sin(dot(st.xyz,\n"
+    "                     vec3(12.9898,78.233, 102.234)))*\n"
+    "    43758.5453123);\n"
+	"}\n"
+
+	"out vec4 color;\n"
+    " \n"
+    "void main(void) {\n"
+		//get fragment coordinates
+    "   float coordX = (gl_FragCoord.x-0.5)/viewportWidth;\n"
+    "   float coordY = (gl_FragCoord.y-0.5)/viewportHeight;\n"
+    "   ivec2 sliSize = textureSize(sliceTex, 0);\n"
+		//retrieve pixel in slicing texture
+    "   vec4 sli = texelFetch(sliceTex,\n"
+    "                         ivec2(coordX*float(sliSize.x), \n"
+    "                               coordY*float(sliSize.y)), \n"
+    "                         0);\n"
+    "   float pixZ=abs(gl_FragCoord.z);\n"
+    "   float cutZ=abs(sli.z);\n"
+    "   int depthID=int(sli.y)-1;\n"
+#ifdef GL42
+    "   int outCols=imageSize(outputTex).x;\n"
+	"   int outOffset=(int(shapeID-1)*depthOutNb+(depthID-1))*revSize;\n"
+#endif
+    "   int rendered=0;\n"
+    "   vec3 finalColor = shapeColor;\n"
+    "   float alpha=0;\n"
+	"	vec3 pixelPosW;\n"
+	"	vec3 pixelPos = vec3(0.0, 0.0, 1.0);\n"
+	"	vec3 ratioWithinBox = vec3(0.0, 0.0, 0.0);\n"
+	"	vec3 outRatioWithinBox = vec3(0.0, 0.0, 0.0);\n"
+		//if there is a slicing pixel aligned with our coordinate
+		//and we are revealed by this depth module
+	"	if(cutZ>0 && (revealedBy & (1<<(1+depthID)))>0 ) { \n"
+			//compute the slicing pixel world position
+    "   	pixelPosW = vec3(viewMat[3][0], \n"
+	"                       viewMat[3][1], \n"
+    "                       viewMat[3][2])\n"
+    "                  + vec3(normalize(viewRay) * sli.w);\n"
+    "       pixelPosW.x = pixelPosW.x*(-2.0*(1-mirrored)+1.0);\n"
+			//compute the slicing pixel position in model coords
+	"		pixelPos = (invModelMat * vec4(pixelPosW,1.0)).xyz;\n"
+	"\n"
+			//depending on type, test if slicing pixel inside 
+			//and retrieve distance to the surface on each axis
+	"		vec3 diffMin = vec3(1.0);\n" 
+	"		vec3 diffMax = vec3(1.0);\n"
+	"		switch(shapeGeom) {\n"
+	"			case PATH : {\n"//use min/max/size of current segment
+	"				pixelPos = (subShapeInvMat*vec4(pixelPos,1.0)).xyz;\n"
+	"				if(length(vec2(pixelPos.x, pixelPos.y))<=0.5\n"
+	"						&& (pixelPos.z>-0.5 && pixelPos.z<0.5)) { \n"
+	"					float xx = (pixelPos.x)*(pixelPos.x);\n"
+	"					float yy = (pixelPos.y)*(pixelPos.y);\n"
+	"					float ax = sqrt(0.25-yy);\n"
+	"					diffMin.x = pixelPos.x+ax;\n"
+	"					diffMax.x = ax-pixelPos.x;\n"
+	"					float ay = sqrt(0.25-xx);\n"
+	"					diffMin.y = pixelPos.y+ay;\n"
+	"					diffMax.y = ay-pixelPos.y;\n"
+	"					diffMin.z = pixelPos.z+0.5;\n"
+	"					diffMax.z = 0.5-pixelPos.z;\n"
+    "          			rendered=1;\n"
+	"				}\n"
+	"			}break;\n"
+	"			case CONE : {\n"
+	"				if(pixelPos.y<0.5 && pixelPos.y>-0.5) {\n"
+	"					float xx = (pixelPos.x)*(pixelPos.x);\n"
+	"					float yy = (pixelPos.y-0.5)*(pixelPos.y-0.5);\n"
+	"					float zz = (pixelPos.z)*(pixelPos.z);\n"
+	"					if((xx+zz)/yy<0.25){ \n"
+	"						float ax = sqrt(0.25*yy-zz);\n"
+	"						diffMin.x = pixelPos.x+ax;\n"
+	"						diffMax.x = ax-pixelPos.x;\n"
+	"						float ay = sqrt((yy+xx)/0.25);\n"
+	"						diffMin.y = pixelPos.y+0.5;\n"
+	"						diffMax.y = 0.5-pixelPos.y;\n"
+	"						float az = sqrt(0.25*yy-xx);\n"
+	"						diffMin.z = pixelPos.z+az;\n"
+	"						diffMax.z = az-pixelPos.z;\n"
+    "          				rendered=1;\n"
+	"					}\n"
+	"				}\n"
+	"			} break;\n"
+	"			case TUBE : {\n"
+	"				if(length(vec2(pixelPos.x, pixelPos.z))<=0.5\n"
+	"						&& (pixelPos.y>-0.5 && pixelPos.y<0.5)) { \n"
+	"					float xx = (pixelPos.x)*(pixelPos.x);\n"
+	"					float zz = (pixelPos.z)*(pixelPos.z);\n"
+	"					float ax = sqrt(0.25-zz);\n"
+	"					diffMin.x = pixelPos.x+ax;\n"
+	"					diffMax.x = ax-pixelPos.x;\n"
+	"					float az = sqrt(0.25-xx);\n"
+	"					diffMin.z = pixelPos.z+az;\n"
+	"					diffMax.z = az-pixelPos.z;\n"
+	"					diffMin.y = pixelPos.y+0.5;\n"
+	"					diffMax.y = 0.5-pixelPos.y;\n"
+    "          			rendered=1;\n"
+	"				}\n"
+	"			} break;\n"
+	"			case SPHERE : {\n"
+	"				if(length(pixelPos)<=0.5) { \n"
+	"					float xx = (pixelPos.x)*(pixelPos.x);\n"
+	"					float yy = (pixelPos.y)*(pixelPos.y);\n"
+	"					float zz = (pixelPos.z)*(pixelPos.z);\n"
+	"					float ax = sqrt(0.25-yy-zz);\n"
+	"					diffMin.x = pixelPos.x+ax;\n"
+	"					diffMax.x = ax-pixelPos.x;\n"
+	"					float ay = sqrt(0.25-xx-zz);\n"
+	"					diffMin.y = pixelPos.y+ay;\n"
+	"					diffMax.y = ay-pixelPos.y;\n"
+	"					float az = sqrt(0.25-xx-yy);\n"
+	"					diffMin.z = pixelPos.z+az;\n"
+	"					diffMax.z = az-pixelPos.z;\n"
+    "          			rendered=1;\n"
+	"				}\n"
+	"			} break;\n"
+	"			case BOX : {\n"
+	"				diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);\n"
+	"				diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;\n"
+    "       		if(diffMin.x>0 && diffMax.x>0\n"
+	"						&& diffMin.y>0 && diffMax.y>0\n"
+    "          				&& diffMin.z>0 && diffMax.z>0){\n"
+	"					rendered=1;\n" 
+	"				} \n"
+	"			} break;\n"
+	"			case FRAME : {\n"
+	"				diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);\n"
+	"				diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;\n"
+    "       		if(diffMin.x>0 && diffMax.x>0\n"
+	"						&& diffMin.y>0 && diffMax.y>0\n"
+    "          				&& diffMin.z>0 && diffMax.z>0){\n"
+	"					rendered=1;\n" 
+	"				} \n"
+	"			} break;\n"
+	"			case MODEL : {\n"
+    "   			ivec2 selSize = textureSize(selectTex, 0);\n"
+    "   			vec4 sel = texelFetch(selectTex,\n"
+    "                         ivec2(coordX*float(selSize.x), \n"
+    "                               coordY*float(selSize.y)), \n"
+    "                         0);\n"
+        			//get front surfaces before depth map
+    "   			if(pixZ<=cutZ+thickness/1000.0) { \n"
+	"					if(sel.z==0) {\n"
+	"						if(sel.x==shapeID) {\n"
+	"							rendered=1;\n" 
+	"						}\n"
+	"						else if((int(shapeIDBit)&int(sel.w))>0) {\n"
+	"							diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);\n"
+	"							diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;\n"
+    "       					if(diffMin.x>0 && diffMax.x>0\n"
+	"									&& diffMin.y>0 && diffMax.y>0\n"
+    "          							&& diffMin.z>0 && diffMax.z>0){\n"
+	"								rendered=1;\n" 
+	"							}\n"
+	"						}\n"
+	"					}\n"
+    "       			if(surface>0 \n"
+    "               		&& (pixZ>cutZ \n"
+    "                      || (sel.z>0 && (int(shapeIDBit)&int(sel.w))>0))) {\n"
+	"							rendered=2;\n"
+	"					}\n"
+	"				}\n"
+	"			} break;\n"
+	"		}\n"
+	"		if(rendered>0) {\n"
+	"			ratioWithinBox = (pixelPos)+0.5;\n"
+				//test if on the surface
+	"			if(diffMin.x*modelScale.x<thickness || \n"
+	"							diffMax.x*modelScale.x<thickness || \n"
+	"							diffMin.y*modelScale.y<thickness || \n"
+	"							diffMax.y*modelScale.y<thickness || \n"
+	"							diffMin.z*modelScale.z<thickness || \n"
+	"							diffMax.z*modelScale.z<thickness) { \n"
+	"					rendered=2;\n" 
+	"			} \n"
+                    //extend ratiowithinbox to multiplesubshapes
+                    //and get gradient ratio according to type
+    "               float gradRatio = 0;\n"
+    "               vec3 subAdd;\n"
+    "               vec3 subDiv;\n"
+    "               if(insideStructure==0) {\n"//from center
+    "                   subAdd = vec3(subShapeID, subShapeID, subShapeID);\n"
+    "                   subDiv = vec3(subShapesNb, subShapesNb, subShapesNb);\n"
+    "                  ratioWithinBox.xyz=(ratioWithinBox.xyz+subAdd)/subDiv;\n"
+    "                  	outRatioWithinBox.xyz=ratioWithinBox.xyz;\n"
+    "                   gradRatio = length(ratioWithinBox.xyz\n"
+    "                                     - vec3(0.5,0.5,0.5))/0.5;\n"
+    "               }\n"
+    "               else {\n"//from surface or along axes
+    "                   subAdd = vec3(0,0, subShapeID);\n"
+    "                   subDiv = vec3(1,1, subShapesNb);\n"
+    "                  	ratioWithinBox.xyz=(ratioWithinBox.xyz+subAdd)/subDiv;\n"
+    "                  	outRatioWithinBox.xyz=ratioWithinBox.xyz;\n"
+	"					if(insideStructure==1) {\n"
+	"						ratioWithinBox.x=0.5;\n"
+	"					}\n"
+	"					else if(insideStructure==2) {\n"
+	"						ratioWithinBox.y=0.5;\n"
+	"					}\n"
+	"					else if(insideStructure==3 && shapeGeom!=PATH) {\n"
+	"						ratioWithinBox.z=0.5;\n"
+	"					}\n"
+	"					switch(shapeGeom) {\n"
+	"						case BOX : {\n"
+	"							vec3 q = abs(ratioWithinBox.xyz\n"
+	"										-vec3(0.5,0.5,0.5))*2.0\n" 
+	"									- vec3(1.0,1.0,1.0);\n"
+  	"							gradRatio = 1.0-abs(length(max(q,0.0)) \n"
+	"									+ min(max(q.x,max(q.y,q.z)),0.0));\n"
+	"						} break;\n"
+	"						case SPHERE : {\n"
+    "                   		gradRatio = length(ratioWithinBox.xyz\n"
+    "                       	              - vec3(0.5,0.5,0.5))/0.5;\n"
+	"						} break;\n"
+	"						case PATH  : {\n"
+	"							vec2 d = abs(vec2(length((ratioWithinBox.xy-vec2(0.5, 0.5))*2.0), \n"
+	"												  (ratioWithinBox.z-0.5)*2.0)) \n"
+	"											- vec2(1.0,1.0);\n"
+	"						 	gradRatio = 1.0 - abs(min(max(d.x,d.y),0.0)\n"
+	"										+ length(max(d,0.0)));\n"
+	"						} break;\n"
+	"						case TUBE  : {\n"
+	"							vec2 d = abs(vec2(length((ratioWithinBox.xz-vec2(0.5, 0.5))*2.0), \n"
+	"												  (ratioWithinBox.y-0.5)*2.0)) \n"
+	"											- vec2(1.0,1.0);\n"
+	"						 	gradRatio = 1.0 - abs(min(max(d.x,d.y),0.0)\n"
+	"										+ length(max(d,0.0)));\n"
+	"						} break;\n"
+	"						case CONE : {\n" 
+	"							float q = length((ratioWithinBox.xz\n"
+	"											- vec2(0.5,0.5))*2.0);\n"
+  	"							gradRatio = 1.0-abs(max(dot(vec2(0.5,0.5),\n"
+	"										vec2(q,(ratioWithinBox.y-1.0))),\n"
+	"										-1.0-(ratioWithinBox.y-1.0)));\n"
+	"						} break;\n"
+	"						case FRAME : {\n" //FIXME compute frame SDF
+	"							vec3 q = abs(ratioWithinBox.xyz\n"
+	"										-vec3(0.5,0.5,0.5))*2.0\n" 
+	"									- vec3(1.0,1.0,1.0);\n"
+  	"							gradRatio = 1.0-abs(length(max(q,0.0)) \n"
+	"									+ min(max(q.x,max(q.y,q.z)),0.0));\n"
+	"						} break;\n"
+	"						case MODEL : {\n" 
+    "                   		gradRatio = texture(surfDistTex, \n"
+	"                             					ratioWithinBox).r\n"
+	"										* structureRatio;\n"
+	"						} break;\n"
+	"						default :{\n"//defaults to sphere
+    "                   		gradRatio = length(ratioWithinBox.xyz\n"
+    "                       	              - vec3(0.5,0.5,0.5))/0.5;\n"
+	"						} break;\n"
+    "               	}\n"
+    "               }\n"
+                    //texture coordinates
+    "               vec3 texCoords = vec3(1-ratioWithinBox.x,\n"
+    "                                     1-ratioWithinBox.y,\n"
+    "                                     ratioWithinBox.z);\n"
+	"\n"
+					//start with shapeColor
+	"				finalColor = shapeColor;\n"
+					//test gradient
+	"				if(gradientAlpha>0) {\n"
+	"					float gradColor = \n"
+	"						pow(gradientCurveRatio<0?1.0-gradRatio:gradRatio,\n" 
+	"							abs(gradientCurveRatio));\n"
+	"					if(gradientSteps>1) {\n"
+	"						gradColor = floor(gradColor*gradientSteps)\n"
+	"										/ gradientSteps;\n"
+	"					}\n"
+	"					gradColor*=(gradRatio<=1.0)?1.0:0.0;\n"
+	"					if(gradientType>0) {\n"//gradient texture
+	"						finalColor=finalColor*(1.0-gradientAlpha) \n"
+	"								+ finalColor*gradientAlpha\n"
+    "									* texture(gradientTex, \n"
+    "										vec2(gradRatio, 0.0)).xyz;\n"
+	"					}\n"
+	"					else {\n"
+	"						finalColor=finalColor*(1.0-gradientAlpha) \n"
+	"								+ finalColor*gradColor*gradientAlpha;\n"
+	"					}\n"
+	"				}\n"
+					//test density
+	"				if(densityAlpha>0) {\n"
+	"					float densColor = \n"
+	"						pow(densityCurveRatio<0?1.0-gradRatio:gradRatio,\n" 
+	"							abs(densityCurveRatio));\n"
+    "                   if(densityType==0 && \n" //layers
+	"							length(mod(densColor*100.0, \n"
+	"									   densitySize*100.0))\n"
+	"								< densityRatio*densitySize*100.0) {\n"
+	"						densColor = 1.0;\n"
+	"						densColor*=(gradRatio<=1.0)?1.0:0.0;\n"
+    "					}\n" 
+    "                   else if(densityType==1\n" //grid
+	"							&& (length(mod(ratioWithinBox.x*100,\n"
+    "										densitySize*100.0))\n"
+	"								<densitySize*densityRatio*100.0 \n"
+    "                   		|| length(mod(ratioWithinBox.y*100,\n"
+    "										densitySize*100.0))\n"
+	"								<densitySize*densityRatio*100.0 \n"
+    "                   		|| length(mod(ratioWithinBox.z*100,\n"
+    "										densitySize*100.0))\n"
+	"								<densitySize*densityRatio*100.0)) { \n"
+	"							densColor = 1.0;\n"
+    "                   }\n" 
+	"					else if(densityType==2  \n" //pointcloud
+	"						   && floor(random(ratioWithinBox.xyz)\n"
+	"										*floor(100.0))>100.0*densColor) {\n"
+	"							densColor = 1.0; \n"
+	"						densColor*=(gradRatio<=1.0)?1.0:0.0;\n"
+	"					}\n"
+	"					else {\n"
+	"						densColor = 0.0;\n"
+	"					}\n"
+	"					finalColor=finalColor*(1.0-densityAlpha) \n"
+	"								+ finalColor*densColor*densityAlpha;\n"
+	"				}\n"
+					//test texture
+	"				if(texAlpha>0) {\n"
+    "                   vec3 texColor = texture(insideTex, \n"
+    "                             texOffset+texScale*texCoords).xyz;\n"
+	"					if(texGray>0) {\n"
+	"						texColor=vec3((texColor.r+texColor.g+texColor.b)\n"
+	"									/ 3.0);\n"
+	"					}\n"
+	"					finalColor=finalColor*(1.0-texAlpha) \n"
+	"								+ finalColor*texColor*texAlpha;\n"
+	"				}\n"
+#ifdef GL42
+					//if revealing something, output values
+    "               if(sli.x>=1.0 && depthID<=depthOutNb) {\n"
+                        //inside output
+    "                   if(revInside>0 && rendered==1) {\n"
+    "                       imageAtomicMax(outputTex, \n"
+    "                               ivec2(mod(outOffset+revInside,outCols), \n"
+    "                                 floor((outOffset+revInside))/outCols),\n"
+    "                               1);\n"
+    "                   }\n"
+    "                   outRatioWithinBox.x=clamp(outRatioWithinBox.x, 0, 1);\n"
+    "                   outRatioWithinBox.y=clamp(outRatioWithinBox.y, 0, 1);\n"
+    "                   outRatioWithinBox.z=clamp(outRatioWithinBox.z, 0, 1);\n"
+                        //compute min,max on the three axes
+    "                   int xk=int(outRatioWithinBox.x*1000.0);\n"
+    "                   int yk=int(outRatioWithinBox.y*1000.0);\n"
+    "                   int zk=int(outRatioWithinBox.z*1000.0);\n"
+                        //output min/max ratios
+    "                   if(revCenter>0) {\n"
+    "                       imageAtomicMax(outputTex, \n"
+    "                          ivec2(mod(outOffset+revCenter+0,outCols), \n"
+    "                                floor((outOffset+revCenter+0)/outCols)),\n"
+    "                           1000-xk);\n"
+    "                       imageAtomicMax(outputTex, \n"
+    "                          ivec2(mod(outOffset+revCenter+1,outCols), \n"
+    "                                floor((outOffset+revCenter+1)/outCols)),\n"
+    "                          xk);\n"
+    "                       imageAtomicMax(outputTex, \n"
+    "                          ivec2(mod(outOffset+revCenter+2,outCols), \n"
+    "                                floor((outOffset+revCenter+2)/outCols)),\n"
+    "                         1000-yk);\n"
+    "                       imageAtomicMax(outputTex, \n"
+    "                          ivec2(mod(outOffset+revCenter+3,outCols), \n"
+    "                                floor((outOffset+revCenter+3)/outCols)),\n"
+    "                          yk);\n"
+    "                       imageAtomicMax(outputTex, \n"
+    "                          ivec2(mod(outOffset+revCenter+4,outCols), \n"
+    "                                floor((outOffset+revCenter+4)/outCols)),\n"
+    "                          1000-zk);\n"
+    "                       imageAtomicMax(outputTex, \n"
+    "                          ivec2(mod(outOffset+revCenter+5,outCols), \n"
+    "                                floor((outOffset+revCenter+5)/outCols)),\n"
+    "                          zk);\n"
+    "                   }\n"
+						//convert from rgb to hsv
+	"					vec3 hsv = rgb2hsv(finalColor);\n"
+                        //Sum color channels
+    "                   if(revColor>0) {\n"
+                            //count nb revealed points
+    "                       imageAtomicAdd(outputTex,\n"
+    "                          ivec2(mod(outOffset+revColor+0,outCols), \n"
+    "                                floor((outOffset+revColor+0)/outCols)),\n"
+    "                          1);\n"
+                            //sum point h
+    "                       imageAtomicAdd(outputTex,\n"
+    "                          ivec2(mod(outOffset+revColor+1,outCols), \n"
+    "                                floor((outOffset+revColor+1)/outCols)),\n"
+    "                          clamp(int(hsv.x*1000.0),0,1000));\n"
+                            //sum s
+    "                       imageAtomicAdd(outputTex,\n"
+    "                          ivec2(mod(outOffset+revColor+2,outCols), \n"
+    "                                floor((outOffset+revColor+2)/outCols)),\n"
+    "                          clamp(int(hsv.y*1000.0),0,1000));\n"
+                            //sum v
+    "                       imageAtomicAdd(outputTex,\n"
+    "                          ivec2(mod(outOffset+revColor+3,outCols), \n"
+    "                                floor((outOffset+revColor+3)/outCols)),\n"
+    "                          clamp(int(hsv.z*1000.0),0,1000));\n"
+    "                   }\n"
+						//histo : accumulate on luminance bins
+    "                   if(revHisto>0) {\n"
+                            //count nb revealed points
+    "                       imageAtomicAdd(outputTex,\n"
+    "                          ivec2(mod(outOffset+revHisto,outCols), \n"
+    "                                floor((outOffset+revHisto)/outCols)),\n"
+    "                          1);\n"
+	"						int bin = int(hsv.z*float(histoOutSize-1));\n"
+    "                       imageAtomicAdd(outputTex,\n"
+    "                          ivec2(mod(outOffset+revHisto+1+bin,outCols), \n"
+    "                                floor((outOffset+revHisto+1+bin)/outCols)),\n"
+    "                          1);\n"
+	"					}\n"
+
+                        //2D grid of projected voxels (nbvox, 3D coords, lum)
+    "                   if(revVoxels>0) {\n"
+							//compute pixel ratio within 2D bounding rect
+	"						vec2 pixRatio = (vec2(coordX, coordY)\n"
+	"											- boundingRect.xy) / \n"
+	"									   (boundingRect.zw-boundingRect.xy);\n"
+	"						pixRatio.x = clamp(pixRatio.x, 0.0, 1.0);\n"
+	"						pixRatio.y = clamp(pixRatio.y, 0.0, 1.0);\n"
+							//compute offset in voxel output
+	"						int voxOff = outOffset+revVoxels;\n"
+	"						voxOff+=5*(int(pixRatio.x*voxelOutSize)\n"
+	"							+ int((1.0-pixRatio.y)*voxelOutSize)\n"
+	"									*voxelOutSize);\n"
+							//accumulate points
+	"						imageAtomicAdd(outputTex,\n"
+    "                          ivec2(mod(voxOff,outCols), \n"
+    "                                floor((voxOff)/outCols)),\n"
+	"							1);\n"
+							//accumulate coords
+	"						imageAtomicAdd(outputTex, \n"
+    "                          ivec2(mod(voxOff+1,outCols), \n"
+    "                                floor((voxOff+1)/outCols)),\n"
+    "                          clamp(int(outRatioWithinBox.x*1000.0),0,1000));\n"
+	"						imageAtomicAdd(outputTex, \n"
+    "                          ivec2(mod(voxOff+2,outCols), \n"
+    "                                floor((voxOff+2)/outCols)),\n"
+    "                          clamp(int(outRatioWithinBox.y*1000.0),0,1000));\n"
+	"						imageAtomicAdd(outputTex, \n"
+    "                          ivec2(mod(voxOff+3,outCols), \n"
+    "                                floor((voxOff+3)/outCols)),\n"
+    "                          clamp(int(outRatioWithinBox.z*1000.0),0,1000));\n"
+							//accumulate lum
+	"						imageAtomicAdd(outputTex, \n"
+    "                          ivec2(mod(voxOff+4,outCols), \n"
+    "                                floor((voxOff+4)/outCols)),\n"
+    "                          clamp(int(hsv.z*1000.0),0,1000));\n"
+    "                   }\n"
+    "               }\n"
+#endif
+    "       }\n"
+			//SURFACE test
+    "       if(rendered>1) { \n"
+	"			finalColor = surfaceColor;\n"
+#ifdef GL42
+    "           if(revSurface>0 && sli.x>=1.0 && depthID<=depthOutNb) {\n"
+    "               imageAtomicMax(outputTex,\n"
+    "                         ivec2(mod(outOffset+revSurface,outCols), \n"
+    "                               floor((outOffset+revSurface)/outCols)),\n"
+    "                         1);\n"
+    "           }\n"
+#endif
+    "       }\n"
+    "   }\n"
+		//final test, output if rendered or not, output final color
+    "   if(rendered>0 && length(finalColor)>0) { \n"
+#ifdef GL42
+	"		if(revSize>0) {\n"
+    "   		imageAtomicOr(outputTex, \n"
+    "           				ivec2(mod(outOffset,outCols), \n"
+    "             					floor((outOffset))/outCols),\n"
+    "           				rendered);\n"
+	"		}\n"
+#endif
+    "       if((insideVisible>0 && rendered==1) \n"
+	"				|| (surface>0 && rendered==2)) {\n"
+	"			color = vec4(finalColor, 1.0);\n"//display
+	//"			color = vec4(finalColor, sli.x);\n"//display
+	/*
+	"			if(sli.x>0.5) {\n"
+	"				color = vec4(1.0, 0.0, 0.0, 1.0);\n"//display
+	"			}\n"
+	"			else {\n"
+	"				color = vec4(0.0, 1.0, 0.0, 1.0);\n"//display
+	"			}\n"
+	*/
+	"		}\n"
+	"		else {\n"
+	"			color = vec4(0.0, 0.0, 0.0, 1.0);\n"
+	"		}\n"
+    //"       color = vec4((pixelPos+0.5)/2.0, 1.0);\n"//debug pix coords
+    //"       color = vec4(cutZ*10.0, pixZ*10.0, 0.0, 1.0);\n"//debug slice texture
+	//"		  color = vec4(texture(surfDistTex, ratioWithinBox).r*10.0, 1.0,1.0,1.0);\n"
+	//"		  color = vec4(texture(insideTex, ratioWithinBox).r*10.0, 1.0,1.0,1.0);\n"
+	//"		  color = vec4(ratioWithinBox.xyz, 1.0);\n"
+    "   }\n"
+    "   else {\n" //DISCARD
+	//"		color = vec4(1.0,0.0,0.0,1.0);\n"
+    "       discard;\n"
+    "   }\n"
+    "}\n"};
+    m_programs[Reveal::RENDERPROG]
+        = Reveal::getInstance()->createProgram(vertSource, fragSource);
+    m_uniforms[Reveal::RENDERPROG] = map<Reveal::REVIL_UNIFORM, GLint>();
+    m_uniforms[Reveal::RENDERPROG][Reveal::MIRRORED]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "mirrored");
+    m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPROJMAT]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "viewProjMat");
+    m_uniforms[Reveal::RENDERPROG][Reveal::VIEWMAT]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "viewMat");
+    m_uniforms[Reveal::RENDERPROG][Reveal::MODELMAT]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "modelMat");
+    m_uniforms[Reveal::RENDERPROG][Reveal::INVMODELMAT]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "invModelMat");
+    m_uniforms[Reveal::RENDERPROG][Reveal::MODELSCALE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "modelScale");
+    m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTWIDTH]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "viewportWidth");
+    m_uniforms[Reveal::RENDERPROG][Reveal::VIEWPORTHEIGHT]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG],"viewportHeight");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SLICETEX]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "sliceTex");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SELECTTEX]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "selectTex");
+    m_uniforms[Reveal::RENDERPROG][Reveal::INSIDETEX]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "insideTex");
+    m_uniforms[Reveal::RENDERPROG][Reveal::COORDSTEX]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "coordsTex");
+    m_uniforms[Reveal::RENDERPROG][Reveal::TEXGRAY]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "texGray");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REACTTEX]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "reactTex");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SURFDISTEX]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "surfDistTex");
+
+    m_uniforms[Reveal::RENDERPROG][Reveal::SHAPEID]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "shapeID");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SHAPEIDBIT]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "shapeIDBit");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SHAPEGEOM]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "shapeGeom");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SHAPECOLOR]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "shapeColor");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SUBSHAPEID]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "subShapeID");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SUBSHAPESNB]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "subShapesNb");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SUBSHAPEINVMAT]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG],"subShapeInvMat");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REVEALEDBY]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revealedBy");
+
+    m_uniforms[Reveal::RENDERPROG][Reveal::SURFACE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "surface");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SURFACECOLOR]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "surfaceColor");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SURFACETHICKNESS]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "thickness");
+    m_uniforms[Reveal::RENDERPROG][Reveal::SURFACETEX]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "surfaceTex");
+
+    m_uniforms[Reveal::RENDERPROG][Reveal::INSIDEVISIBLE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "insideVisible");
+    m_uniforms[Reveal::RENDERPROG][Reveal::INSIDESTRUCT]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "insideStructure");
+    m_uniforms[Reveal::RENDERPROG][Reveal::STRUCTRATIO]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "structureRatio");
+
+    m_uniforms[Reveal::RENDERPROG][Reveal::GRADIENTALPHA]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "gradientAlpha");
+    m_uniforms[Reveal::RENDERPROG][Reveal::GRADIENTTYPE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "gradientType");
+    m_uniforms[Reveal::RENDERPROG][Reveal::GRADIENTSTEPS]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "gradientSteps");
+    m_uniforms[Reveal::RENDERPROG][Reveal::GRADIENTCURVERATIO]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "gradientCurveRatio");
+    m_uniforms[Reveal::RENDERPROG][Reveal::GRADIENTTEXTURE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "gradientTex");
+
+    m_uniforms[Reveal::RENDERPROG][Reveal::DENSITYALPHA]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "densityAlpha");
+    m_uniforms[Reveal::RENDERPROG][Reveal::DENSITYTYPE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "densityType");
+    m_uniforms[Reveal::RENDERPROG][Reveal::DENSITYRATIO]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "densityRatio");
+    m_uniforms[Reveal::RENDERPROG][Reveal::DENSITYSIZE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "densitySize");
+    m_uniforms[Reveal::RENDERPROG][Reveal::DENSITYCURVERATIO]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "densityCurveRatio");
+
+    m_uniforms[Reveal::RENDERPROG][Reveal::TEXALPHA]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "texAlpha");
+    m_uniforms[Reveal::RENDERPROG][Reveal::TEXOFFSET]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "texOffset");
+    m_uniforms[Reveal::RENDERPROG][Reveal::TEXSCALE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "texScale");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REACTIVITY]
+      = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "reactivity");
+
+
+    m_uniforms[Reveal::RENDERPROG][Reveal::BBOXMIN]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "bboxMin");
+    m_uniforms[Reveal::RENDERPROG][Reveal::BBOXSIZE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "bboxSize");
+    m_uniforms[Reveal::RENDERPROG][Reveal::BBOXLOCALSIZE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "bboxLocalSize");
+    m_uniforms[Reveal::RENDERPROG][Reveal::BBOXROT]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "bboxRot");
+#ifdef GL42
+    //output texture
+    m_outputImg = new unsigned int[m_outputImgSize*m_outputImgSize];
+    m_outputImgInit = new unsigned int[m_outputImgSize*m_outputImgSize];
+    memset(&m_outputImgInit[0], 0, m_outputImgSize*m_outputImgSize*4);
+    glGenTextures(1, &m_outputTex);
+    glBindTexture(GL_TEXTURE_2D, m_outputTex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI,
+                 m_outputImgSize, m_outputImgSize, 0,
+                 GL_RED_INTEGER, GL_UNSIGNED_INT, m_outputImgInit);
+    m_uniforms[Reveal::RENDERPROG][Reveal::OUTPUTTEX]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "outputTex");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REVSIZE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revSize");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REVSURFACE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revSurface");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REVINSIDE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revInside");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REVCENTER]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revCenter");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REVCURSOR]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revCursor");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REVCOLOR]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revColor");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REVHISTO]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revHisto");
+    m_uniforms[Reveal::RENDERPROG][Reveal::REVVOXELS]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "revVoxels");
+    m_uniforms[Reveal::RENDERPROG][Reveal::OUTSHAPESIZE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "shapeOutSize");
+    m_uniforms[Reveal::RENDERPROG][Reveal::OUTHISTOSIZE]
+     = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "histoOutSize");
+    m_uniforms[Reveal::RENDERPROG][Reveal::OUTVOXELSIZE]
+     = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "voxelOutSize");
+    m_uniforms[Reveal::RENDERPROG][Reveal::OUTDEPTHSIZE]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "depthOutSize");
+    m_uniforms[Reveal::RENDERPROG][Reveal::OUTNBDEPTH]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "depthOutNb");
+    m_uniforms[Reveal::RENDERPROG][Reveal::BRECT]
+        = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "boundingRect");
+    createRTT(m_renderTex, m_renderFBO, m_rttWidth, m_rttHeight, false);
+#endif
+    }
+
+   {
+    //select prog
+    const char * vertSource = {
+#ifdef GL42
+    "#version 430 \n"
+#else
+    "#version 410 \n"
+#endif
+    " \n"
+    "in vec3 vertex;\n"
+    " \n"
+    "uniform mat4 modelMat;\n"
+    "uniform mat4 viewMat;\n"
+    "uniform mat4 viewProjMat;\n"
+    "uniform float mirrored;\n"
+    " \n"
+    "void main(void) {\n"
+    "   vec4 posWS = modelMat * vec4(vertex, 1.0);\n"
+    "   if(mirrored<1) {\n"
+    "       posWS.x = -posWS.x;\n"
+    "   }\n"
+    "   gl_Position = viewProjMat * posWS;\n"
+    "}\n"};
+
+    const char * fragSource = {
+#ifdef GL42
+    "#version 430 \n"
+#else
+    "#version 410 \n"
+#endif
+    " \n"
+#ifdef GL42
+    "layout(binding=0) uniform sampler2D sliceTex;\n"
+#else
+    "uniform sampler2D sliceTex;\n"
+#endif
+    "uniform float viewportWidth;\n"
+    "uniform float viewportHeight;\n"
+    "uniform float shapeID;\n"
+    "uniform float shapeIDBit;\n"
+    "uniform float mirrored;\n"
+    "uniform float thickness;\n"
+    "uniform int surface;\n"
+    " \n"
+    "out vec4 color;\n"
+    " \n"
+    "void main(void) {\n"
+    "   float coordX = (gl_FragCoord.x-0.5)/viewportWidth;\n"
+    "   float coordY = (gl_FragCoord.y-0.5)/viewportHeight;\n"
+    "   ivec2 sliSize = textureSize(sliceTex, 0);\n"
+    "   vec4 sli = texelFetch(sliceTex,\n"
+    "                         ivec2(coordX*float(sliSize.x),\n"
+    "                               coordY*float(sliSize.y)),\n"
+    "                         0);\n"
+    "   float pixZ=abs(gl_FragCoord.z);\n"
+    "   float cutZ=abs(sli.z);\n"
+    //  keep all ids of back surfaces after depth map
+    "   if(pixZ>cutZ && cutZ>0) {\n"
+    "       if((mirrored<1 && !gl_FrontFacing)\n"
+    "               || (mirrored>0 && gl_FrontFacing)) {\n"
+    "           color = vec4(shapeID, 0, \n"
+    "                        (abs(pixZ-cutZ)<thickness/1000.0 && surface>0)?1:0, \n"
+    "                        shapeIDBit);\n"
+    "       }\n"
+    "       else {\n" //occlude back when front face also behind
+    "           color = vec4(-shapeID, 0, 0, -shapeIDBit);\n"
+    "       }\n"
+    "   }\n"
+    "   else {\n"
+    "       discard;\n"
+    "   }\n"
+    "}\n"};
+    m_programs[Reveal::SELECTPROG]
+        = Reveal::getInstance()->createProgram(vertSource, fragSource);
+    m_uniforms[Reveal::SELECTPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
+    m_uniforms[Reveal::SELECTPROG][Reveal::MIRRORED]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "mirrored");
+    m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPROJMAT]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "viewProjMat");
+    m_uniforms[Reveal::SELECTPROG][Reveal::VIEWMAT]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "viewMat");
+    m_uniforms[Reveal::SELECTPROG][Reveal::MODELMAT]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "modelMat");
+    m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPORTWIDTH]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "viewportWidth");
+    m_uniforms[Reveal::SELECTPROG][Reveal::VIEWPORTHEIGHT]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG],"viewportHeight");
+    m_uniforms[Reveal::SELECTPROG][Reveal::SLICETEX]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "sliceTex");
+    m_uniforms[Reveal::SELECTPROG][Reveal::SHAPEID]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "shapeID");
+    m_uniforms[Reveal::SELECTPROG][Reveal::SHAPEIDBIT]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "shapeIDBit");
+    m_uniforms[Reveal::SELECTPROG][Reveal::SURFACETHICKNESS]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "thickness");
+    m_uniforms[Reveal::SELECTPROG][Reveal::SURFACE]
+        = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "surface");
+    createRTT(m_selectTex, m_selectFBO, m_rttWidth, m_rttHeight, false);
+    }
+
+    //SLICE
+    {
+    const char * vertSource = {
+#ifdef GL42
+    "#version 430 \n"
+#else
+    "#version 410 \n"
+#endif
+    " \n"
+    "#define s2(a, b) temp = a; a = min(a, b); b = max(temp, b);\n"
+    "#define mn3(a, b, c)  s2(a, b); s2(a, c);\n"
+    "#define mx3(a, b, c)  s2(b, c); s2(a, c);\n"
+    "#define mnmx3(a, b, c) mx3(a, b, c); s2(a, b);\n"
+    "#define mnmx4(a, b, c, d) s2(a, b); s2(c, d); s2(a, c); s2(b, d);\n"
+    "#define mnmx5(a, b, c, d, e) s2(a,b); s2(c,d);mn3(a,c,e);mx3(b,d,e);\n"
+   "#define mnmx6(a,b,c,d,e,f) s2(a,d);s2(b,e);s2(c,f);mn3(a,b,c);mx3(d,e,f);\n"
+    "in vec3 vertex; \n"
+    " \n"
+#ifdef GL42
+    "layout(binding=0) uniform sampler2D depthCamTex;\n"
+    "layout(binding=1) uniform sampler2D depthCamTexFil;\n"
+    "layout(binding=2) uniform sampler2D markersTex;\n"
+    //"layout(r32ui, binding=2) uniform coherent uimage2D outputTex;\n"
+#else
+    "uniform sampler2D depthCamTex;\n"
+    "uniform sampler2D depthCamTexFil;\n"
+    "uniform sampler2D markersTex;\n"
+#endif
+    "uniform mat4 modelMat;\n"
+    "uniform mat4 viewMat;\n"
+    "uniform mat4 viewProjMat;\n"
+    "uniform float camXReso;\n"
+    "uniform float camYReso;\n"
+    "uniform float camXZFactor;\n"
+    "uniform float camYZFactor;\n"
+    "uniform int camFilter;\n"
+    "uniform int background;\n"
+    "uniform float camContThresh;\n"
+    "uniform float camMarkers;\n"
+    "uniform int depthType;\n"
+    "uniform int depthID;\n"
+    "uniform float outputCurs;\n"
+    "uniform float mirrored;\n"
+    " \n"
+    "out vec3 viewRay;\n"
+    "out float kept;\n"
+    "flat out int outDepthID;\n"
+    " \n"
+    "void main(void) {\n"
+    "   vec4 depthPos = vec4(0, 0, 0, 1);\n"
+    "   vec4 posWS = vec4(0, 0, 0, 1);\n"
+        //depth camera
+    "   if(depthType==0) {\n"
+    "	    vec2 coords = vertex.xy;\n"
+            //get marker if any
+    "       if(camMarkers>0) {\n"
+    "           outDepthID = int(float(texture(markersTex,\n"
+    "                                  vec2(coords.x/camXReso,\n"
+    "                                       coords.y/camYReso)).r)\n"
+    "                           * 255.0);\n"
+    "       }\n"
+    "       else {\n"
+    "           outDepthID=depthID+1;\n"
+    "       }\n"
+            //get depth pixel in camera texture
+    "       float depth = \n"
+    "                     float(texture(depthCamTex,\n"
+    "                                   vec2(coords.x/camXReso,\n"
+    "                                        coords.y/camYReso)).r)\n"
+    "                     * 65535.0;\n"
+    "       kept=1.0;\n"
+    "       float backgroundDepth=0;\n"
+    "       if(background>0) {\n"
+    "           float backDepth = float(texture(depthCamTex,\n"
+    "                                   vec2(coords.x/camXReso,\n"
+    "                                        coords.y/camYReso)).r)\n"
+    "                                   * 65535.0;\n"
+    "           if(backDepth<depth) {\n"
+    "               depth=backDepth;\n"
+    "               backgroundDepth=1;\n"
+    "           }\n"
+    "       }\n"
+    "       if(depth<=500.0 || depth>8000.0) {\n"
+    "           kept=0.0;\n"
+    "       }\n"
+    "       else if(backgroundDepth==0) {\n"
+                //filter out contours
+    "           float maxD=camContThresh;\n" 
+    "           bool contour=false;\n"
+    "           for(int dX = -1; dX <= 1; ++dX) {\n"
+    "               for(int dY = -1; dY <= 1; ++dY) {\n"
+    "                   if(abs(float(texture(depthCamTex,\n"
+    "                                   vec2((coords.x+dX)/camXReso,\n"
+    "                                        (coords.y+dY)/camYReso)).r)\n"
+    "                               * 65535.0\n"
+    "                           - depth) > maxD) {\n"
+    "                       contour=true;\n"
+    "                   }\n"
+    "               }\n"
+    "           }\n"
+    "           if(contour) {\n"
+    "               kept=0.0;\n"
+    "           }\n"
+                //see if needs filtering
+    "           if(camFilter>0) {\n"
+    "               float filtDepth = float(texture(depthCamTexFil,\n"
+    "                                       vec2(coords.x/camXReso,\n"
+    "                                        	 coords.y/camYReso)).r)\n"
+    "                                   * 65535.0;\n"
+                    //select either filtered version or current one
+                    //depending on movement 
+    "               if(abs(filtDepth-depth)<camContThresh) {\n"
+    "                   float filRatio = abs(filtDepth-depth)/camContThresh;\n"
+    "                   depth=(1-filRatio)*filtDepth+(filRatio)*depth;\n"
+    "               }\n"
+    "           }\n"
+    "       }\n"
+            //test distance again
+    "       if(depth<=500.0 || depth>8000.0) {\n"
+    "           kept=0.0;\n"
+    "       }\n"
+            //compute position in world units
+    "       depthPos = vec4((vertex.x/camXReso-0.5)\n"
+    "                           *depth*camXZFactor,\n"
+    "                        (0.5-(vertex.y/camYReso))\n"
+    "                           *depth*camYZFactor,\n"
+    "                        depth,\n"
+    "                        1.0);\n"
+            //get world pos
+    "       posWS = modelMat * depthPos;\n"
+    "   }\n"
+        //other slicing shapes
+    "   else {\n"
+    "       outDepthID=depthID+1;\n"
+    "       kept=1.0;\n"
+    "       depthPos=vec4(vertex, 1.0);\n"
+    "       posWS = modelMat * depthPos;\n"
+    "       if(mirrored<1) {\n"
+    "           posWS.x = -posWS.x;\n"
+    "       }\n"
+    "   }\n"
+#ifdef GL42
+/*
+        //output minimum point on z axis if output is active
+    "   if(outputCurs>0 && kept>0.0) {\n"
+    "       imageAtomicMin(outputTex,ivec2(0,int(depthID)+500),\n"
+    "                                  int(floor(1000.0+posWS.z/10.0)*1000000\n"
+    "                                      +floor(posWS.y/10.0+500.0)*1000\n"
+    "                                      +floor(posWS.x/10.0+500.0)));\n"
+    //"       imageAtomicMin(outputTex,ivec2(0, int(depthID)+500),4400600);\n"
+    //"       imageAtomicMin(outputTex,ivec2(0, int(depthID)+500),6400600);\n"
+    "   }\n"
+*/
+#endif
+        //keep/interpolate ray from view to each vertex
+    "   viewRay = (posWS.xyz - vec3(viewMat[3][0],\n"
+    "                               viewMat[3][1],\n"
+    "                               viewMat[3][2]));\n"
+    "   gl_Position = viewProjMat * posWS;\n"
+    "}\n"};
+    const char * fragSource = {
+#ifdef GL42
+    "#version 430 \n"
+#else
+    "#version 410 \n"
+#endif
+    " \n"
+    "in float kept;\n"
+    "in vec3 viewRay;\n"
+    "flat in int outDepthID;\n"
+    " \n"
+    "out vec4 color;\n"
+    " \n"
+    "void main(void) {\n"
+    "   float thresh=0.8;\n"
+    "   if(kept>=thresh) {\n"
+    "       color = vec4((kept-thresh)/(1.0-thresh),\n"
+    "                     float(outDepthID),\n"
+    "                     gl_FragCoord.z,\n"
+    "                     length(viewRay));\n"
+    "   }\n"
+    "   else {\n"
+    "       discard;\n"
+    "   }\n"
+//    "   color = vec4(1.0, 1.0, 0.0, 1.0);\n"
+    "}\n"};
+
+    m_programs[Reveal::SLICEPROG]
+        = Reveal::getInstance()->createProgram(vertSource, fragSource);
+    m_uniforms[Reveal::SLICEPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
+    m_uniforms[Reveal::SLICEPROG][Reveal::BACKGROUND]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "background");
+    m_uniforms[Reveal::SLICEPROG][Reveal::MIRRORED]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "mirrored");
+    m_uniforms[Reveal::SLICEPROG][Reveal::VIEWPROJMAT]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "viewProjMat");
+    m_uniforms[Reveal::SLICEPROG][Reveal::VIEWMAT]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "viewMat");
+    m_uniforms[Reveal::SLICEPROG][Reveal::MODELMAT]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "modelMat");
+    m_uniforms[Reveal::SLICEPROG][Reveal::DEPTHTYPE]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "depthType");
+    m_uniforms[Reveal::SLICEPROG][Reveal::DEPTHID]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "depthID");
+    m_uniforms[Reveal::SLICEPROG][Reveal::CAMXRESO]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camXReso");
+    m_uniforms[Reveal::SLICEPROG][Reveal::CAMYRESO]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camYReso");
+    m_uniforms[Reveal::SLICEPROG][Reveal::CAMXZFACTOR]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camXZFactor");
+    m_uniforms[Reveal::SLICEPROG][Reveal::CAMYZFACTOR]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camYZFactor");
+    m_uniforms[Reveal::SLICEPROG][Reveal::CAMTEX]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "depthCamTex");
+    m_uniforms[Reveal::SLICEPROG][Reveal::CAMTEXFIL]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "depthCamTexFil");
+    m_uniforms[Reveal::SLICEPROG][Reveal::MARKTEX]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "markersTex");
+    m_uniforms[Reveal::SLICEPROG][Reveal::CAMFILTER]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camFilter");
+    m_uniforms[Reveal::SLICEPROG][Reveal::CAMCONTOURTHRESH]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camContThresh");
+    m_uniforms[Reveal::SLICEPROG][Reveal::CAMMARKERS]
+        = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "camMarkers");
+    createRTT(m_sliceRttTex, m_sliceFBO, m_rttWidth, m_rttHeight, false);
+    }
+
+    //Calibration
+    {
+    const char * vertSource = {
+#ifdef GL42
+    "#version 430 \n"
+#else
+    "#version 410 \n"
+#endif
+    " \n"
+    "in vec3 vertex; \n"
+    " \n"
+    "void main(void) {\n"
+    "   gl_Position = vec4(vertex, 1.0);\n"
+    "}\n"};
+
+    const char * fragSource = {
+#ifdef GL42
+    "#version 430 \n"
+#else
+    "#version 410 \n"
+#endif
+    " \n"
+    "uniform float viewportWidth;\n"
+    "uniform float viewportHeight;\n"
+    "uniform float patW;\n"
+    "uniform float patPosX;\n"
+    "uniform float patPosY;\n"
+    "uniform float patNbX;\n"
+    "uniform float patNbY;\n"
+    "uniform float patBright;\n"
+    "uniform vec2 patOffset;\n"
+    "uniform vec2 patRange;\n"
+#ifdef GL42
+    "layout(binding=0) uniform sampler2D patternTex;\n"
+#else
+    "uniform sampler2D patternTex;\n"
+#endif
+    " \n"
+    "out vec4 color;\n"
+    " \n"
+    "void main(void) {\n"
+    /*
+    "   float coordX = (gl_FragCoord.x-0.5)/viewportWidth;\n"
+    "   float coordY = (gl_FragCoord.y-0.5)/viewportHeight;\n"
+    "   ivec2 patSize = textureSize(patternTex, 0);\n"
+    "   float pat = texelFetch(patternTex,\n"
+    "                          ivec2(coordX*float(patSize.x),\n"
+    "                                (1.0-coordY)*float(patSize.y)),\n"
+    "                          0).r;\n"
+    "   color=vec4(pat, pat, pat, 1.0);\n"
+    //"   color=vec4(1.0,1.0,1.0,1.0);\n"
+    */
+    //pixel is white by default
+    "   color = vec4(patBright);\n"
+    "   float offX = gl_FragCoord.x - patPosX;\n"
+    "   float offY = (viewportHeight-gl_FragCoord.y) - patPosY;\n"
+    //black squares
+    "   if(offX>=0 && offX<patW*(patNbX+1)\n"
+    "           && offY>=0 && offY<patW*(patNbY+1)) {\n"
+    "       if((mod(offX,patW*2)<patW && mod(offY,patW*2)<patW) \n"
+    "          || (mod(offX,patW*2)>patW && mod(offY,patW*2)>patW)) {\n"
+    "           color = vec4(0, 0, 0, 1);\n"
+    "       }\n"
+    "   }\n"
+    //color in red the pattern range border
+    "   float thick=2;\n"
+    "   float coordY = viewportHeight-gl_FragCoord.y;\n"
+    "   if(((abs(gl_FragCoord.x-patOffset.x)<thick\n"
+    "               || abs(gl_FragCoord.x-(patOffset.x+patRange.x))<thick)\n"
+    "           && coordY>patOffset.y\n" 
+    "           && coordY<(patOffset.y+patRange.y))\n"
+    "       ||((abs(coordY-patOffset.y)<thick\n"
+    "               || abs(coordY-(patOffset.y+patRange.y))<thick)\n"
+    "           && gl_FragCoord.x>patOffset.x\n" 
+    "           && gl_FragCoord.x<(patOffset.x+patRange.x))) {\n"
+    "       color=vec4(1,0,0,1);\n"
+    "   }\n"
+    "}\n"};
+    m_programs[Reveal::CALIBPROG]
+        = Reveal::getInstance()->createProgram(vertSource, fragSource);
+    m_uniforms[Reveal::CALIBPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
+    m_uniforms[Reveal::CALIBPROG][Reveal::VIEWPORTWIDTH]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"viewportWidth");
+    m_uniforms[Reveal::CALIBPROG][Reveal::VIEWPORTHEIGHT]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"viewportHeight");
+    
+    /*
+    m_uniforms[Reveal::CALIBPROG][Reveal::PATTERNTEX]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patternTex");
+    */
+    
+    
+    m_uniforms[Reveal::CALIBPROG][Reveal::PATW]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patW");
+    m_uniforms[Reveal::CALIBPROG][Reveal::PATPOSX]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patPosX");
+    m_uniforms[Reveal::CALIBPROG][Reveal::PATPOSY]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patPosY");
+    m_uniforms[Reveal::CALIBPROG][Reveal::PATNBX]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patNbX");
+    m_uniforms[Reveal::CALIBPROG][Reveal::PATNBY]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patNbY");
+    m_uniforms[Reveal::CALIBPROG][Reveal::PATRANGE]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patRange");
+    m_uniforms[Reveal::CALIBPROG][Reveal::PATOFFSET]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patOffset");
+    m_uniforms[Reveal::CALIBPROG][Reveal::PATBRIGHT]
+        = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"patBright");
+        
+        
+    m_calibGeom = new QuadGeometry();
+    }
+}
+
+void ProjectorModule::createRTT(GLuint& tex, GLuint& fbo, 
+                                const int& width, const int& height,
+                                bool filter) {
+    glGenTextures(1, &tex);
+    glBindTexture(GL_TEXTURE_2D, tex);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height,
+                 0, GL_RGBA, GL_FLOAT, 0);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
+                    filter?GL_LINEAR:GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+                    filter?GL_LINEAR:GL_NEAREST);
+    glGenFramebuffers(1, &fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0);
+    GLenum drawBuffers[1] = {GL_COLOR_ATTACHMENT0};
+    glDrawBuffers(1, drawBuffers);
+    GLuint idDepthrenderbuffer;
+    glGenRenderbuffers(1, &idDepthrenderbuffer);
+    glBindRenderbuffer(GL_RENDERBUFFER, idDepthrenderbuffer);
+    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT,
+                          width, height);
+    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                              GL_RENDERBUFFER, idDepthrenderbuffer);
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void ProjectorModule::deleteModule() {
+    if(m_space) {
+        m_space->removeProj(this);
+    }
+    glfwDestroyWindow(m_projWindow);
+    Module::deleteModule();
+}
+
+void ProjectorModule::setSpace(SpaceModule* space) {
+    m_space=space;
+}
+
+void ProjectorModule::refreshDepthCamList(const vector<DepthCamModule*> cams) {
+    vector<string> labels;
+    labels.push_back("none");
+    vector<DepthCamModule*>::const_iterator itCam=cams.begin();
+    for(; itCam!=cams.end(); ++itCam) {
+        labels.push_back((*itCam)->getName());
+    }
+    m_attributesMap["attached_to_camera"]
+            ->editStringValuesChoices().assign(1, labels);
+    m_attributesMap["calibrate_with_camera"]
+            ->editStringValuesChoices().assign(1, labels);
+}
+
+void ProjectorModule::attachToCam(const string& camName) {
+    if(m_space) {
+        if(m_attachedToCam) {
+            m_attachedToCam->detachProj(this);
+        }
+        m_attachedToCam = m_space->getDepthCamModule(camName);
+        if(m_attachedToCam) {
+            m_attachedToCam->attachProj(this);
+        }
+    }
+}
+
+void ProjectorModule::setWindowDimensions(const int& x, const int& y,
+                                          const int& w, const int& h) {
+    glfwSetWindowPos(m_projWindow, x, y);
+    glfwSetWindowSize(m_projWindow, w, h);
+    m_width=w;
+    m_height=h;
+}
+
+void ProjectorModule::setWindowDecoration(bool d) {
+    //m_window->setWindowDecoration(d);
+}
+
+void ProjectorModule::fullscreenMonitor(const std::string& monitorName) {
+    int count;
+    GLFWmonitor** monitors = glfwGetMonitors(&count);
+
+    GLFWmonitor* monitor  = NULL;
+    for(int m=0; m<count; ++m) {
+        if(monitorName.compare(glfwGetMonitorName(monitors[m]))==0) {
+            monitor=monitors[m];
+        }
+    }
+
+    int posX=0;
+    int posY=0;
+    m_width=640;
+    m_height=480;
+    if(monitor) {
+        const GLFWvidmode* mode = glfwGetVideoMode(monitor);
+        m_width=mode->width;
+        m_height=mode->height;
+        glfwGetMonitorPos(monitor, &posX, &posY);
+    }
+    m_posX=posX;
+    m_posY=posY;
+    glfwSetWindowMonitor(m_projWindow, monitor, 0, 0,
+                         m_width, m_height, GLFW_DONT_CARE);
+    updateWindowDims();
+    refreshMonitors();
+}
+
+void ProjectorModule::refreshMonitors(){
+    int count;
+    GLFWmonitor** monitors = glfwGetMonitors(&count);
+    vector<string> monitorNames;
+    monitorNames.push_back("windowed");
+    for(int m=0; m<count; ++m) {
+        monitorNames.push_back(glfwGetMonitorName(monitors[m]));
+    }
+    m_attributesMap["fullscreen_monitor"]
+        ->editStringValuesChoices().assign(count, monitorNames);
+}
+
+void ProjectorModule::setViewMatrix(const vector<float>& vals) {
+    m_viewMat = mat4(vals[0], vals[1], vals[2], vals[3],
+                     vals[4], vals[5], vals[6], vals[7],
+                     vals[8], vals[9], vals[10], vals[11],
+                     vals[12], vals[13], vals[14], vals[15]);
+    updateViewProjMatrix();
+}
+
+void ProjectorModule::setProjectionMatrix(const vector<float>& vals) {
+    m_projMat = mat4(vals[0], vals[1], vals[2], vals[3],
+                     vals[4], vals[5], vals[6], vals[7],
+                     vals[8], vals[9], vals[10], vals[11],
+                     vals[12], vals[13], vals[14], vals[15]);
+    updateViewProjMatrix();
+}
+
+void ProjectorModule::updateModelMatrix() {
+    if(!m_attachedToCam) {
+        Module::updateModelMatrix();
+    }
+    updateViewProjMatrix();
+}
+
+void ProjectorModule::setModelMat(const glm::mat4& mat) {
+    Module::setModelMat(mat);
+    updateViewProjMatrix();
+}
+
+void ProjectorModule::updateViewProjMatrix() {
+    m_transViewMat = m_modelMat * inverse(m_viewMat);
+    m_viewProjMat = m_projMat * inverse(m_transViewMat);
+}
+
+void ProjectorModule::setModuleName(const string& name) {
+    Module::setModuleName(name);
+    glfwSetWindowTitle(m_projWindow, name.c_str());
+    if(m_space) {
+        m_space->refreshProjList();
+    }
+}
+
+void ProjectorModule::outputRevealed(bool output) {
+    m_processOutput=output;
+}
+
+void ProjectorModule::postFilter(const int& filt) {
+    m_postFilter=filt;
+}
+
+void ProjectorModule::setTransparentWindow(const bool& transp) {
+    m_transparentBackground=transp;
+}
+
+void ProjectorModule::processOutput() {
+    bool outputProcessed=false;
+
+    //retrieve active revealed modules
+    vector<RevealedModule*>& revModules
+        = Reveal::getInstance()->editRegisteredOutputRevealed();
+    vector<DepthCamModule*>& camModules
+        = Reveal::getInstance()->editRegisteredOutputDepthCams();
+
+    if(revModules.size()>0 || camModules.size()>0) {
+        //retrieve output image
+        glBindTexture(GL_TEXTURE_2D, m_outputTex);
+        glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, 
+                      GL_UNSIGNED_BYTE,
+                      m_outputImg);
+    }
+
+
+    //process shape revealing output
+    if(revModules.size()>0) {
+		m_outNbDepth = m_space->getNbDepthModulesFromID();
+        //get output values for revealed modules with active output
+        vector<RevealedModule*>::iterator itSh = revModules.begin();
+        for(; itSh!=revModules.end(); ++itSh) {
+			//test if shape is visible from this projector
+			if((*itSh)->getVisibilityMask() & m_visibilityMask) {
+				for(int d=1; d<m_outNbDepth+1; ++d) {
+					DepthModule* mod = m_space->getDepthModuleFromID(d);
+					if(mod) {
+						if(mod->isDepthVisible(d)) {
+							(*itSh)->processReveal(d, 
+												   mod->getName(), 
+												   m_outNbDepth,
+												   m_outputImg);
+							outputProcessed=true;
+						}
+					}
+				}
+			}
+        }
+    }
+
+    /*
+    //process cam
+    if(camModules.size()>0) {
+        unsigned int curs;
+        vector<float> pos(3,0);
+        vector<DepthCamModule*>::iterator itCa = camModules.begin();
+        for(; itCa!=camModules.end(); ++itCa) {
+            extractOutputValue((*itCa)->getDepthID()+500, 0, curs);
+            pos[0] = (int(curs) - int(curs/1000)*1000)*10-5000;
+            pos[1] = (int(curs/1000) - int(curs/1000000)*1000)*10-5000;
+            pos[2] = 10000-int(curs/1000000)*10;
+            //cout<<"got cursor "<<curs<<" from cam at pos "
+            //    <<pos[0]<<" "<<pos[1]<<" "<<pos[2]<<endl;
+            (*itCa)->processCursor(pos);
+        }
+        outputProcessed=true;
+    }
+    */
+
+    if(outputProcessed) {
+        //reset output image to 0
+        glBindTexture(GL_TEXTURE_2D, m_outputTex);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
+                     m_outputImgSize, m_outputImgSize, 0,
+                     GL_RGBA, GL_UNSIGNED_BYTE, m_outputImgInit);
+    }
+}
+
+void ProjectorModule::updateWindowSize(const int& w, const int& h) {
+    m_height=h;
+    m_width=w;
+    updateWindowDims();
+}
+
+void ProjectorModule::updateWindowPos(const int& x, const int& y) {
+    m_posX=x;
+    m_posY=y;
+    updateWindowDims();
+}
+
+void ProjectorModule::updateWindowDims() {
+    vector<int> dims(4,0);
+    dims[0]=m_posX;
+    dims[1]=m_posY;
+    dims[2]=m_width;
+    dims[3]=m_height;
+    m_attributesMap["window_dimensions"]->initInts(dims);
+    m_patternPosRange = Size(m_width, m_height);
+}
+
+//-------------------------Calibration----------------------------------
+
+/*
+static void cbPatternSquareWidth(int w, void* mod) {
+    if(w>10) {
+        ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
+        proj->setPatternSquareWidth(w);
+    }
+}*/
+
+void ProjectorModule::setPatternSquareWidth(const int& w) {
+    m_patternSquareWidth=w;
+    updateCalibrationPattern();
+}
+
+static void cbPatternPosOX(int x, void* mod) {
+    ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
+    proj->setPatternPosOX(x);
+}
+
+void ProjectorModule::setPatternPosOX(const int& x) {
+    m_patternPosOffset.width=x;
+    updateCalibrationPattern();
+}
+
+static void cbPatternPosOY(int y, void* mod) {
+    ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
+    proj->setPatternPosOY(y);
+}
+
+void ProjectorModule::setPatternPosOY(const int& y) {
+    m_patternPosOffset.height=y;
+    updateCalibrationPattern();
+}
+
+static void cbPatternPosRX(int x, void* mod) {
+    ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
+    proj->setPatternPosRX(x);
+}
+
+void ProjectorModule::setPatternPosRX(const int& x) {
+    m_patternPosRange.width=x;
+    updateCalibrationPattern();
+}
+
+static void cbPatternPosRY(int y, void* mod) {
+    ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
+    proj->setPatternPosRY(y);
+}
+
+void ProjectorModule::setPatternPosRY(const int& y) {
+    m_patternPosRange.height=y;
+    updateCalibrationPattern();
+}
+
+static void cbCalib(int c, void* mod) {
+    ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
+    proj->setCalib(c);
+}
+
+void ProjectorModule::setCalib(const int& c) {
+    if(m_calibrating==1 && c==0) {
+        m_calibrationStopped=true;
+    }
+    m_calibrating=c;
+}
+
+static void cbPatternBrightness(int b, void* mod) {
+    ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
+    proj->setPatternBrightness(b);
+}
+
+void ProjectorModule::setPatternBrightness(const int& b) {
+    m_patternBrightness=b;
+}
+
+void ProjectorModule::updateCalibrationPattern() {
+    m_generatedCorners.clear();
+    for(int j=1; j<m_patternSize.height+1; ++j) {
+        for(int i=1; i<m_patternSize.width+1; ++i) {
+            int cornerX=m_patternSquareWidth*i+m_patternPosition.width;
+            int cornerY=m_patternSquareWidth*j+m_patternPosition.height;
+            m_generatedCorners.push_back(Point2f(cornerX, cornerY));
+        }
+    }
+}
+
+void ProjectorModule::calibrate(const std::string& camName) {
+    //get depth camera module and activate color image
+    DepthCamModule* cam = NULL;
+    if(m_space) {
+        cam = m_space->getDepthCamModule(camName);
+    }
+    if(cam==NULL) {
+        cout<<"No camera attached to projector"<<endl;
+        return;
+    }
+
+    //close cam and reopen in calibration mode
+    cam->closeDevice();
+    cam->openDevice(cam->getDeviceID(), true);
+
+    //check cam is open
+    if(!cam->isOpen()) {
+        cout<<"Camera "<<cam->getName()<<"is not open"<<endl;
+        return;
+    }
+
+    cout<<"Calibrating projector ..."<<endl;
+
+    //create opencv windows, trackbars and initialize variables
+    m_imageSize = cv::Size(640 ,480); //fixme, get from cam color image size
+    m_calibrating=0;
+    m_calibrationStopped=false;
+    m_neededFramesNb=9;
+    cv::Mat kinectRgbImg = Mat::zeros(m_imageSize, CV_8UC3);
+    namedWindow("DepthCamRGB");
+    namedWindow("Controls");
+    createTrackbar("Pattern Offset X", "Controls",
+                    &m_patternPosOffset.width, 1000, cbPatternPosOX, this);
+    createTrackbar("Pattern Offset Y", "Controls",
+                    &m_patternPosOffset.height, 500, cbPatternPosOY, this);
+    createTrackbar("Pattern Range X", "Controls",
+                    &m_patternPosRange.width, 1920, cbPatternPosRX, this);
+    createTrackbar("Pattern Range Y", "Controls",
+                    &m_patternPosRange.height, 1080, cbPatternPosRY, this);
+    createTrackbar("Pattern Brightness", "Controls",
+                    &m_patternBrightness, 100, cbPatternBrightness, this);
+    createTrackbar("Calibrate (1:Start, 0:Cancel)", "Controls",
+                    NULL, 1, cbCalib, this);
+    vector<vector<Point3f> > objectPoints;
+    vector<vector<Point2f> > imagePoints;
+    Mat cameraMatrix = Mat::eye(3, 3, CV_64F);
+    Mat distCoeffs = Mat::zeros(8, 1, CV_64F);
+    vector<Mat> rvecs;
+    vector<Mat> tvecs;
+
+    cam->activateColor();
+    for(int f=0; f<m_neededFramesNb && !m_calibrationStopped;) {
+        //update pattern position
+        m_patternSquareWidth = m_height/20;
+
+        m_patternPosition.width = (m_patternPosRange.width-m_patternSquareWidth)
+                                        / sqrt(m_neededFramesNb)
+                                    *(fmod(f,sqrt(m_neededFramesNb)))
+                                  +m_patternSquareWidth
+                                  +m_patternPosOffset.width;
+
+        m_patternPosition.height=(m_patternPosRange.height-m_patternSquareWidth)
+                                        / sqrt(m_neededFramesNb)
+                                    *(floor(f/sqrt(m_neededFramesNb)))
+                                  +m_patternSquareWidth
+                                  +m_patternPosOffset.height;
+        updateCalibrationPattern();
+
+        //display frame with calibration pattern
+        glfwMakeContextCurrent(m_projWindow);
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        glViewport(0, 0, m_width, m_height);
+        glDisable(GL_CULL_FACE);
+        glClearColor(0.0, 0.0, 0.0, 1.0);
+        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+        glUseProgram(m_programs[Reveal::CALIBPROG]);
+        glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::VIEWPORTWIDTH],
+                    m_width);
+        glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::VIEWPORTHEIGHT],
+                    m_height);
+        glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATW],
+                    m_patternSquareWidth);
+        glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATPOSX],
+                    m_patternPosition.width);
+        glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATPOSY],
+                    m_patternPosition.height);
+        glUniform2f(m_uniforms[Reveal::CALIBPROG][Reveal::PATOFFSET],
+                    m_patternPosOffset.width, m_patternPosOffset.height);
+        glUniform2f(m_uniforms[Reveal::CALIBPROG][Reveal::PATRANGE],
+                    m_patternPosRange.width, m_patternPosRange.height);
+        glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATNBX],
+                    m_patternSize.width);
+        glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATNBY],
+                    m_patternSize.height);
+        glUniform1f(m_uniforms[Reveal::CALIBPROG][Reveal::PATBRIGHT],
+                    float(m_patternBrightness)/100.0);
+        m_calibGeom->drawDirect(m_contextHandlerID);
+        glfwSwapBuffers(m_projWindow);
+
+        waitKey(10);
+        sleep(1);
+
+        //grab frame
+        if(cam->getFrames()) {
+            openni::VideoFrameRef depthFrame = cam->getDepthFrame();
+            openni::VideoFrameRef colorFrame = cam->getColorFrame();
+
+            //copy to opencv mat
+            for(int j=0; j<m_imageSize.height; ++j) {
+                for(int i=0; i<m_imageSize.width; ++i) {
+                    cv::Vec3b& pix = kinectRgbImg.at<cv::Vec3b>(j,i);
+                    int coord=0;
+					coord=j*m_imageSize.width+i;
+                    openni::RGB888Pixel colorPix =
+                        ((openni::RGB888Pixel*) colorFrame.getData())[coord];
+                    pix[0]=colorPix.r;
+                    pix[1]=colorPix.g;
+                    pix[2]=colorPix.b;
+                }
+            }
+
+
+            imshow("DepthCamRGB", kinectRgbImg);
+            if(m_calibrating) {
+                m_foundCorners.clear();
+                //find chessboard in image
+                bool patternFound = findChessboardCorners(
+                                                  kinectRgbImg,
+                                                  m_patternSize,
+                                                  m_foundCorners,
+                                                  CALIB_CB_ADAPTIVE_THRESH);
+                //if we found it
+                if(patternFound) {
+                    //refine
+                    Mat gray;
+                    cvtColor(kinectRgbImg, gray, COLOR_RGB2GRAY);
+                    cornerSubPix(gray, m_foundCorners,
+                             cv::Size(1, 1), cv::Size(-1, -1),
+                             TermCriteria(TermCriteria::EPS,
+                                          30, 0.1));
+
+
+                    bool validDepths=true;
+                    //retrieve the corresponding position and depth
+                    vector<Point3f> worldCorners;
+                    vector<Point2f>::iterator itPnt=m_foundCorners.begin();
+                    for(; itPnt!=m_foundCorners.end(); ++itPnt) {
+                        float posX, posY, posZ;
+						Point2f coord = Point2f((*itPnt).x,(*itPnt).y);
+						Point2f depthCoord = coord;
+
+                        openni::DepthPixel depthPix =
+                            ((openni::DepthPixel*)depthFrame.getData())[int(
+                                    depthCoord.y*m_imageSize.width +
+                                    depthCoord.x)];
+                        posZ=depthPix;
+
+                        //filter the depth
+                        int size=6;
+                        vector<double> vals;
+                        for(int x=depthCoord.x-size/2;
+                                    x<depthCoord.x+size/2; ++x) {
+                            for(int y=depthCoord.y-size/2;
+                                    y<depthCoord.y+size/2; ++y) {
+                                if(x>=0 && x<m_imageSize.width &&
+                                        y>=0 && y<m_imageSize.height) {
+                                    vals.push_back(
+                                    ((openni::DepthPixel*)depthFrame.getData())
+                                        [int(y*m_imageSize.width + x)]);
+                                }
+                            }
+                        }
+                        sort(vals.begin(), vals.end());
+                        posZ=vals[vals.size()/2];
+                        depthPix=posZ;
+
+                        openni::CoordinateConverter::convertDepthToWorld(
+                                                    cam->getDepthStream(),
+                                                    int(depthCoord.x),
+                                                    int(depthCoord.y),
+                                                    depthPix,
+                                                    &posX, &posY, &posZ);
+                        //if(reversed) {
+                        //    posX=-posX;
+                        //    posY=-posY;
+                        //}
+                        if(posZ<=500.0 || posZ>4000.0) {
+                            validDepths=false;
+                        }
+                        else {
+                            worldCorners.push_back(Point3f(posX, posY, posZ));
+                        }
+                    }
+
+                    //if everything is valid
+                    if(validDepths) {
+                        cout<<"Pattern found "<<f<<"/"<<m_neededFramesNb<<endl;
+                        //add the generated corners
+                        imagePoints.push_back(m_generatedCorners);
+                        cout<<m_generatedCorners[0]<<endl;
+                        //add the detected world corners
+                        objectPoints.push_back(worldCorners);
+                        cout<<worldCorners[0]<<endl;
+
+                        //cout<<m_generatedCorners<<endl;
+                        //cout<<worldCorners<<endl;
+
+                        //draw corners
+                        drawChessboardCorners(kinectRgbImg, m_patternSize,
+                                              m_foundCorners, patternFound);
+
+
+                        imshow("DepthCamRGB", kinectRgbImg);
+                        waitKey(10);
+
+                        //wait
+                        #ifdef POSIX
+                            sleep(1);
+                        #else
+                            Sleep(1000);
+                        #endif
+
+                        //increase frame count
+                        ++f;
+                     }
+                }
+            }
+            waitKey(10);
+        }
+    }
+
+    double rms=0;
+
+    if(objectPoints.size()>0) {
+
+        //put the image and object points in the right order for opencv
+        vector<vector<Point3f> > vvo(1); //object points
+        vector<vector<Point2f> > vvi(1); //image points
+        for (unsigned int i=0; i<objectPoints.size(); ++i) {
+            for (unsigned int j = 0; j<objectPoints[i].size(); j++) {
+                vvo[0].push_back(objectPoints[i][j]);
+                vvi[0].push_back(imagePoints[i][j]);
+            }
+        }
+
+        //when enough points found, get the extrinsics/intrisics parameter
+        float w = m_width;
+        float h = m_height;
+        cameraMatrix = (Mat1d(3, 3) <<  w, 0, w/2.,
+                                        0, h, h / 2.,
+                                        0, 0, 1);
+        distCoeffs = Mat::zeros(8, 1, CV_64F);
+        rms=calibrateCamera(vvo, vvi,
+                               Size(w, h), cameraMatrix,
+                               distCoeffs, rvecs, tvecs,
+                               CALIB_FIX_K1+
+                               CALIB_FIX_K2+
+                               CALIB_FIX_K3+
+                               CALIB_FIX_K4+
+                               CALIB_FIX_K5+
+                               CALIB_FIX_K6+
+                               CALIB_ZERO_TANGENT_DIST+
+                               CALIB_USE_INTRINSIC_GUESS);
+
+        cout<<"... done , RMS="<<rms<<endl;
+
+        //Build the opengl view matrix
+        Mat rot;
+        rvecs[0].copyTo(rot);
+        Mat rotMat = Mat::zeros(3, 3, CV_64F);
+        Rodrigues(rot, rotMat);
+
+        mat4 viewMatrix(rotMat.at<double>(0,0), rotMat.at<double>(1,0),
+                            rotMat.at<double>(2,0), 0,
+                        rotMat.at<double>(0,1), rotMat.at<double>(1,1),
+                            rotMat.at<double>(2,1), 0,
+                        rotMat.at<double>(0,2), rotMat.at<double>(1,2),
+                            rotMat.at<double>(2,2), 0,
+                        tvecs[0].at<double>(0,0), tvecs[0].at<double>(1,0),
+                            tvecs[0].at<double>(2,0), 1);
+
+        mat4 glCoordsMat(-1, 0, 0, 0,
+                          0, 1, 0, 0,
+                          0, 0, 1, 0,
+                          0, 0, 0, 1);
+        m_viewMat=glCoordsMat*viewMatrix;
+
+        m_attributesMap["view_matrix"]->setFloats(
+                                            vector<float>(
+                                               value_ptr(m_viewMat),
+                                               value_ptr(m_viewMat)+16));
+        //build the opengl projection matrix
+        double fx=cameraMatrix.at<double>(0,0);
+        double cx=cameraMatrix.at<double>(0,2);
+        double fy=cameraMatrix.at<double>(1,1);
+        double cy=cameraMatrix.at<double>(1,2);
+        double l=0;
+        double r=w;
+        double b=h;
+        double t=0;
+        double n=100;
+        double f=10000;
+        mat4 projMatrix(
+                2.0*fx/w,       0,                      0,              0,
+                0,              2.0*fy/h,               0,              0,
+                1.0-2.0*(cx)/w,-1.0+(2.0*(cy)+2.0)/h,   (f+n)/(n-f),    -1,
+                0,              0,                      (2.0*f*n)/(n-f), 0);
+        m_attributesMap["projection_matrix"]->setFloats(
+                    vector<float>(value_ptr(projMatrix),
+                                  value_ptr(projMatrix)+16));
+        m_attributesMap["attached_to_camera"]
+            ->setStrings(vector<string>(1, cam->getName()));
+    }
+
+    ostringstream oss;
+    oss<<rms;
+
+    cv::Mat reconstructionImg = Mat::zeros(Size(m_width, m_height), CV_8UC3);
+
+    //project reconstructed kinect
+    while(!m_calibrationStopped) {
+        if(cam->getFrames()) {
+            openni::VideoFrameRef depthFrame = cam->getDepthFrame();
+            openni::VideoFrameRef colorFrame = cam->getColorFrame();
+
+            //get points from the kinect and their actual 3D positions
+            reconstructionImg.setTo(cv::Vec3b(0,0,0));
+            vector<Point3f> objPnts;
+            vector<cv::Vec3b> kinPnts;
+            vector<Point2f> imgPnts;
+            for(int j=0; j<m_imageSize.height; ++j) {
+                for(int i=0; i<m_imageSize.width; ++i) {
+                    float posX, posY, posZ;
+                    int coord = m_imageSize.width*j+i;
+                    openni::DepthPixel depthPix =
+                        ((openni::DepthPixel*)depthFrame.getData())[coord];
+                    openni::CoordinateConverter::convertDepthToWorld(
+                                                        cam->getDepthStream(),
+                                                        i, j, depthPix,
+                                                        &posX, &posY, &posZ);
+                    objPnts.push_back(Point3f(posX,posY,posZ));
+                    const openni::RGB888Pixel& colorPix =
+                        ((openni::RGB888Pixel*) colorFrame.getData())[coord];
+                    kinPnts.push_back(cv::Vec3b(colorPix.r,
+                                            colorPix.g,
+                                            colorPix.b));
+                }
+            }
+            projectPoints(objPnts, rvecs[0], tvecs[0],
+                          cameraMatrix, distCoeffs, imgPnts);
+
+            //for each of the image points
+            vector<Point2f>::iterator itPnt=imgPnts.begin();
+            vector<cv::Vec3b>::iterator itKin=kinPnts.begin();
+            vector<Point3f>::iterator itObj=objPnts.begin();
+            for(; itPnt!=imgPnts.end() && itKin!=kinPnts.end();
+                    ++itPnt, ++itKin, ++itObj) {
+                if((*itPnt).x<reconstructionImg.cols &&
+                        (*itPnt).y<reconstructionImg.rows &&
+                        (*itPnt).x>0 &&
+                        (*itPnt).y>0) {
+                    reconstructionImg.at<cv::Vec3b>(
+                                    (*itPnt).y,
+                                    (*itPnt).x)
+                        =(*itKin);
+                }
+            }
+
+            putText(reconstructionImg, "RMS="+oss.str(), Point(0,50), 
+                    cv::FONT_HERSHEY_SIMPLEX, 2, 
+                    Scalar(255, 255, 255));
+            imshow( "DepthCamRGB", reconstructionImg);
+        }
+        waitKey(10);
+    }
+
+    //close opencv windows
+    destroyWindow("DepthCamRGB");
+    destroyWindow("Controls");
+    waitKey(10);
+
+    //reopen cam in normal mode
+    cam->closeDevice();
+    cam->openDevice(cam->getDeviceID());
+}
+
+void ProjectorModule::calibrateCamWithMarker(const std::string& camName) {
+
+
+
+}
+
diff --git a/src/modules/ProjectorModule.hpp b/src/modules/ProjectorModule.hpp
new file mode 100644
index 0000000..3cbdf06
--- /dev/null
+++ b/src/modules/ProjectorModule.hpp
@@ -0,0 +1,227 @@
+/***************************************************************************
+ *  ProjectorModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef ProjectorModule_h
+#define ProjectorModule_h
+
+#include "GroupModule.hpp"
+#include <iostream>
+#include <pthread.h>
+
+#include "opencv2/highgui/highgui.hpp"
+#include "opencv2/calib3d/calib3d.hpp"
+
+#include "../geoms/QuadGeometry.hpp"
+
+#include "../Reveal.hpp"
+
+class SpaceModule;
+class DepthCamModule;
+
+class ProjectorModule : public Module, public ContextHandler {
+    public:
+        ProjectorModule();
+        virtual ~ProjectorModule();
+        virtual void draw();
+        void deleteModule();
+
+        static void activeCallback(Module* mod, 
+                                           const std::vector<bool>& vals) {
+            static_cast<ProjectorModule*>(mod)->setActive(vals[0]);
+        }
+        inline void setActive(bool active) {m_active=active;}
+        static void calibrateCallback(Module* mod, 
+                                        const std::vector<std::string>& vals) {
+            static_cast<ProjectorModule*>(mod)->calibrate(vals[0]);
+        }
+        void calibrate(const std::string& camName);
+        void calibrateCamWithMarker(const std::string& camName);
+        static void windowDimensionsCallback(Module* mod, 
+                                             const std::vector<int>& vals) {
+            static_cast<ProjectorModule*>(mod)->setWindowDimensions(vals[0],
+                                                                    vals[1],
+                                                                    vals[2],
+                                                                    vals[3]);
+        }
+        void setWindowDimensions(const int& x, const int& y, 
+                                 const int& w, const int& h);
+        static void windowSizeCallback(GLFWwindow* win, int w, int h) {
+            static_cast<ProjectorModule*>(glfwGetWindowUserPointer(win)) 
+                            ->updateWindowSize(w, h);
+        }
+        static void framebufferSizeCallback(GLFWwindow* win, int w, int h) {
+            static_cast<ProjectorModule*>(glfwGetWindowUserPointer(win)) 
+                            ->updateWindowSize(w, h);
+        }
+        void updateWindowSize(const int& w, const int& h);
+        static void windowPositionCallback(GLFWwindow* win, int x, int y) {
+            static_cast<ProjectorModule*>(glfwGetWindowUserPointer(win)) 
+                            ->updateWindowPos(x, y);
+        }
+        void updateWindowPos(const int& x, const int& y);
+        void updateWindowDims();
+
+        static void windowDecorationCallback(Module* mod, 
+                                             const std::vector<bool>& vals) {
+            static_cast<ProjectorModule*>(mod)->setWindowDecoration(vals[0]);
+        }
+        void setWindowDecoration(bool d);
+        static void fullscreenMonitorCallback(Module* mod, 
+                                        const std::vector<std::string>& vals) {
+            static_cast<ProjectorModule*>(mod)->fullscreenMonitor(vals[0]);
+        }
+        void fullscreenMonitor(const std::string& monitor);
+        static void viewMatrixCallback(Module* mod, 
+                                             const std::vector<float>& vals) {
+            static_cast<ProjectorModule*>(mod)->setViewMatrix(vals);
+        }
+        void setViewMatrix(const std::vector<float>& vals);
+        static void projectionMatrixCallback(Module* mod, 
+                                             const std::vector<float>& vals) {
+            static_cast<ProjectorModule*>(mod)->setProjectionMatrix(vals);
+        }
+        void setProjectionMatrix(const std::vector<float>& vals);
+        static void attachToCamCallback(Module* mod, 
+                                        const std::vector<std::string>& vals) {
+            static_cast<ProjectorModule*>(mod)->attachToCam(vals[0]);
+        }
+        void attachToCam(const std::string& camName);
+        static void outputRevealedCallback(Module* mod, 
+                                           const std::vector<bool>& vals) {
+            static_cast<ProjectorModule*>(mod)->outputRevealed(vals[0]);
+        }
+        void outputRevealed(bool output);
+        static void mirroredCallback(Module* mod, 
+                                     const std::vector<bool>& vals) {
+            static_cast<ProjectorModule*>(mod)->setMirrored(vals[0]);
+        }
+        inline void setMirrored(bool m){m_mirrored=m;}
+
+        static void postFilterCallback(Module* mod, 
+                                        const std::vector<int>& vals) {
+            static_cast<ProjectorModule*>(mod)->postFilter(vals[0]);
+        }
+        void postFilter(const int& filt);
+
+        static void transparentWindowCallback(Module* mod, 
+                                        const std::vector<bool>& vals) {
+            static_cast<ProjectorModule*>(mod)->setTransparentWindow(vals[0]);
+        }
+        void setTransparentWindow(const bool& transp);
+
+
+        void setPatternSquareWidth(const int&);
+        void setPatternPosOX(const int&);
+        void setPatternPosOY(const int&);
+        void setPatternPosRX(const int&);
+        void setPatternPosRY(const int&);
+        void setPatternPositionY(const int&);
+        void setPatternBrightness(const int&);
+        void setCalib(const int&);
+        void setModuleName(const std::string&);
+
+		inline const bool& getMirrored(){return m_mirrored;}
+
+        void setSpace(SpaceModule* space);
+        virtual void setModelMat(const glm::mat4& mat);
+        void updateModelMatrix();
+        void updateViewProjMatrix();
+        inline void setProjID(const int& id){m_projID=id;}
+        inline const int& getProjID(){return m_projID;}
+
+        void refreshMonitors();
+
+        void refreshDepthCamList(const std::vector<DepthCamModule*>);
+        void processOutput();
+
+    private:
+        void initGL();
+        void createRTT(GLuint& tex, GLuint& fbo, 
+                        const int& width, const int& height, bool filter);
+
+        void updateCalibrationPattern();
+
+
+    private:
+        int m_projID;
+        GLFWwindow* m_projWindow;
+        SpaceModule* m_space;
+        DepthCamModule* m_attachedToCam;
+        DepthCamModule* m_calibrationCam;
+        glm::mat4 m_transViewMat;
+        bool m_initialized;
+        bool m_mirrored;
+        bool m_active;
+        GLuint m_selectTex;
+        GLuint m_selectFBO;
+        GLuint m_sliceTex;
+        GLuint m_sliceRttTex;
+        GLuint m_sliceSmpTex;
+        GLuint m_sliceFBO;
+        GLuint m_renderTex;
+        GLuint m_renderFBO;
+        float m_posX, m_posY;
+        int m_rttWidth, m_rttHeight;
+        bool m_processOutput;
+        float m_postFilter;
+		bool m_transparentBackground;
+
+        QuadGeometry* m_calibGeom;
+
+        //calibration
+        cv::Mat m_projectedImg;
+        std::vector<cv::Point2f> m_foundCorners;
+        cv::Size m_patternSize;
+        int m_patternSquareWidth; 
+        int m_patternThresh;
+        cv::Size m_patternPosOffset;
+        cv::Size m_patternPosRange;
+        cv::Size m_patternPosition; 
+        int m_neededFramesNb;
+        std::vector<cv::Point2f> m_generatedCorners;
+        bool m_calibrated;
+        int m_calibrating;
+        int m_patternBrightness;
+        bool m_calibrationStopped;
+        cv::Size m_imageSize;
+
+        //shader/programs
+        std::map<Reveal::REVIL_PROGRAM, GLint> m_programs;
+        std::map<Reveal::REVIL_PROGRAM, 
+                 std::map<Reveal::REVIL_UNIFORM, GLint> > m_uniforms;
+
+        //output
+        GLuint m_outputTex;
+        static const unsigned int m_outputImgSize=500;
+        unsigned int* m_outputImg;
+        unsigned int* m_outputImgInit;
+        int m_outShapeSize;
+        int m_outVoxelSize;
+        int m_outHistoSize;
+        int m_outDepthSize;
+        int m_outNbDepth;
+};
+
+
+#endif
+
diff --git a/src/modules/RevealedArrowModule.cpp b/src/modules/RevealedArrowModule.cpp
new file mode 100644
index 0000000..32d96e2
--- /dev/null
+++ b/src/modules/RevealedArrowModule.cpp
@@ -0,0 +1,348 @@
+/***************************************************************************
+ *  RevealedArrowModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "RevealedArrowModule.hpp" 
+
+#include "../geoms/Geometry.hpp"
+
+#include <glm/gtx/matrix_decompose.hpp>
+#include <glm/gtx/quaternion.hpp>
+#include <glm/gtx/polar_coordinates.hpp>
+#include <glm/gtx/rotate_vector.hpp>
+#include <glm/gtx/euler_angles.hpp> 
+
+using namespace std;
+
+RevealedArrowModule::RevealedArrowModule(): GroupModule()  {
+    m_type="Arrow";
+    m_name="arrow";
+    addNameAttribute();
+    addRemoveAttribute();
+    addVisibleAttribute();
+    addVisibleFromAttribute();
+
+    addAttribute(new Attribute("origin_module", 
+                                Attribute::STRING_ATTRIBUTE,
+                                originModuleCallback, this, 1));
+    addAttribute(new Attribute("origin_offset", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                originOffsetCallback, this, 3));
+    addAttribute(new Attribute("destination_module", 
+                                Attribute::STRING_ATTRIBUTE,
+                                destinationModuleCallback, this, 1));
+    addAttribute(new Attribute("destination_offset", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                destinationOffsetCallback, this, 3));
+    addAttribute(new Attribute("elements_number", 
+                                Attribute::INT_ATTRIBUTE,
+                                elementsNumberCallback, this, 1));
+    addAttribute(new Attribute("elements_speed", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                elementsSpeedCallback, this, 1));
+    addAttribute(new Attribute("elements_thickness", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                elementsThicknessCallback, this, 1));
+    addAttribute(new Attribute("elements_direction", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                elementsDirectionCallback, this, 3));
+    addAttribute(new Attribute("follow_direction", 
+                                Attribute::BOOL_ATTRIBUTE,
+                                followDirectionCallback, this, 1));
+
+    addAttribute(new Attribute("revealed_elements", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                elementsRevealedCallback, this, 1));
+    m_revAttributes.push_back(m_attributesMap["revealed_elements"]);
+
+    m_thickness=0.5;
+    m_followDirection=false;
+    m_origPnt = new ArrowPoint(this);
+    m_destPnt = new ArrowPoint(this);
+    
+    m_nbElements=0;
+    m_attributesMap["elements_number"]->setInts(vector<int>(1, 10));
+    m_attributesMap["elements_thickness"]->setFloats(vector<float>(1, 0.2));
+    m_attributesMap["elements_speed"]->setFloats(vector<float>(1, 5));
+    vector<float> dir(3,0);
+    dir[2]=-1;
+    m_attributesMap["elements_direction"]->setFloats(dir);
+    m_distance=0;
+
+    m_attributesMap["origin_offset"]->setFloats(vector<float>(3,0));
+    m_attributesMap["destination_offset"]->setFloats(vector<float>(3,0));
+
+    m_revealed.push_back(0);
+    m_revealedChanged=false;
+
+    Reveal::getInstance()->addModuleListObserver(this);
+    Reveal::getInstance()->addUpdateObserver(this);
+}
+
+RevealedArrowModule::~RevealedArrowModule() {
+}
+
+void RevealedArrowModule::deleteModule() {
+    GroupModule::deleteModule();
+    for(int i=0; i<m_nbElements; ++i) {
+        m_elements[i]->deleteModule();
+    }
+}
+
+void RevealedArrowModule::draw() {
+}
+
+void RevealedArrowModule::setVisible(bool vis) {
+    GroupModule::setVisible(vis);
+    for(int i=0; i<m_nbElements; ++i) {
+        m_elements[i]->setParentVisible(m_parentVisible&&m_visible);
+    }
+}
+
+void RevealedArrowModule::setOriginModule(const std::string& moduleStr) {
+    Module* mod = NULL;
+    mod = Reveal::getInstance()->findModule(moduleStr);
+    m_origModStr=moduleStr;
+    if(mod) {
+        m_origPnt->setModule(mod);
+        mod->getAttribute("absolute_position")->addListener(m_origPnt);
+    }
+    updateArrowPoints();
+}
+
+void RevealedArrowModule::setOriginOffset(const float& x, 
+                                          const float& y,
+                                          const float& z) {
+    m_originOffset[0]=x;
+    m_originOffset[1]=y;
+    m_originOffset[2]=z;
+    updateArrowPoints();
+}
+
+void RevealedArrowModule::setDestinationModule(const std::string& moduleStr) {
+    Module* mod = NULL;
+    mod = Reveal::getInstance()->findModule(moduleStr);
+    m_destModStr=moduleStr;
+    if(mod) {
+        m_destPnt->setModule(mod);
+        mod->getAttribute("absolute_position")->addListener(m_destPnt);
+    }
+    updateArrowPoints();
+}
+
+void RevealedArrowModule::setDestinationOffset(const float& x, 
+                                               const float& y,
+                                               const float& z) {
+    m_destOffset[0]=x;
+    m_destOffset[1]=y;
+    m_destOffset[2]=z;
+    updateArrowPoints();
+}
+
+void RevealedArrowModule::setElementsNumber(const int& nb) {
+    if(nb>0) {
+        if(nb>m_nbElements) {
+            for(int i=m_nbElements; i<nb; ++i) {
+                m_elements.push_back(new ArrowElementModule(m_elements.size(),
+							    this));
+                m_elements.back()->setShape("cone");
+                m_elements.back()->setSurfaceThickness(5);
+                m_elements.back()->setInsideVisible(false);
+                m_elements.back()->setGradientType("along_y");
+                m_positions.push_back(0);
+            }
+        }
+        m_nbElements=nb;
+        for(int i=0; i<m_nbElements; ++i) {
+            m_elements[i]->setVisible(true);
+        }
+        for(unsigned int i=m_nbElements; i<m_elements.size(); ++i) {
+            m_elements[i]->setVisible(false);
+        }
+        updateArrowPoints();
+    }
+}
+
+void RevealedArrowModule::setElementsSpeed(const float& sp) {
+    if(sp>=0) {
+        m_speed=sp/1000;
+        updateArrowPoints();
+    }
+}
+
+void RevealedArrowModule::setThickness(const float& th) {
+    if(th>0) {
+        m_thickness=th;
+        updateArrowPoints();
+    }
+}
+
+void RevealedArrowModule::setElementsDirection(const float& x, 
+                                              const float& y,
+                                              const float& z) {
+    m_elementsDirection[0]=x;
+    m_elementsDirection[1]=y;
+    m_elementsDirection[2]=z;
+    updateArrowPoints();
+}
+
+void RevealedArrowModule::setFollowDirection(bool f) {
+    m_followDirection=f;
+    updateArrowPoints();
+}
+
+void RevealedArrowModule::update(const int& timeDiffMs) {
+  if(m_visible) {
+    if(m_speed>0) {
+        for(int i=0; i<m_nbElements; ++i) {
+            m_positions[i]=fmod(m_positions[i]+m_speed,1);
+            float pos = m_positions[i]*m_distance;
+            m_elements[i]->setPosition(m_origin[0]+m_dir[0]*pos,
+                                       m_origin[1]+m_dir[1]*pos,
+                                       m_origin[2]+m_dir[2]*pos);
+        }
+    }
+    if(m_revealedChanged) {
+      m_revealed[0]=0;
+      for(int i=0; i<m_nbElements; ++i) {
+        if(m_elements[i]->isRevealed()>0) {
+          m_revealed[0]=1;
+        }
+      }
+      m_attributesMap["revealed_elements"]->setFloatsIfChanged(m_revealed);
+      m_revealedChanged=false;
+    }
+  }
+}
+
+
+void RevealedArrowModule::updateModulesList(const map<string, Module*>& mods) {
+    vector<vector<string> >& oriModNames = m_attributesMap["origin_module"]
+                                                ->editStringValuesChoices();
+    vector<vector<string> >& desModNames = m_attributesMap["destination_module"]
+                                                ->editStringValuesChoices();
+    oriModNames.clear();
+    desModNames.clear();
+    oriModNames.push_back(vector<string>());
+    desModNames.push_back(vector<string>());
+    map<string, Module*>::const_iterator itMod = mods.begin();
+    for(; itMod!=mods.end(); ++itMod) { //select names from scene modules
+        if(itMod->first.find("/revil/scene/")==0 
+                && itMod->first.compare(m_fullName)!=0) {
+            oriModNames[0].push_back(itMod->first);
+            desModNames[0].push_back(itMod->first);
+        }
+    }
+    setOriginModule(m_origModStr);
+    setDestinationModule(m_destModStr);
+}
+
+void RevealedArrowModule::updateArrowPoints() {
+    if(m_origPnt->getModule()!=NULL 
+            && m_destPnt->getModule()!=NULL) {
+
+        const vector<float>& floatValues1 
+        =m_origPnt->getModule()->getAttribute("absolute_position")->getFloats();
+        for(int i=0; i<3; ++i) {
+            m_origin[i]=floatValues1[i]+m_originOffset[i];
+        }
+
+        const vector<float>& floatValues2 
+        =m_destPnt->getModule()->getAttribute("absolute_position")->getFloats();
+        for(int i=0; i<3; ++i) {
+            m_dest[i]=floatValues2[i]+m_destOffset[i];
+        }
+
+        m_dir = m_dest - m_origin;
+        m_distance=length(m_dir);
+        m_dir = glm::normalize(m_dir);
+
+        glm::quat q;
+        glm::vec3 up(0,1,0);
+        getQuatFromTwoVecs(q, up, m_dir);
+        //glm::vec3 e = glm::eulerAngles(q);
+        for(int i=0; i<m_nbElements; ++i) {
+            m_positions[i]=(float(i)+0.5)/float(m_nbElements);
+            float pos = m_positions[i]*m_distance;
+            m_elements[i]->setPosition(m_origin[0]+m_dir[0]*pos,
+                                       m_origin[1]+m_dir[1]*pos,
+                                       m_origin[2]+m_dir[2]*pos);
+            if(m_followDirection) {
+                m_elements[i]->setQuaternion(q[0],q[1],q[2],q[3]);
+                m_elements[i]->setScale(m_thickness,
+                                        (m_distance/float(m_nbElements))/200,
+                                        m_thickness);
+            }
+            else {
+                glm::quat q2;
+                getQuatFromTwoVecs(q2, up, m_elementsDirection);
+                m_elements[i]->setQuaternion(q2[0],q2[1],q2[2],q2[3]);
+                m_elements[i]->setScale((m_distance/float(m_nbElements))/200,
+                                        m_thickness,
+                                        (m_distance/float(m_nbElements))/200);
+            }
+        }
+    }
+}
+
+void RevealedArrowModule::gotAttributeListenersUpdate(Attribute* att) {
+    bool active=false;
+    vector<Attribute*>::iterator itAtt = m_revAttributes.begin();
+    for(; itAtt!=m_revAttributes.end(); ++itAtt) {
+        if((*itAtt)->editListeners().size()>0) {
+            active=true;
+        }
+    } 
+    if(active) {
+      for(int i=0; i<m_nbElements; ++i) {
+	Reveal::getInstance()->registerOutputRevealed(m_elements[i]);
+      }
+    }
+    else {
+      for(int i=0; i<m_nbElements; ++i) {
+	Reveal::getInstance()->unregisterOutputRevealed(m_elements[i]);
+      }
+    }
+}
+
+void RevealedArrowModule::processRevealedElement() {
+  m_revealedChanged=true;
+}
+
+ArrowPoint::ArrowPoint(RevealedArrowModule* mod) {
+    m_saved=false;
+    m_arrowMod=mod;
+    m_mod=NULL;
+}
+
+void ArrowPoint::setModule(Module* mod) {
+    m_mod=mod;
+}
+
+void ArrowPoint::update(std::vector<float>& floatValues, 
+                        std::vector<int>& intValues,
+                        std::vector<bool>& boolValues,
+                        std::vector<std::string>& stringValues) {
+    m_arrowMod->updateArrowPoints();
+}
+
+
diff --git a/src/modules/RevealedArrowModule.hpp b/src/modules/RevealedArrowModule.hpp
new file mode 100644
index 0000000..b59b79a
--- /dev/null
+++ b/src/modules/RevealedArrowModule.hpp
@@ -0,0 +1,199 @@
+/***************************************************************************
+ *  RevealedArrowModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef RevealedArrowModule_h
+#define RevealedArrowModule_h
+
+#include "GroupModule.hpp"
+#include "RevealedShapeModule.hpp"
+
+class ArrowPoint;
+class ArrowElementModule;
+
+class RevealedArrowModule : public GroupModule, 
+                            public ModuleListObserver {
+    public:
+        RevealedArrowModule();
+        virtual ~RevealedArrowModule();
+        virtual void deleteModule();
+
+        void draw();
+        void setVisible(bool vis);
+
+        static void originModuleCallback(Module* mod, 
+                                   const std::vector<std::string>& vals) {
+            dynamic_cast<RevealedArrowModule*>(mod)->setOriginModule(vals[0]);
+        }
+        void setOriginModule(const std::string& mod);
+
+        static void originOffsetCallback(Module* mod, 
+                                   const std::vector<float>& vals) {
+            dynamic_cast<RevealedArrowModule*>(mod)->setOriginOffset(
+                                                        vals[0],
+                                                        vals[1],
+                                                        vals[2]);
+        }
+        void setOriginOffset(const float& x, 
+                             const float& y, 
+                             const float& z);
+
+        static void destinationModuleCallback(Module* mod, 
+                                   const std::vector<std::string>& vals) {
+            dynamic_cast<RevealedArrowModule*>(mod)
+                ->setDestinationModule(vals[0]);
+        }
+        void setDestinationModule(const std::string& mod);
+
+        static void destinationOffsetCallback(Module* mod, 
+                                   const std::vector<float>& vals) {
+            dynamic_cast<RevealedArrowModule*>(mod)->setDestinationOffset(
+                                                        vals[0],
+                                                        vals[1],
+                                                        vals[2]);
+        }
+        void setDestinationOffset(const float& x, 
+                                  const float& y, 
+                                  const float& z);
+
+        static void elementsNumberCallback(Module* mod, 
+                                   const std::vector<int>& vals) {
+            dynamic_cast<RevealedArrowModule*>(mod)->setElementsNumber(vals[0]);
+        }
+        void setElementsNumber(const int& mod);
+
+        static void elementsSpeedCallback(Module* mod, 
+                                   const std::vector<float>& vals) {
+            dynamic_cast<RevealedArrowModule*>(mod)->setElementsSpeed(vals[0]);
+        }
+        void setElementsSpeed(const float& mod);
+
+        static void elementsThicknessCallback(Module* mod, 
+                                   const std::vector<float>& vals) {
+            dynamic_cast<RevealedArrowModule*>(mod)->setThickness(vals[0]);
+        }
+        void setThickness(const float& th);
+
+        static void elementsDirectionCallback(Module* mod, 
+                                   const std::vector<float>& vals) {
+            dynamic_cast<RevealedArrowModule*>(mod)->setElementsDirection(
+                                                        vals[0],
+                                                        vals[1],
+                                                        vals[2]);
+        }
+        void setElementsDirection(const float& x, 
+                                 const float& y, 
+                                 const float& z);
+
+        static void followDirectionCallback(Module* mod, 
+                                   const std::vector<bool>& vals) {
+         dynamic_cast<RevealedArrowModule*>(mod)->setFollowDirection(vals[0]);
+        }
+        void setFollowDirection(bool f);
+
+        static void elementsRevealedCallback(Module* mod, 
+                                   const std::vector<float>& vals) {}
+	void processRevealedElement();
+
+
+        void update(const int& timeDiffMs);
+        virtual void updateModulesList(const std::map<std::string, Module*>&);
+
+	void gotAttributeListenersUpdate(Attribute* att);
+        void updateArrowPoints();
+
+    protected:
+        int m_nbElements;
+        float m_speed;
+        ArrowPoint* m_origPnt;
+        ArrowPoint* m_destPnt;
+        glm::vec3 m_origin;
+        glm::vec3 m_originOffset;
+        glm::vec3 m_dest;
+        glm::vec3 m_destOffset;
+        glm::vec3 m_dir;
+        float m_distance;
+        std::vector<ArrowElementModule*> m_elements;
+        std::vector<float> m_positions;
+        std::string m_origModStr;
+        std::string m_destModStr;
+        float m_thickness;
+        glm::vec3 m_elementsDirection;
+        bool m_followDirection;
+	std::vector<Attribute*> m_revAttributes;
+	std::vector<float> m_revealed;
+	bool m_revealedChanged;
+};
+
+class ArrowPoint : public Listener {
+    public:
+        ArrowPoint(RevealedArrowModule*);
+        void setModule(Module* mod);
+        inline Module* getModule(){return m_mod;}
+        void update(std::vector<float>& floatValues, 
+                    std::vector<int>& intValues,
+                    std::vector<bool>& boolValues,
+                    std::vector<std::string>& stringValues);
+    private:
+        RevealedArrowModule* m_arrowMod;
+        Module* m_mod;
+};
+
+class ArrowElementModule : public RevealedShapeModule {
+  public:
+    ArrowElementModule(	const int& elID, 
+			RevealedArrowModule* arr) : RevealedShapeModule(),
+						    m_elementID(elID),
+						    m_arrow(arr),
+						    m_revealed(0) {
+    }
+
+
+    virtual void processReveal(const unsigned int& id,
+			       const std::vector<std::string>& name, 
+			       const std::vector<float>& surface, 
+			       const std::vector<float>& inside,
+			       const std::vector<float>& center,
+			       const std::vector<float>& extent,
+			       const std::vector<float>& color,
+			       const std::vector<float>& blob) {
+
+      if(m_revealed!=inside[0]) {
+            m_revealed=inside[0];
+            m_arrow->processRevealedElement();
+      }
+    }
+
+    inline const float& isRevealed(){return m_revealed;}
+
+  private:
+    int m_elementID;
+    int m_elementRevealed;
+    RevealedArrowModule* m_arrow;
+    float m_revealed;
+
+};
+
+
+
+#endif
+
diff --git a/src/modules/RevealedCutModule.cpp b/src/modules/RevealedCutModule.cpp
new file mode 100644
index 0000000..a2cbc28
--- /dev/null
+++ b/src/modules/RevealedCutModule.cpp
@@ -0,0 +1,393 @@
+/***************************************************************************
+ *  RevealedCutModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "RevealedCutModule.hpp" 
+
+#include <iostream>
+#include <glm/gtx/quaternion.hpp>
+
+#include "../Reveal.hpp"
+
+#include "../geoms/Geometry.hpp"
+
+using namespace std;
+
+RevealedCutModule::RevealedCutModule(): ShapeModule(), RevealedModule() {
+    m_type="Cut";
+    m_name="cut";
+    m_cutWin=NULL;
+    m_updateOnce=false;
+
+    Reveal::getInstance()->getGeom(Reveal::GEOM_BOX)->registerModule(this);
+
+    m_layersNb=1;
+    int nbBytes = m_texWidth*m_texHeight*m_layersNb*3;
+    m_layersData = new char[nbBytes];
+    m_coordImage = new float[m_texWidth*m_texHeight*2];
+
+    addNameAttribute();
+    addRemoveAttribute();
+    addVisibleAttribute();
+    addVisibleFromAttribute();
+    addRevealedByAttribute();
+
+    //add cut attributes
+    addAttribute(new Attribute("refresh_windows", 
+                                Attribute::ACTION_ATTRIBUTE,
+                                refreshWindowsCallback, this));
+    addAttribute(new Attribute("window", 
+                               Attribute::STRING_ATTRIBUTE,
+                               windowCallback, this, 1));
+    addAttribute(new Attribute("selection_position", 
+                               Attribute::INT_ATTRIBUTE,
+                               selPosCallback, this, 2));
+    addAttribute(new Attribute("selection_size", 
+                               Attribute::INT_ATTRIBUTE,
+                               selSizeCallback, this, 2));
+    addAttribute(new Attribute("update_once", 
+                               Attribute::BOOL_ATTRIBUTE,
+                               updateOnceCallback, this, 1));
+    refreshWindows();
+
+    addTransformationAttributes();
+    addRevealedAttributes();
+    addRevealedOutputAttributes();
+    m_inside=9;
+    m_localInsideAxes=true;
+
+    Reveal::getInstance()->addUpdateObserver(this);
+}
+
+RevealedCutModule::~RevealedCutModule() {
+    Reveal::getInstance()->getGeom(Reveal::GEOM_BOX)->unregisterModule(this);
+    Reveal::getInstance()->removeUpdateObserver(this);
+}
+
+void RevealedCutModule::refreshWindows() {
+    CutWindowsManager* winsMan = CutWindowsManager::getInstance();
+    winsMan->updateWindowsList();
+
+    vector<string> names;
+    names.push_back("none");
+    vector<CutWindow*>& wins = winsMan->editWindowList();
+    vector<CutWindow*>::iterator itWin = wins.begin();
+    for(; itWin!=wins.end(); ++itWin) {
+        names.push_back(((*itWin)->getName()).c_str());
+    }
+    m_attributesMap["window"]->editStringValuesChoices().assign(1,names);
+    m_attributesMap["window"]->initStrings(vector<string>(1, names[0]));
+}
+
+void RevealedCutModule::setWindow(const std::string& winName) {
+    CutWindow* win = CutWindowsManager::getInstance()->getWindow(winName);
+    m_cutWin=win;
+    if(m_cutWin) {
+        m_nbPixPerRow = m_cutWin->computeNbPixPerRow(200, 100);
+        vector<int> coords(2,0);
+        m_attributesMap["selection_position"]->initInts(coords);
+        coords[0]=m_cutWin->getWidth();
+        coords[1]=m_cutWin->getHeight();
+        m_attributesMap["selection_size"]->initInts(coords);
+        m_winX=0;
+        m_winY=0;
+        m_winW=m_cutWin->getWidth();
+        m_winH=m_cutWin->getHeight();
+        recomputePixels();
+    }
+}
+
+void RevealedCutModule::selPos(const int& posX, const int& posY) {
+    m_winX=posX;
+    m_winY=posY;
+    recomputePixels();
+}
+
+void RevealedCutModule::selSize(const int& sizeX, const int& sizeY) {
+    m_winW=sizeX;
+    m_winH=sizeY;
+    recomputePixels();
+}
+
+void RevealedCutModule::updateOnce(bool upOn) {
+    m_updateOnce=upOn;
+    m_updateOnceDone=false;
+}
+
+void RevealedCutModule::recomputePixels() {
+    //if window attached, recompute correspondance between pixel coordinates 
+    if(m_cutWin) {
+        //get new pixperrow in window
+        m_nbPixPerRow = m_cutWin->computeNbPixPerRow(m_winW, 
+                                                     m_winH);
+        //clear existing coordinates 
+        vector<float> coord(2,0);
+        vector<float> start(2,0);
+        vector<bool> restart(2,false);
+        vector<float> stepY(2,0);
+        vector<float> stepX(2,0);
+
+        //compute the pixels offset and steps
+        start[0]=m_winX;
+        start[1]=m_winY;
+        restart[0]=true;
+        stepX[0]=float(m_winW)/float(m_texWidth);
+        stepY[1]=float(m_winH)/float(m_texHeight);
+
+        vector<int> intCoord(2, 0);
+        coord[0]=start[0];
+        coord[1]=start[1];
+
+        //compute coordinates according to shape
+        for(int py = 0; py < m_texHeight; py++) {
+            coord[0]=restart[0]?start[0]:coord[0];
+            coord[1]=restart[1]?start[1]:coord[1];
+            for(int px = 0; px < m_texWidth; px++) {
+                intCoord[0]=coord[0]; 
+                intCoord[1]=coord[1];
+                coord[0]+=stepX[0];
+                coord[1]+=stepX[1];
+                m_coordImage[(m_texWidth*py+px)*2]=float(intCoord[0]) 
+                                 / float(m_cutWin->getWidth());
+                m_coordImage[(m_texWidth*py+px)*2+1]=float(intCoord[1]) 
+                                 / float(m_cutWin->getHeight());
+            }
+            coord[0]+=stepY[0];
+            coord[1]+=stepY[1];
+        }
+        //ask for reinitializing texture uniform
+        map<int, bool>::iterator itUp = m_coordsUpMap.begin();
+        for(; itUp!=m_coordsUpMap.end(); ++itUp) {
+            itUp->second=true;
+        }
+    }
+    m_updateOnceDone=false;
+}
+
+void RevealedCutModule::draw(const int& contextID, 
+                             const Reveal::REVIL_PROGRAM& prog, 
+                             map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                             const unsigned int& comp){
+
+    RevealedModule::draw(contextID, prog, uniforms, comp);
+    if(m_cutWin && prog==Reveal::RENDERPROG) {
+        glUniform1i(uniforms[Reveal::INSIDETEX], 2);
+        glActiveTexture(GL_TEXTURE2);
+        glBindTexture(GL_TEXTURE_3D, m_insideIDMap[contextID]);
+        if(!m_updateOnce || (m_updateOnce && !m_updateOnceDone)) {
+            glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+            glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 
+                         m_nbPixPerRow, m_cutWin->getHeight(), 
+                         m_layersNb, 0,
+                         GL_RGBA, GL_UNSIGNED_BYTE,
+                         m_cutWin->grabImage());
+            m_updateOnceDone=true;
+        }
+
+        glUniform1i(uniforms[Reveal::COORDSTEX], 4);
+        glActiveTexture(GL_TEXTURE4);
+        glBindTexture(GL_TEXTURE_2D, m_coordsIDMap[contextID]);
+        if(m_coordsUpMap[contextID]) {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F,
+                         m_texWidth, m_texHeight,
+                         0, GL_RG, GL_FLOAT,
+                         m_coordImage);
+            m_coordsUpMap[contextID]=false;
+        }
+    }
+}
+
+void RevealedCutModule::update(const int& timeDiffMs) {
+    if(m_cutWin) {
+        m_cutWin->releaseImage();
+    }
+}
+
+//Window manager
+#ifdef LINUX
+CutWindow::CutWindow(CutWindowsManager* man, 
+                     Display* disp, 
+                     const Window& win): m_winsMan(man), 
+                                         m_disp(disp), 
+                                         m_win(win) { 
+    Window root;
+    unsigned int bw, d, w, h;
+    XGetGeometry(m_disp, m_win, &root, &m_posX, &m_posY, 
+                 &w, &h, &bw, &d);
+    m_width=w;
+    m_height=h;
+    m_offsetX=0;
+    m_offsetY=0;
+    m_pixPerRow=m_width;
+    m_grabbed=false;
+    m_init=false;
+    m_defaultImgData = new uchar[m_width*m_height*3];
+}
+#endif
+
+void CutWindow::releaseImage() {
+#ifdef LINUX
+    if(m_grabbed) {
+        if(m_ximg) {
+            //XDestroyImage(m_ximg);
+        }
+        m_grabbed=false;
+    }
+#endif
+}
+
+uchar* CutWindow::grabImage() {
+#ifdef LINUX
+    if(!m_grabbed) {
+        //XImage* newImg = XGetImage(m_disp, m_win, 
+        //                           0, 0, 
+        //                           m_width, m_height, 
+        //                           AllPlanes, ZPixmap);
+        XImage* newImg=NULL;
+        if(!m_init) {
+            newImg = XGetImage(m_disp, m_win, 
+                               0, 0, 
+                               m_width, m_height, 
+                               AllPlanes, ZPixmap);
+            if(newImg) {
+                m_ximg=newImg;
+                m_init=true;
+            }
+        }
+        else {
+            newImg = XGetSubImage(m_disp, m_win, 
+                                  0, 0, 
+                                  m_width, m_height, 
+                                  AllPlanes, ZPixmap,
+                                  m_ximg, 0, 0);
+        }
+        if(newImg) {
+            m_imgData=(uchar*)m_ximg->data;
+        }
+        else {
+            m_imgData=m_defaultImgData;
+        }
+        m_grabbed=true;
+    }
+#endif
+    return m_imgData;
+}
+
+int CutWindow::computeNbPixPerRow(const int& srcW, const int& srcH) {
+#ifdef LINUX
+    XWindowAttributes attrs;
+    XGetWindowAttributes(m_disp, m_win, &attrs);
+    m_width=attrs.width;
+    m_height=attrs.height;
+    m_pixPerRow=m_width;
+    return m_width;
+#else
+    return 100;
+#endif
+}
+
+CutWindowsManager* CutWindowsManager::getInstance() {
+    static CutWindowsManager winsMan;
+    return &winsMan;
+}
+
+CutWindowsManager::CutWindowsManager() {
+#ifdef LINUX
+    m_disp = XOpenDisplay(NULL);
+#endif
+}
+
+CutWindowsManager::~CutWindowsManager() {
+#ifdef LINUX
+    XCloseDisplay(m_disp);
+#endif
+}
+
+void CutWindowsManager::updateWindowsList() {
+    map<string, CutWindow*> prevWins;
+    vector<CutWindow*>::iterator itWin=m_windowList.begin();
+    for(; itWin!=m_windowList.end(); ++itWin) {
+        prevWins[(*itWin)->getName()]=(*itWin);
+    }
+    m_windowList.clear();
+    unsigned long len;
+
+#ifdef LINUX
+    Window *list = getWinList(m_disp, &len);
+    for(int i=0;i<(int)len;i++) {
+        char* name = getWinName(m_disp, list[i]);
+        CutWindow* newWin=NULL;
+        if(prevWins.find(string(name))!=prevWins.end()) {
+            newWin = prevWins[string(name)];
+        }
+        else {
+            newWin = new CutWindow(this, m_disp, list[i]);
+        }
+        newWin->setName(string(name));
+        m_windowList.push_back(newWin);
+        free(name);
+    }
+    XFree(list);
+#endif
+
+}
+
+#ifdef LINUX
+char* CutWindowsManager::getWinName(Display* disp, Window win) {
+    Atom prop = XInternAtom(disp,"WM_NAME",false);
+    Atom type;
+    int form;
+    unsigned long remain, len;
+    unsigned char *list;
+
+    if (XGetWindowProperty(disp,win,prop,0,1024,false,XA_STRING,
+            &type,&form,&len,&remain,&list) != Success) {
+        cout<<"Error getting window name"<<endl;
+        return NULL;
+    }
+    return (char*)list;
+}
+
+Window* CutWindowsManager::getWinList(Display* disp, unsigned long* len) {
+    Atom prop = XInternAtom(disp,"_NET_CLIENT_LIST",false);
+    Atom type;
+    int form;
+    unsigned long remain;
+    unsigned char *list;
+    if(XGetWindowProperty(disp,XDefaultRootWindow(disp), 
+                          prop,0,1024,false,XA_WINDOW,
+                          &type,&form,len,&remain,&list) != Success) {
+        cout<<"Error getting windows list"<<endl;
+        return 0;
+    }
+    return (Window*)list;
+}
+#endif
+
diff --git a/src/modules/RevealedCutModule.hpp b/src/modules/RevealedCutModule.hpp
new file mode 100644
index 0000000..86dafd4
--- /dev/null
+++ b/src/modules/RevealedCutModule.hpp
@@ -0,0 +1,160 @@
+/***************************************************************************
+ *  RevealedCutModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef RevealedCutModule_h
+#define RevealedCutModule_h
+
+
+#include "ShapeModule.hpp"
+#include "RevealedModule.hpp"
+
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Image_Surface.H>
+
+#ifdef LINUX
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#endif
+
+
+class CutWindow;
+class CutWindowsManager;
+
+class RevealedCutModule : public ShapeModule, public RevealedModule {
+    public:
+        RevealedCutModule();
+        virtual ~RevealedCutModule();
+        void draw(const int& contextID,
+                  const Reveal::REVIL_PROGRAM& prog, 
+                  std::map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                  const unsigned int& comp=0);
+        virtual void update(const int& timeDiffMs);
+
+        static void windowCallback(Module* mod, 
+                                 const std::vector<std::string>& vals) {
+            dynamic_cast<RevealedCutModule*>(mod)->setWindow(vals[0]);
+        }
+        void setWindow(const std::string& text);
+        static void refreshWindowsCallback(Module* mod) {
+            dynamic_cast<RevealedCutModule*>(mod)->refreshWindows();
+        }
+        virtual void refreshWindows();
+        static void selPosCallback(Module* mod, 
+                                   const std::vector<int>& vals) {
+            dynamic_cast<RevealedCutModule*>(mod)->selPos(vals[0], vals[1]);
+        }
+        void selPos(const int& posX, const int& posY);
+        static void selSizeCallback(Module* mod, 
+                                    const std::vector<int>& vals) {
+            dynamic_cast<RevealedCutModule*>(mod)->selSize(vals[0], vals[1]);
+        }
+        void selSize(const int& sizeX, const int& sizeY);
+        static void updateOnceCallback(Module* mod, 
+                                       const std::vector<bool>& vals) {
+            dynamic_cast<RevealedCutModule*>(mod)->updateOnce(vals[0]);
+        }
+        void updateOnce(bool);
+        void recomputePixels();
+
+    protected:
+        std::string m_text;
+        CutWindow* m_cutWin;
+        int m_winX, m_winY, m_winW, m_winH;
+        float* m_coordImage;
+        int m_nbPixPerRow;
+        std::vector<int> m_srcIndices;
+        std::vector<std::vector<int> > m_srcCoords;
+        std::vector<int> m_destIndices;
+        bool m_updateOnce;
+        bool m_updateOnceDone;
+};
+
+class CutWindow {
+    public:
+#ifdef LINUX
+        CutWindow(CutWindowsManager* man, Display* disp, const Window& win);
+        ~CutWindow();
+#endif
+        int computeNbPixPerRow(const int& srcW, const int& srcH);
+        uchar* grabImage();
+        void releaseImage();
+
+        void setName(const std::string& name){m_name=name;}
+        const std::string& getName(){return m_name;}
+        const int& getHeight(){return m_height;} 
+        const int& getWidth(){return m_width;} 
+
+    private:
+        CutWindowsManager* m_winsMan;
+        int m_winID;
+        std::string m_name;
+        int m_posX, m_posY, m_width, m_height;
+        int m_offsetX, m_offsetY, m_pixPerRow;
+        uchar* m_imgData;
+        uchar* m_defaultImgData;
+        bool m_grabbed;
+        bool m_init;
+
+#ifdef LINUX
+        Display* m_disp;
+        Window m_win;
+        XImage* m_ximg;
+#endif
+};
+
+class CutWindowsManager {
+    public:
+        static CutWindowsManager* getInstance();
+        ~CutWindowsManager();
+        void updateWindowsList();
+        std::vector<CutWindow*>& editWindowList(){return m_windowList;}
+        CutWindow* getWindow(const std::string& name) {
+            CutWindow* res=NULL;
+            std::vector<CutWindow*>::iterator itWin=m_windowList.begin();
+            for(; itWin!=m_windowList.end(); ++itWin) {
+                if((*itWin)->getName().compare(name)==0 && name.compare("")!=0){
+                    res=(*itWin);
+                }
+            }
+            return res;
+        }
+        int getNbWindows(){return m_windowList.size();}
+
+        #ifdef LINUX
+        Window* getWinList(Display* disp, unsigned long* len);
+        char* getWinName(Display* disp, Window);
+        #endif
+
+    private:
+        CutWindowsManager();
+        std::vector<CutWindow*> m_windowList;
+        std::map<unsigned int, CutWindow*> m_windowMap;
+
+        #ifdef LINUX
+        Display* m_disp;
+        #endif
+};
+
+
+#endif
+
diff --git a/src/modules/RevealedGridModule.cpp b/src/modules/RevealedGridModule.cpp
new file mode 100644
index 0000000..504ef96
--- /dev/null
+++ b/src/modules/RevealedGridModule.cpp
@@ -0,0 +1,202 @@
+/***************************************************************************
+ *  RevealedGridModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "RevealedGridModule.hpp" 
+
+#include "../geoms/Geometry.hpp"
+
+#include <glm/gtx/matrix_decompose.hpp>
+#include <glm/gtx/quaternion.hpp>
+#include <glm/gtx/polar_coordinates.hpp>
+#include <glm/gtx/rotate_vector.hpp>
+#include <glm/gtx/euler_angles.hpp> 
+
+using namespace std;
+
+RevealedGridModule::RevealedGridModule(): GroupModule()  {
+    m_type="Grid";
+    m_name="grid";
+    addNameAttribute();
+    addRemoveAttribute();
+    addVisibleAttribute();
+    //addVisibleFromAttribute(); //TODO
+    
+    addAttribute(new Attribute("dimensions", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                dimensionsCallback, this, 3));
+
+    addTransformationAttributes();
+
+    addAttribute(new Attribute("elements_number", 
+                                Attribute::INT_ATTRIBUTE,
+                                elementsNumberCallback, this, 3));
+    addAttribute(new Attribute("elements_size", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                elementsSizeCallback, this, 1));
+    addAttribute(new Attribute("revealed_elements", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                elementsRevealedCallback, this, 2));
+    m_revAttributes.push_back(m_attributesMap["revealed_elements"]);
+
+    //TODO add mode : random, aligned, personnalized
+    //TODO add element pos attribute : element id then pos 3D 
+
+    m_totalNbElements=0;
+    m_nbElements[0]=m_nbElements[1]=m_nbElements[2]=0;
+    m_gridDims[0]=m_gridDims[1]=m_gridDims[2]=200;
+    m_elementsSize=20;
+    m_attributesMap["elements_size"]->setFloats(vector<float>(1, 20));
+    m_attributesMap["elements_number"]->setInts(vector<int>(3, 5));
+    m_attributesMap["dimensions"]->setFloats(vector<float>(3, 200));
+
+    m_revealed.push_back(0);
+    m_revealed.push_back(0);
+}
+
+RevealedGridModule::~RevealedGridModule() {
+}
+
+void RevealedGridModule::deleteModule() {
+    GroupModule::deleteModule();
+    for(int i=0; i<m_totalNbElements; ++i) {
+        m_elements[i]->deleteModule();
+    }
+}
+
+void RevealedGridModule::draw() {
+}
+
+void RevealedGridModule::updateModelMatrix() {
+  GroupModule::updateModelMatrix();
+  for(GridElementModule* el : m_elements) {
+    el->setParentMatrix(m_modelMat);
+    el->updateModelMatrix();
+  }
+}
+
+void RevealedGridModule::setVisible(bool vis) {
+  GroupModule::setVisible(vis);
+  for(int i=0; i<m_totalNbElements && i<int(m_elements.size()); ++i) {
+    m_elements[i]->setParentVisible(m_parentVisible&&m_visible);
+  }
+}
+
+void RevealedGridModule::setGridDimensions(const float& x, 
+                                           const float& y,
+                                           const float& z) {
+  if(x>0 && y>0 && z>0) {
+      m_gridDims[0]=x;
+      m_gridDims[1]=y;
+      m_gridDims[2]=z;
+      updateGridPoints();
+  }
+}
+
+void RevealedGridModule::setElementsNumber(const int& x, 
+                                           const int& y,
+                                           const int& z) {
+  int nb = x*y*z;
+  if(nb>0) {
+    m_nbElements[0]=x;
+    m_nbElements[1]=y;
+    m_nbElements[2]=z;
+    if(nb>m_totalNbElements) {
+      for(int i=m_totalNbElements; i<nb; ++i) {
+        m_elements.push_back(new GridElementModule(m_elements.size(),
+                                                   this));
+      }
+    }
+    m_totalNbElements=nb;
+    for(int i=0; i<m_totalNbElements; ++i) {
+      m_elements[i]->setVisible(true);
+    }
+    for(unsigned int i=m_totalNbElements; i<m_elements.size(); ++i) {
+      m_elements[i]->setVisible(false);
+    }
+    updateGridPoints();
+  }
+}
+
+void RevealedGridModule::setElementsSize(const float& s) {
+  if(s>0) {
+    m_elementsSize=s;
+    updateGridPoints();
+  }
+}
+
+void RevealedGridModule::update(const int& timeDiffMs) {
+}
+
+void RevealedGridModule::updateModulesList(const map<string, Module*>& mods) {
+}
+
+void RevealedGridModule::updateGridPoints() {
+  int el=0;
+  vector<float> pos(3,0);
+  float steps[3];
+  for(int i=0; i<3; ++i) {
+    steps[i]=m_gridDims[i]/m_nbElements[i];
+  }
+  vector<float> dims(3, m_elementsSize);
+  for(int x=0; x<m_nbElements[0]; x++) {
+    for(int y=0; y<m_nbElements[1]; y++) {
+      for(int z=0; z<m_nbElements[2]; z++) {
+        pos[0]=(x-m_nbElements[0]/2.0+0.5)*steps[0];
+        pos[1]=(y-m_nbElements[1]/2.0+0.5)*steps[1];
+        pos[2]=(z-m_nbElements[2]/2.0+0.5)*steps[2];
+        m_elements[el]->getAttribute("position")->setFloats(pos);
+        m_elements[el]->getAttribute("dimensions")->setFloats(dims);
+        el++;
+      }
+    }
+  }
+  updateModelMatrix();
+}
+
+void RevealedGridModule::gotAttributeListenersUpdate(Attribute* att) {
+    bool active=false;
+    for(Attribute *att : m_revAttributes) {
+      if(att->editListeners().size()>0) {
+        active=true;
+      }
+    } 
+    if(active) {
+        for(GridElementModule* el : m_elements) {
+            Reveal::getInstance()->registerOutputRevealed(el);
+        }
+    }
+    else {
+        vector<GridElementModule*>::iterator el=m_elements.begin();        
+        for(; el!=m_elements.end(); el++) {
+            Reveal::getInstance()->unregisterOutputRevealed(*el);
+        }
+    }
+}
+
+void RevealedGridModule::processRevealedElement(const int& elID, 
+                                                const float& val) {
+  m_revealed[0]=elID;
+  m_revealed[1]=val;
+  m_attributesMap["revealed_elements"]->setFloatsIfChanged(m_revealed);
+}
+
diff --git a/src/modules/RevealedGridModule.hpp b/src/modules/RevealedGridModule.hpp
new file mode 100644
index 0000000..0781325
--- /dev/null
+++ b/src/modules/RevealedGridModule.hpp
@@ -0,0 +1,126 @@
+/***************************************************************************
+ *  RevealedGridModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef RevealedGridModule_h
+#define RevealedGridModule_h
+
+#include "GroupModule.hpp"
+#include "RevealedShapeModule.hpp"
+
+class GridElementModule;
+
+class RevealedGridModule : public GroupModule, 
+                           public ModuleListObserver {
+    public:
+        RevealedGridModule();
+        virtual ~RevealedGridModule();
+        virtual void deleteModule();
+
+        void draw();
+        void setVisible(bool vis);
+
+        static void dimensionsCallback(Module* mod, 
+                                       const std::vector<float>& vals) {
+            dynamic_cast<RevealedGridModule*>(mod)->setGridDimensions(vals[0], 
+                                                                      vals[1],
+                                                                      vals[2]);
+        }
+        void setGridDimensions(const float& x, 
+                               const float& y, 
+                               const float& z);
+
+        static void elementsNumberCallback(Module* mod, 
+                                           const std::vector<int>& vals) {
+            dynamic_cast<RevealedGridModule*>(mod)->setElementsNumber(vals[0], 
+                                                                      vals[1],
+                                                                      vals[2]);
+        }
+        void setElementsNumber(const int& x, 
+                               const int& y, 
+                               const int& z);
+
+
+        static void elementsSizeCallback(Module* mod, 
+                                         const std::vector<float>& vals) {
+            dynamic_cast<RevealedGridModule*>(mod)->setElementsSize(vals[0]);
+        }
+        void setElementsSize(const float& th);
+
+        static void elementsRevealedCallback(Module* mod, 
+                                   const std::vector<float>& vals) {}
+	void processRevealedElement(const int&, const float&);
+
+
+        void update(const int& timeDiffMs);
+        virtual void updateModulesList(const std::map<std::string, Module*>&);
+
+	void gotAttributeListenersUpdate(Attribute* att);
+        void updateGridPoints();
+
+        virtual void updateModelMatrix();
+
+  protected:
+        int m_totalNbElements;
+        int m_nbElements[3];
+        float m_gridDims[3];
+        std::vector<GridElementModule*> m_elements;
+        std::vector<float> m_positions;
+        float m_elementsSize;
+	std::vector<Attribute*> m_revAttributes;
+	std::vector<float> m_revealed;
+	bool m_revealedChanged;
+};
+
+class GridElementModule : public RevealedShapeModule {
+  public:
+    GridElementModule(const int& elID, 
+		      RevealedGridModule* arr) : RevealedShapeModule(),
+                                                 m_elementID(elID),
+                                                 m_grid(arr),
+                                                 m_revealed(0) {
+    }
+
+    virtual void processReveal(const unsigned int& id,
+			       const std::vector<std::string>& name, 
+			       const std::vector<float>& surface, 
+			       const std::vector<float>& inside,
+			       const std::vector<float>& center,
+			       const std::vector<float>& extent,
+			       const std::vector<float>& color,
+			       const std::vector<float>& blob) {
+
+      if(m_revealed!=(inside[0]+surface[0]>0)?1:0) {
+          m_revealed=(inside[0]+surface[0]>0)?1:0;
+          m_grid->processRevealedElement(m_elementID, m_revealed);
+      }
+    }
+
+  private:
+    int m_elementID;
+    int m_elementRevealed;
+    RevealedGridModule* m_grid;
+    float m_revealed;
+};
+
+#endif
+
diff --git a/src/modules/RevealedModelModule.cpp b/src/modules/RevealedModelModule.cpp
new file mode 100644
index 0000000..9369cf0
--- /dev/null
+++ b/src/modules/RevealedModelModule.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+ *  RevealedModelModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "RevealedModelModule.hpp" 
+
+#include "../geoms/Geometry.hpp"
+
+#include <math.h>
+#define EPSILON 0.0001
+
+using namespace std;
+
+RevealedModelModule::RevealedModelModule(): ModelModule(), RevealedModule(){
+    m_type="Model";
+    m_name="model";
+    addNameAttribute();
+    addRemoveAttribute();
+    addVisibleAttribute();
+    addVisibleFromAttribute();
+    addRevealedByAttribute();
+    addModelAttributes();
+    addTransformationAttributes();
+	addFollowMarkerAttribute();
+    addRevealedAttributes();
+
+    addRevealedInsideStructureAttributes();
+
+    addAttribute(new Attribute("generate_texture_from_surface",
+                               Attribute::ACTION_ATTRIBUTE,
+                               generateSurfaceDistanceCallback, this,
+                               Attribute::LOCAL));
+
+    addRevealedInsideGradientAttributes();
+    addRevealedInsideDensityAttributes();
+    addRevealedInsideTextureAttributes();
+
+    addRevealedOutputAttributes();
+    m_currentGeom = m_modelGeom;
+	m_shapeGeom = Reveal::GEOM_MODEL;
+}
+
+RevealedModelModule::~RevealedModelModule() {
+/*
+    Reveal::getInstance()
+                ->getGeom(m_shapesMap[m_currentModel])
+                                ->unregisterModule(this);
+*/
+}
+
+void RevealedModelModule::draw(const int& contextID, 
+                               const Reveal::REVIL_PROGRAM& prog, 
+                               map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                               const unsigned int& comp) {
+
+    RevealedModule::draw(contextID, prog, uniforms, comp);
+    if(prog==Reveal::RENDERPROG) {
+		//send the surface distance texture
+        glUniform1i(uniforms[Reveal::SURFDISTEX], 5);
+        glActiveTexture(GL_TEXTURE5);
+        glBindTexture(GL_TEXTURE_3D, m_coordsIDMap[contextID]);
+        if(m_coordsUpMap[contextID]) {
+			glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+			glTexImage3D(GL_TEXTURE_3D, 0, GL_R32F,
+						m_surfDistDims.x, m_surfDistDims.y, m_surfDistDims.z,
+						0, GL_RED, GL_FLOAT, m_surfDistData.data());
+            m_coordsUpMap[contextID]=false;
+			cout<<"update surfdist txture"<<endl;
+        }
+    }
+}
+
+void RevealedModelModule::setModel(const std::string& fileName) {
+	ModelModule::setModel(fileName);
+	//try opening texture from surface
+	if(!m_modelStr.empty()) {
+		openSurfaceDistanceTexture(m_modelStr+"_surfdist.pvm");
+	}
+	//ask for reinitializing texture uniform
+	map<int, bool>::iterator itUp = m_coordsUpMap.begin();
+	for(; itUp!=m_coordsUpMap.end(); ++itUp) {
+		itUp->second=true;
+	}
+}
+
+
+void RevealedModelModule::generateSurfaceDistanceTexture() {
+	if(!m_modelStr.empty()) {
+		RevealedModule::generateSurfaceDistanceTexture(m_modelStr
+														+ "_surfdist.pvm");
+	}
+}
+
+
diff --git a/src/modules/RevealedModelModule.hpp b/src/modules/RevealedModelModule.hpp
new file mode 100644
index 0000000..8370993
--- /dev/null
+++ b/src/modules/RevealedModelModule.hpp
@@ -0,0 +1,54 @@
+/***************************************************************************
+ *  RevealedModelModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef RevealedModelModule_h
+#define RevealedModelModule_h
+
+#include "ModelModule.hpp"
+#include "RevealedModule.hpp"
+
+class RevealedModelModule : public ModelModule, public RevealedModule {
+    public:
+        RevealedModelModule();
+        virtual ~RevealedModelModule();
+        void draw(const int& contextID,
+                  const Reveal::REVIL_PROGRAM& prog, 
+                  std::map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                  const unsigned int& comp=0);
+        void gotAttributeListenersUpdate(Attribute* att) { 
+            RevealedModule::gotAttributeListenersUpdate(att);
+        }
+
+        static void generateSurfaceDistanceCallback(Module* mod) {
+            dynamic_cast<RevealedModelModule*>(mod)
+							->generateSurfaceDistanceTexture();
+        }
+		void generateSurfaceDistanceTexture();
+		void setModel(const std::string& fileName);
+
+    protected:
+};
+
+
+#endif
+
diff --git a/src/modules/RevealedModule.cpp b/src/modules/RevealedModule.cpp
new file mode 100644
index 0000000..6c69f44
--- /dev/null
+++ b/src/modules/RevealedModule.cpp
@@ -0,0 +1,1797 @@
+/***************************************************************************
+ *  RevealedModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "RevealedModule.hpp" 
+
+#include <iostream>
+#include <fstream>
+#include <limits>
+#include <unistd.h>
+
+#include <glm/gtx/norm.hpp>
+
+#include <FL/filename.H>
+#include <opencv2/opencv.hpp>
+
+#include "../geoms/Geometry.hpp"
+
+using namespace std;
+
+RevealedModule::RevealedModule(): GeomModule(), 
+                                  m_volumeTextureWidth(300), 
+                                  m_volumeTextureHeight(300),
+                                  m_outputActive(true) {
+
+    Reveal::getInstance()->registerRevealed(this);
+
+    //Material
+    m_surface=1;
+    m_reactivityType=0;
+    m_surfaceThickness=5.0;
+	m_shapeGeom=Reveal::GEOM_SPHERE;
+    m_layersData=NULL;
+    m_insideImage=NULL;
+    m_surfaceImage=NULL;
+    m_gradientImage=NULL;
+	m_textureGrayscale=false;
+	m_textureCanDelete=true;
+    m_layersNb=0;
+    for(int d=0; d<3; d++) {
+        m_textureOffset[d]=0;
+        m_textureScale[d]=1;
+    }
+
+	m_revSize=0;
+	m_revSurf=0;
+	m_revIns=0;
+	m_revCent=0;
+	m_revCol=0;
+	m_revHis=0;
+	m_revVox=0;
+	m_voxDim=5;
+	m_voxSize = m_voxDim*m_voxDim*m_voxDim;
+
+	m_outHistoSize=m_voxDim*m_voxDim;
+	m_outVoxelSize=m_voxDim*m_voxDim;
+
+	m_reactThread=NULL;
+	m_reactTexInput = new float[m_voxSize];
+	m_reactTexInternal = new float[m_voxSize];
+	m_reactTexOutput = new char[m_voxSize*3];
+	for(int v=0; v<m_voxSize; v++) {
+		m_reactTexInput[v]=0;
+		m_reactTexInternal[v]=0;
+		m_reactTexOutput[v*3]=0;
+		m_reactTexOutput[v*3+1]=0;
+		m_reactTexOutput[v*3+2]=0;
+	}
+}
+
+RevealedModule::~RevealedModule() {}
+
+void RevealedModule::addRevealedAttributes() {
+    addAttribute(new Attribute("color", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               colorCallback, this, 3));
+    addAttribute(new Attribute("surface", 
+                               Attribute::STRING_ATTRIBUTE,
+                               surfaceCallback, this, 1));
+    m_surfaces.push_back("none");
+    m_surfaces.push_back("color");
+    m_surfaces.push_back("texture");
+    m_attributesMap["surface"]->editStringValuesChoices().assign(1,m_surfaces);
+    m_attributesMap["surface"]->initStrings(vector<string>(1,m_surfaces[1]));
+    addAttribute(new Attribute("surface_color", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               surfaceColorCallback, this, 3));
+    addAttribute(new Attribute("surface_thickness", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               surfaceThicknessCallback, this, 1));
+    m_attributesMap["surface_thickness"]
+						->initFloats(vector<float>(1,m_surfaceThickness));
+    addAttribute(new Attribute("surface_texture", 
+                               Attribute::FILE_OPEN_ATTRIBUTE, 
+                               surfaceTextureCallback, this));
+
+    vector<float> initCol(3,0);
+    initCol[0]=360;
+    initCol[2]=100;
+    m_color.resize(3, 0);
+    m_surfaceColor.resize(3, 0);
+    hsv2rgb(initCol, m_color);
+    hsv2rgb(initCol, m_surfaceColor);
+    m_attributesMap["color"]->setFloats(initCol);
+    m_attributesMap["surface_color"]->setFloats(initCol);
+
+}
+
+void RevealedModule::addRevealedInsideAttributes() {
+	addRevealedInsideStructureAttributes();
+	addRevealedInsideGradientAttributes();
+	addRevealedInsideDensityAttributes();
+	addRevealedInsideTextureAttributes();
+}
+
+void RevealedModule::addRevealedInsideStructureAttributes() {
+	//Visible
+    addAttribute(new Attribute("inside_visible", 
+                               Attribute::BOOL_ATTRIBUTE,
+                               insideVisibleCallback, this, 1));
+    m_attributesMap["inside_visible"]->initBools(vector<bool>(1, true));
+	m_insideVisible=true;
+  
+	//Axes and structure
+    addAttribute(new Attribute("inside_axes", 
+                               Attribute::STRING_ATTRIBUTE,
+                               insideAxesCallback, this, 1));
+    m_insideAxes.push_back("local");
+    m_insideAxes.push_back("global");
+    m_attributesMap["inside_axes"]
+            ->editStringValuesChoices().assign(1, m_insideAxes);
+    m_attributesMap["inside_axes"]
+            ->initStrings(vector<string>(1, m_insideAxes[0]));
+
+    addAttribute(new Attribute("inside_structure", 
+                               Attribute::STRING_ATTRIBUTE,
+                               insideStructureCallback, this, 1));
+    m_insideStructures.push_back("from_center");
+    m_insideStructures.push_back("along_x");
+    m_insideStructures.push_back("along_y");
+    m_insideStructures.push_back("along_z");
+    m_insideStructures.push_back("from_surface");
+    m_attributesMap["inside_structure"]
+            ->editStringValuesChoices().assign(1, m_insideStructures);
+    m_attributesMap["inside_structure"]
+            ->setStrings(vector<string>(1,m_insideStructures[4]));
+
+	m_structureRatio=0;
+    addAttribute(new Attribute("structure_ratio", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               structureRatioCallback, this, 1));
+}
+
+void RevealedModule::addRevealedInsideGradientAttributes() {
+	//Gradient
+    addAttribute(new Attribute("gradient_alpha", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               gradientAlphaCallback, this, 1));
+    m_attributesMap["gradient_alpha"]->setFloats(vector<float>(1, 1));
+    addAttribute(new Attribute("gradient_type", 
+                               Attribute::STRING_ATTRIBUTE,
+                               gradientTypeCallback, this, 1));
+    m_gradientTypes.push_back("grayscale");
+    m_gradientTypes.push_back("texture");
+    m_attributesMap["gradient_type"]
+            ->editStringValuesChoices().assign(1, m_gradientTypes);
+    m_attributesMap["gradient_type"]
+            ->setStrings(vector<string>(1, m_gradientTypes[0]));
+    addAttribute(new Attribute("gradient_steps", 
+                               Attribute::INT_ATTRIBUTE,
+                               gradientStepsCallback, this, 1));
+    addAttribute(new Attribute("gradient_curve_ratio", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               gradientCurveRatioCallback, this, 1));
+    m_attributesMap["gradient_curve_ratio"]->setFloats(vector<float>(1, 1.0));
+
+    addAttribute(new Attribute("gradient_texture", 
+                               Attribute::FILE_OPEN_ATTRIBUTE,
+                               gradientTextureCallback, this));
+}
+
+void RevealedModule::addRevealedInsideDensityAttributes() {
+	//Density
+    addAttribute(new Attribute("density_alpha", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               densityAlphaCallback, this, 1));
+    m_attributesMap["density_alpha"]->setFloats(vector<float>(1, 0.5));
+    addAttribute(new Attribute("density_type", 
+                               Attribute::STRING_ATTRIBUTE,
+                               densityTypeCallback, this, 1));
+    m_insideDensityTypes.push_back("layers");
+    m_insideDensityTypes.push_back("grid");
+    m_insideDensityTypes.push_back("pointcloud");
+    m_attributesMap["density_type"]
+            ->editStringValuesChoices().assign(1, m_insideDensityTypes);
+    m_attributesMap["density_type"]
+            ->setStrings(vector<string>(1,m_insideDensityTypes[0]));
+    addAttribute(new Attribute("density_ratio", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               densityRatioCallback, this, 1));
+    m_attributesMap["density_ratio"]->setFloats(vector<float>(1,0.3));
+    addAttribute(new Attribute("density_size", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               densitySizeCallback, this, 1));
+    m_attributesMap["density_size"]->setFloats(vector<float>(1,0.1));
+    addAttribute(new Attribute("density_curve_ratio", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               densityCurveRatioCallback, this, 1));
+    m_attributesMap["density_curve_ratio"]->setFloats(vector<float>(1,1));
+}
+
+void RevealedModule::addRevealedInsideTextureAttributes() {
+	//Textures
+    addAttribute(new Attribute("texture_alpha", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               textureAlphaCallback, this, 1));
+    addAttribute(new Attribute("texture", 
+                               Attribute::FILE_OPEN_ATTRIBUTE, 
+                               textureCallback, this));
+    addAttribute(new Attribute("texture_layers_folder", 
+                               Attribute::FOLDER_OPEN_ATTRIBUTE, 
+                               textureLayersFolderCallback, this));
+    addAttribute(new Attribute("texture_grayscale", 
+                               Attribute::BOOL_ATTRIBUTE, 
+                               textureGrayscaleCallback, this, 1));
+    addAttribute(new Attribute("texture_blend", 
+                               Attribute::BOOL_ATTRIBUTE,
+                               textureBlendCallback, this, 1));
+    m_attributesMap["texture_blend"]->setBools(vector<bool>(1, true));
+    addAttribute(new Attribute("texture_offset", 
+                               Attribute::FLOAT_ATTRIBUTE, 
+                               textureOffsetCallback, this, 3));
+    addAttribute(new Attribute("texture_scale", 
+                               Attribute::FLOAT_ATTRIBUTE, 
+                               textureScaleCallback, this, 3));
+    m_attributesMap["texture_scale"]->initFloats(vector<float>(3, 1));
+
+    addAttribute(new Attribute("texture_reactivity", 
+                               Attribute::STRING_ATTRIBUTE,
+                               textureReactCallback, this, 1));
+    m_reactivityTypes.push_back("none");
+    m_reactivityTypes.push_back("thermal");
+    m_attributesMap["texture_reactivity"]
+            ->editStringValuesChoices().assign(1, m_reactivityTypes);
+    m_attributesMap["texture_reactivity"]
+            ->initStrings(vector<string>(1,m_reactivityTypes[0]));
+
+    addAttribute(new Attribute("layer_anim_position", 
+                               Attribute::FLOAT_ATTRIBUTE, 
+                               animPosCallback, this, 1));
+    addAttribute(new Attribute("layer_anim_play", 
+                               Attribute::BOOL_ATTRIBUTE, 
+                               animPlayCallback, this, 1));
+    m_attributesMap["layer_anim_play"]->initBools(vector<bool>(1,false));
+    addAttribute(new Attribute("layer_anim_speed", 
+                               Attribute::FLOAT_ATTRIBUTE, 
+                               animSpeedCallback, this, 1));
+    m_attributesMap["layer_anim_speed"]->initFloats(vector<float>(1,1));
+}
+
+void RevealedModule::addRevealedOutputAttributes() {
+    addAttribute(new Attribute("revealed_name", 
+                               Attribute::STRING_ATTRIBUTE,
+                               revnamCallback, this, 1, Attribute::OUTPUT));
+    m_attributesMap["revealed_name"]->initStrings(vector<string>(1,"name"));
+    m_revAttributes.push_back(m_attributesMap["revealed_name"]);
+    addAttribute(new Attribute("revealed_surface", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               revsurCallback, this, 1, Attribute::OUTPUT));
+    m_revAttributes.push_back(m_attributesMap["revealed_surface"]);
+	m_attributesMap["revealed_surface"]->setChangeCount(30);
+    addAttribute(new Attribute("revealed_inside", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               revinsCallback, this, 1, Attribute::OUTPUT));
+	m_attributesMap["revealed_inside"]->setChangeCount(30);
+    m_revAttributes.push_back(m_attributesMap["revealed_inside"]);
+    addAttribute(new Attribute("revealed_center", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               revcentCallback, this, 3, Attribute::OUTPUT));
+    m_revAttributes.push_back(m_attributesMap["revealed_center"]);
+    addAttribute(new Attribute("revealed_extent", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               revextCallback, this, 4, Attribute::OUTPUT));
+    m_revAttributes.push_back(m_attributesMap["revealed_extent"]);
+    addAttribute(new Attribute("revealed_color", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               revcolCallback, this, 3, Attribute::OUTPUT));
+    m_revAttributes.push_back(m_attributesMap["revealed_color"]);
+    addAttribute(new Attribute("revealed_histo", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               revhistoCallback, this, m_outHistoSize, 
+							   Attribute::OUTPUT));
+    m_revAttributes.push_back(m_attributesMap["revealed_histo"]);
+    addAttribute(new Attribute("revealed_voxels", 
+                               Attribute::FLOAT_ATTRIBUTE,
+                               revvoxelCallback, this, 
+							   m_outVoxelSize*4, 
+							   Attribute::OUTPUT));
+    m_revAttributes.push_back(m_attributesMap["revealed_voxels"]);
+}
+
+void RevealedModule::deleteModule() {
+    Reveal::getInstance()->unregisterRevealed(this);
+    GeomModule::deleteModule();
+}
+
+void RevealedModule::draw(const int& contextID,
+                          const Reveal::REVIL_PROGRAM& prog, 
+                          map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                          const unsigned int& comp){
+
+    GeomModule::draw(contextID, prog, uniforms, comp);
+    glUniform3fv(uniforms[Reveal::SHAPECOLOR], 1, &m_color[0]);
+
+    glUniform1i(uniforms[Reveal::SURFACE], m_surface);
+    glUniform3fv(uniforms[Reveal::SURFACECOLOR], 1, &m_surfaceColor[0]);
+    glUniform1f(uniforms[Reveal::SURFACETHICKNESS], m_surfaceThickness);
+
+    glUniform1f(uniforms[Reveal::SHAPEID], m_revID);
+    glUniform1f(uniforms[Reveal::SHAPEIDBIT], m_revIDBit);
+	glUniform1i(uniforms[Reveal::SHAPEGEOM], m_shapeGeom);
+    if(prog==Reveal::RENDERPROG) {
+        if(m_insideIDMap.find(contextID)==m_insideIDMap.end()) {
+            GLuint texID;
+            glGenTextures(1, &texID);
+            m_insideIDMap[contextID]=texID;
+            m_insideUpMap[contextID]=true;
+
+            glGenTextures(1, &texID);
+            m_coordsIDMap[contextID]=texID;
+            m_coordsUpMap[contextID]=true;
+
+            glGenTextures(1, &texID);
+            m_surfaceIDMap[contextID]=texID;
+            m_surfaceUpMap[contextID]=true;
+
+            glGenTextures(1, &texID);
+            m_gradientIDMap[contextID]=texID;
+            m_gradientUpMap[contextID]=true;
+
+			m_boundingRect[contextID]=glm::vec4(0.0);
+			m_boundingRectUpdate[contextID]=true;
+
+            glGenTextures(1, &texID);
+            m_reactIDMap[contextID]=texID;
+            m_reactUpMap[contextID]=true;
+        }
+
+		//test if bounding rect needs updating
+		if(m_boundingRectUpdate[contextID]) {
+			//get viewproj matrix of current projector
+			ContextHandler* proj = Reveal::getInstance()
+									->getContextHandler(contextID);
+			glm::mat4& mat = proj->getViewProjMat();
+
+			m_boundingRect[contextID][0]=numeric_limits<float>::max();
+			m_boundingRect[contextID][1]=numeric_limits<float>::max();
+			m_boundingRect[contextID][2]=-numeric_limits<float>::max();
+			m_boundingRect[contextID][3]=-numeric_limits<float>::max();
+			for(int p=0; p<8; ++p) {
+				glm::vec4 pnt;
+				pnt[0] = m_bbPnts[p%2][0];
+				pnt[1] = m_bbPnts[(p/2)%2][1];
+				pnt[2] = m_bbPnts[(p/4)%2][2];
+				pnt[3] = 1.0;
+
+				//transform the point with viewproj matrix
+				pnt = mat * pnt;
+
+				//find the bounding rect
+				m_boundingRect[contextID][0] 
+					= min<float>(pnt[0]/pnt[3], m_boundingRect[contextID][0]);
+				m_boundingRect[contextID][1] 
+					= min<float>(pnt[1]/pnt[3], m_boundingRect[contextID][1]);
+				m_boundingRect[contextID][2] 
+					= max<float>(pnt[0]/pnt[3], m_boundingRect[contextID][2]);
+				m_boundingRect[contextID][3] 
+					= max<float>(pnt[1]/pnt[3], m_boundingRect[contextID][3]);
+			}
+
+			//put coordinates between 0 and 1
+			for(int p=0; p<4; ++p) {
+				m_boundingRect[contextID][p]
+					= (m_boundingRect[contextID][p]+1.0)/2.0;
+			}
+
+			m_boundingRect[contextID][0]=1.0-m_boundingRect[contextID][0];
+			m_boundingRect[contextID][2]=1.0-m_boundingRect[contextID][2];
+
+			m_boundingRectUpdate[contextID]=false;
+		}
+
+		glUniform1i(uniforms[Reveal::REVSIZE], m_revSize);
+		glUniform1i(uniforms[Reveal::REVSURFACE], m_revSurf);
+		glUniform1i(uniforms[Reveal::REVINSIDE], m_revIns);
+		glUniform1i(uniforms[Reveal::REVCENTER], m_revCent);
+		glUniform1i(uniforms[Reveal::REVCOLOR], m_revCol);
+		glUniform1i(uniforms[Reveal::REVHISTO], m_revHis);
+		glUniform1i(uniforms[Reveal::REVVOXELS], m_revVox);
+		glUniform1i(uniforms[Reveal::OUTHISTOSIZE], m_outHistoSize);
+		glUniform1i(uniforms[Reveal::OUTVOXELSIZE], m_voxDim);
+		glUniform4fv(uniforms[Reveal::BRECT], 1, &m_boundingRect[contextID][0]);
+        glUniform1i(uniforms[Reveal::REVEALEDBY], m_revealedBy);
+        glUniform1i(uniforms[Reveal::REACTIVITY], m_reactivityType);
+
+        glUniform1i(uniforms[Reveal::INSIDEVISIBLE], m_insideVisible);
+        glUniform1i(uniforms[Reveal::INSIDESTRUCT], m_insideStructure);
+        glUniform1f(uniforms[Reveal::STRUCTRATIO], m_structureRatio);
+
+        glUniform1f(uniforms[Reveal::GRADIENTALPHA], m_insideGradientAlpha);
+        glUniform1i(uniforms[Reveal::GRADIENTTYPE], m_gradientType);
+        glUniform1i(uniforms[Reveal::GRADIENTSTEPS], m_insideGradientSteps);
+        glUniform1f(uniforms[Reveal::GRADIENTCURVERATIO], 
+					m_insideGradientCurveRatio);
+
+        glUniform1f(uniforms[Reveal::DENSITYALPHA], m_insideDensityAlpha);
+        glUniform1i(uniforms[Reveal::DENSITYTYPE], m_insideDensityType);
+        glUniform1f(uniforms[Reveal::DENSITYRATIO], m_insideDensityRatio);
+        glUniform1f(uniforms[Reveal::DENSITYSIZE], m_insideDensitySize);
+        glUniform1f(uniforms[Reveal::DENSITYCURVERATIO], 
+					m_insideDensityCurveRatio);
+
+        glUniform1f(uniforms[Reveal::TEXALPHA], m_insideTextureAlpha);
+        glUniform1i(uniforms[Reveal::TEXBLEND], m_insideTextureBlend);
+        glUniform3fv(uniforms[Reveal::TEXOFFSET], 1, &m_textureOffset[0]);
+        glUniform3fv(uniforms[Reveal::TEXSCALE], 1, &m_textureScale[0]);
+        glUniform1i(uniforms[Reveal::TEXGRAY], m_textureGrayscale);
+
+        glUniform1i(uniforms[Reveal::INSIDETEX], 2);
+        glActiveTexture(GL_TEXTURE2);
+        glBindTexture(GL_TEXTURE_3D, m_insideIDMap[contextID]);
+
+        //test layers update
+        int d=0;
+        vector<RevealedLayer*>::iterator itLa = m_layers.begin();
+        for(; itLa!=m_layers.end(); ++itLa, ++d) {
+            if((*itLa)->update(m_timeDiffMs, d, m_layersData, 
+                               m_texWidth, m_texHeight)) {
+                m_insideUpMap[contextID]=true;
+            }
+        }
+
+        if(m_insideUpMap[contextID]) { 
+			if(m_insideTextureBlend) {
+                glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, 
+                                GL_LINEAR);
+                glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, 
+                                GL_LINEAR);
+            }
+            else {
+                glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, 
+                                GL_NEAREST);
+                glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, 
+                                GL_NEAREST);
+            }
+			if(m_layersNb>0) { 
+				glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, 
+							 m_texWidth, m_texHeight, m_layersNb, 0,
+							 GL_RGB, GL_UNSIGNED_BYTE,
+							 m_layersData);
+			}
+			else if(m_insideImage) {
+				glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, 
+							 m_texWidth, m_texHeight, 1, 0,
+							 (m_insideImage->d()>3)?GL_RGBA:GL_RGB, 
+							 GL_UNSIGNED_BYTE,
+							 m_insideImage->data()[0]);
+			}
+            m_insideUpMap[contextID]=false;
+        }
+
+        glUniform1i(uniforms[Reveal::GRADIENTTEXTURE], 6);
+        glActiveTexture(GL_TEXTURE6);
+        glBindTexture(GL_TEXTURE_2D, m_gradientIDMap[contextID]);
+        if(m_gradientUpMap[contextID] && m_gradientImage) {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER);
+            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 
+                         m_texWidth, m_texHeight, 0,
+                         GL_RGB, GL_UNSIGNED_BYTE,
+                         m_gradientImage->data()[0]);
+            m_gradientUpMap[contextID]=false;
+        }
+
+        glUniform1i(uniforms[Reveal::SURFACETEX], 3);
+        glActiveTexture(GL_TEXTURE3);
+        glBindTexture(GL_TEXTURE_2D, m_surfaceIDMap[contextID]);
+        if(m_surfaceUpMap[contextID] && m_surfaceImage) {
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER);
+            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 
+                         m_texWidth, m_texHeight, 0,
+                         GL_RGB, GL_UNSIGNED_BYTE,
+                         m_surfaceImage->data()[0]);
+            m_surfaceUpMap[contextID]=false;
+        }
+
+        glUniform1i(uniforms[Reveal::REACTTEX], 4);
+        glActiveTexture(GL_TEXTURE4);
+        glBindTexture(GL_TEXTURE_3D, m_reactIDMap[contextID]);
+        if(m_reactUpMap[contextID] && m_reactLock.try_lock()) {
+			glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, 
+							GL_LINEAR);
+			glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, 
+							GL_LINEAR);
+			glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, 
+						 m_voxDim, m_voxDim, m_voxDim, 0,
+						 GL_RGB, GL_UNSIGNED_BYTE,
+						 m_reactTexOutput);
+            m_reactUpMap[contextID]=false;
+			m_reactLock.unlock();
+        }
+    }
+}
+
+void RevealedModule::update(const int& timeDiffMs) {
+    m_timeDiffMs=timeDiffMs;
+}
+
+void RevealedModule::setColor(const vector<float>& hsv) {
+    hsv2rgb(hsv, m_color);
+}
+
+/*
+void RevealedModule::setInside(const std::string& inside) {
+    int ins=0;
+    vector<string>::iterator itIns=m_insides.begin();
+    for(; itIns!=m_insides.end(); ++itIns, ++ins) {
+        if((*itIns).compare(inside)==0) {
+            m_inside=ins;
+        }
+    }
+    map<int, bool>::iterator itUp = m_insideUpMap.begin();
+    for(; itUp!=m_insideUpMap.end(); ++itUp) {
+        itUp->second=true;
+    }
+}*/
+
+void RevealedModule::setInsideAxes(const std::string& axes) {
+    if(axes.compare("local")==0) {
+        m_localInsideAxes = true;
+    }
+    else {
+        m_localInsideAxes = false;
+    }
+    updateModelMatrix();
+}
+
+void RevealedModule::setInsideStructure(const std::string& stru) {
+    int t=0;
+    vector<string>::iterator itStruct=m_insideStructures.begin();
+    for(; itStruct!=m_insideStructures.end(); ++itStruct, ++t) {
+        if((*itStruct).compare(stru)==0) {
+            m_insideStructure = t;
+        }
+    }
+}
+
+void RevealedModule::setTextureBlend(bool b){
+	m_insideTextureBlend=b;
+    map<int, bool>::iterator itUp = m_insideUpMap.begin();
+    for(; itUp!=m_insideUpMap.end(); ++itUp) {
+        itUp->second=true;
+    }
+}
+
+void RevealedModule::generateSurfaceDistanceTexture(const std::string& file) {
+    ostringstream os;
+    //int maxDigits = os.str().length();
+
+    vector<GLfloat>& vertices = m_currentGeom->editVertexBufferData();
+    vector<GLuint>& indices = m_currentGeom->editIndexBufferData();
+
+    cout<<"Building volumetric texture from "<<indices.size()/3<<" faces"
+        <<" and saving to file "<<file<<endl;
+
+	//m_surfDistDims = glm::vec3(64,64,64);
+	m_surfDistDims = glm::ivec3(128,128,128);
+
+	//voxels
+	std::vector<float> voxels(m_surfDistDims.x
+							  *m_surfDistDims.y
+							  *m_surfDistDims.z, 0);
+    
+    //for each pixel in the volumetric texture
+    for(int v = 0; v < int(voxels.size()); ++v) {
+		cout<<"Computing surface distance "
+			<<to_string(float(v)/float(voxels.size())*100.0)<<"%"<<endl;
+
+		//get 3D coord
+		int i=v%m_surfDistDims.x;
+		int j=(v/m_surfDistDims.x)%m_surfDistDims.y;
+		int k=v/(m_surfDistDims.x*m_surfDistDims.y);
+
+		//get 3D pos of voxel
+		glm::vec3 pos;
+		glm::vec3 pixCol(0,0,0);
+
+		pos[0] = (1.0-float(i)/float(m_surfDistDims.x))-0.5;
+		pos[1] = (1.0-float(j)/float(m_surfDistDims.y))-0.5;
+		pos[2] = (float(k)/float(m_surfDistDims.z))-0.5;
+
+		//find closest face
+		float minDist = std::numeric_limits<float>::max();
+		glm::vec3 nearestPnt;
+
+		for(unsigned int f=0; f<indices.size()/3; f++) {
+
+			glm::vec3 v0(vertices[indices[f*3+0]*5], 
+						 vertices[indices[f*3+0]*5+1], 
+						 vertices[indices[f*3+0]*5+2]);
+			glm::vec3 v1(vertices[indices[f*3+1]*5], 
+						 vertices[indices[f*3+1]*5+1], 
+						 vertices[indices[f*3+1]*5+2]);
+			glm::vec3 v2(vertices[indices[f*3+2]*5], 
+						 vertices[indices[f*3+2]*5+1], 
+						 vertices[indices[f*3+2]*5+2]);
+
+			auto diff = v0 - pos;
+			auto edge0 = v1 - v0;
+			auto edge1 = v2 - v0;
+			auto a00 = glm::dot(edge0, edge0);
+			auto a01 = glm::dot(edge0, edge1);
+			auto a11 = glm::dot(edge1, edge1);
+			auto b0 = glm::dot(diff,edge0);
+			auto b1 = glm::dot(diff,edge1);
+			auto det = std::abs(a00 * a11 - a01 * a01);
+			auto s = a01 * b1 - a11 * b0;
+			auto t = a01 * b0 - a00 * b1;
+
+			//NearestTriEntity ne;
+			if (s + t <= det) {
+				if (s < 0) {
+					if (t < 0) { // region 4
+						if (b0 < 0) {
+							t = 0;
+							if (-b0 >= a00) {
+								// VN1
+								//ne = NearestTriEntity::Vert1;
+								s = 1;
+							}
+							else {
+								// EN0
+								//ne = NearestTriEntity::Edge0;
+								s = -b0 / a00;
+							}
+						}
+						else {
+							s = 0;
+
+							if (b1 >= 0) {
+								// VN0
+								//ne = NearestTriEntity::Vert0;
+								t = 0;
+							}
+							else if (-b1 >= a11) {
+								// VN2
+								//ne = NearestTriEntity::Vert2;
+								t = 1;
+							}
+							else {
+								// EN2
+								//ne = NearestTriEntity::Edge2;
+								t = -b1 / a11;
+							}
+						}
+					}
+					else { // region 3
+						s = 0;
+
+						if (b1 >= 0) {
+							// VN0
+							//ne = NearestTriEntity::Vert0;
+							t = 0;
+						}
+						else if (-b1 >= a11) {
+							// VN2
+							//ne = NearestTriEntity::Vert2;
+							t = 1;
+						}
+						else {
+							// EN2
+							//ne = NearestTriEntity::Edge2;
+							t = -b1 / a11;
+						}
+					}
+				}
+				else if (t < 0) { // region 5
+					t = 0;
+
+					if (b0 >= 0) {
+						// VN0
+						//ne = NearestTriEntity::Vert0;
+						s = 0;
+					}
+					else if (-b0 >= a00) {
+						// VN1
+						//ne = NearestTriEntity::Vert1;
+						s = 1;
+					}
+					else {
+						// EN0
+						//ne = NearestTriEntity::Edge0;
+						s = -b0 / a00;
+					}
+				}
+				else { // region 0
+					// FN
+					//ne = NearestTriEntity::Face;
+					// minimum at interior point
+					auto invDet = (1) / det;
+					s *= invDet;
+					t *= invDet;
+				}
+			}
+			else {
+				double tmp0, tmp1, numer, denom;
+
+				if (s < 0) { // region 2
+					tmp0 = a01 + b0;
+					tmp1 = a11 + b1;
+
+					if (tmp1 > tmp0) {
+						numer = tmp1 - tmp0;
+						denom = a00 - (2) * a01 + a11;
+
+						if (numer >= denom) {
+							// VN1
+							//ne = NearestTriEntity::Vert1;
+							s = 1;
+							t = 0;
+						}
+						else {
+							// EN1
+							//ne = NearestTriEntity::Edge1;
+							s = numer / denom;
+							t = 1 - s;
+						}
+					}
+					else {
+						s = 0;
+
+						if (tmp1 <= 0) {
+							// VN2
+							//ne = NearestTriEntity::Vert2;
+							t = 1;
+						}
+						else if (b1 >= 0) {
+							// VN0
+							//ne = NearestTriEntity::Vert0;
+							t = 0;
+						}
+						else {
+							// EN2
+							//ne = NearestTriEntity::Edge2;
+							t = -b1 / a11;
+						}
+					}
+				}
+				else if (t < 0) { // region 6
+					tmp0 = a01 + b1;
+					tmp1 = a00 + b0;
+
+					if (tmp1 > tmp0) {
+						numer = tmp1 - tmp0;
+						denom = a00 - 2 * a01 + a11;
+
+						if (numer >= denom) {
+							// VN2
+							//ne = NearestTriEntity::Vert2;
+							t = 1;
+							s = 0;
+						}
+						else {
+							// EN1
+							//ne = NearestTriEntity::Edge1;
+							t = numer / denom;
+							s = 1 - t;
+						}
+					}
+					else {
+						t = 0;
+
+						if (tmp1 <= 0) {
+							// VN1
+							//ne = NearestTriEntity::Vert1;
+							s = 1;
+						}
+						else if (b0 >= 0) {
+							// VN0
+							//ne = NearestTriEntity::Vert0;
+							s = 0;
+						}
+						else {
+							// EN0
+							//ne = NearestTriEntity::Edge0;
+							s = -b0 / a00;
+						}
+					}
+				}
+				else { // region 1 
+					numer = a11 + b1 - a01 - b0;
+
+					if (numer <= 0) {
+						// VN2
+						//ne = NearestTriEntity::Vert2;
+						s = 0;
+						t = 1;
+					}
+					else {
+						denom = a00 - (2) * a01 + a11;
+						if (numer >= denom) {
+							// VN1
+							//ne = NearestTriEntity::Vert1;
+							s = 1;
+							t = 0;
+						}
+						else {
+							// EN1
+							//ne = NearestTriEntity::Edge1;
+							s = numer / denom;
+							t = 1 - s;
+						}
+					}
+				}
+			}
+
+			glm::vec3 np = v0 + edge0 * s + edge1 * t;
+			float dist = glm::distance(pos, np);
+			if(dist<minDist) {
+				nearestPnt = np;
+				minDist = dist;
+			}
+		}
+
+		float val = minDist;
+		voxels[v] = std::max<float>(0.0f, val);	
+	}
+
+	ofstream outfile;
+	outfile.open(file, ios::out | ios::trunc);
+	outfile<<"PVM"<<endl;
+	//write dimensions
+	outfile<<to_string(m_surfDistDims.x)<<" "
+			<<to_string(m_surfDistDims.y)<<" "
+			<<to_string(m_surfDistDims.z)<<endl;
+	//format
+	outfile<<"8 1"<<endl;
+	//data
+	int c=0;
+	m_surfDistData.resize(m_surfDistDims.x*m_surfDistDims.y*m_surfDistDims.z);
+	for(int k = 0 ; k < m_surfDistDims.x; k++) {
+		for(int j = 0; j < m_surfDistDims.y; j++) {
+			for(int i = 0; i < m_surfDistDims.z; i++) {
+				float val = voxels[k*(m_surfDistDims.x*m_surfDistDims.y)
+										+ j*(m_surfDistDims.x)+i];
+				outfile<<(unsigned char)(max<float>(0.0,val)*float(UCHAR_MAX));
+				m_surfDistData[c]=val;
+				c++;
+			}
+		}
+	}
+	outfile.close();	
+	map<int, bool>::iterator itUp = m_coordsUpMap.begin();
+	for(; itUp!=m_coordsUpMap.end(); ++itUp) {
+		itUp->second=true;
+	}
+
+	//set the chosen file as the texture layer
+    //setTextureLayersFolder(folder);
+    //m_attributesMap["texture_layers_folder"]
+    //    ->initStrings(vector<string>(1, folder));
+}
+
+void RevealedModule::openSurfaceDistanceTexture(const string& file) {
+	parsePvm(file, m_surfDistDims, m_surfDistData);
+
+	//ask for reinitializing texture uniform
+	map<int, bool>::iterator itUp = m_coordsUpMap.begin();
+	for(; itUp!=m_coordsUpMap.end(); ++itUp) {
+		itUp->second=true;
+	}
+}
+
+void RevealedModule::parsePvm(const std::string& file, 
+							  glm::ivec3& dimensions, 
+							  std::vector<float> &data) {
+	ifstream inpfile;
+	inpfile.open(file, ios::in);
+	cout<<"Loading pvm file "<<endl;
+
+	//read comment line
+	string type;
+	getline(inpfile, type);
+	if(type.compare("PVM")==0) {
+		//read dimensions line
+		string dims;
+		getline(inpfile, dims);
+		istringstream dimsIss(dims);
+		string dim;
+		getline(dimsIss, dim, ' ');
+		dimensions.x = stoi(dim);
+		getline(dimsIss, dim, ' ');
+		dimensions.y = stoi(dim);
+		getline(dimsIss, dim, ' ');
+		dimensions.z = stoi(dim);
+
+		//recreate data
+		data.resize(dimensions.x*dimensions.y*dimensions.z);
+
+		//read data type line
+		string type;
+		getline(inpfile, type);
+		istringstream typeIss(type);
+		string typ;
+		getline(typeIss, typ, ' ');
+
+		//read data depending on type
+		if(typ.compare("8")==0) {
+			for(int c=0; c<int(data.size()); ++c) {
+				unsigned char val = inpfile.get();
+				data[c] = float(val)/float(UCHAR_MAX);
+			}
+		}
+	}
+
+	cout<<"Done loading"<<endl;
+	inpfile.close();
+
+}
+
+//Gradient
+void RevealedModule::setGradientType(const std::string& type) {
+    int t=0;
+    vector<string>::iterator itType=m_gradientTypes.begin();
+    for(; itType!=m_gradientTypes.end(); ++itType, ++t) {
+        if((*itType).compare(type)==0) {
+            m_gradientType = t;
+        }
+    }
+}
+
+void RevealedModule::setGradientTexture(const std::string& f) {
+    Fl_Shared_Image* newImage = Fl_Shared_Image::get(f.c_str(), 
+                                                     m_texWidth, 
+                                                     m_texHeight);
+    if(newImage) {
+        m_gradientImage=newImage;
+        map<int, bool>::iterator itUp = m_gradientUpMap.begin();
+        for(; itUp!=m_gradientUpMap.end(); ++itUp) {
+            itUp->second=true;
+        }
+	}
+}
+
+//Density
+void RevealedModule::setDensityType(const std::string& type) {
+    int t=0;
+    vector<string>::iterator itType=m_insideDensityTypes.begin();
+    for(; itType!=m_insideDensityTypes.end(); ++itType, ++t) {
+        if((*itType).compare(type)==0) {
+            m_insideDensityType = t;
+        }
+    }
+}
+
+
+//Texture
+void RevealedModule::setTexture(const std::string& f) {
+    Fl_Shared_Image* newImage = Fl_Shared_Image::get(f.c_str(), 
+                                                     m_texWidth, 
+                                                     m_texHeight);
+    if(newImage) {
+        m_insideImage=newImage;
+        //ask for reinitializing texture uniform
+        map<int, bool>::iterator itUp = m_insideUpMap.begin();
+        for(; itUp!=m_insideUpMap.end(); ++itUp) {
+            itUp->second=true;
+        }
+    }
+}
+
+void RevealedModule::setTextureOffset(const float& x, 
+                                      const float& y,
+                                      const float& z) {
+	m_textureOffset[0]=x;
+    m_textureOffset[1]=y;
+    m_textureOffset[2]=z;
+}
+
+void RevealedModule::setTextureScale(const float& x, 
+                                     const float& y,
+                                     const float& z) {
+    m_textureScale[0]=(x!=0)?1.0/x:0;
+    m_textureScale[1]=(y!=0)?1.0/y:0;
+    m_textureScale[2]=(z!=0)?1.0/z:0;
+}
+
+void RevealedModule::setTextureLayersFolder(const std::string& folder) {
+    dirent** filesList;
+    int nbFiles = fl_filename_list(folder.c_str(), &filesList, fl_alphasort);
+    m_layers.clear();
+    for(int f=0; f<nbFiles; ++f) {
+        m_texWidth=640;
+        m_texHeight=480;
+        string fullName = folder+"/"+string(filesList[f]->d_name);
+        string extStr = string(fl_filename_ext(fullName.c_str()));
+        if(extStr.compare(".png")==0 || extStr.compare(".jpg")==0 
+				|| extStr.compare(".pgm")==0 ) {
+            Fl_Shared_Image* newImage = Fl_Shared_Image::get(fullName.c_str(), 
+                                                             m_texWidth, 
+                                                             m_texHeight);
+            if(newImage) {
+                if(newImage->refcount()>0) {
+                    newImage->reload();
+                }
+                RevealedLayerImage* layIm = new RevealedLayerImage();
+                layIm->m_image = newImage;
+                m_layers.push_back(layIm);
+            }
+        }
+        else if(extStr.compare(".ogg")==0 
+                || extStr.compare(".mp4")==0
+                || extStr.compare(".mov")==0) {
+            cv::VideoCapture movie; 
+            if(movie.open(fullName.c_str())) {
+                RevealedLayerVideo* layVi = new RevealedLayerVideo(m_texWidth, 
+                                                                    m_texHeight);
+                layVi->setVideo(movie);
+                m_layers.push_back(layVi);
+				m_textureCanDelete=false;
+            }
+        }
+        else if(fl_filename_isdir(fullName.c_str()) && 
+                    string(filesList[f]->d_name)[0]!='.'){ //animation folder
+            dirent** anList;
+            int nbAn=fl_filename_list(fullName.c_str(), &anList, fl_alphasort);
+            vector<Fl_Shared_Image*> ans;
+            for(int f=0; f<nbAn; ++f) {
+                string anName = fullName+"/"+string(anList[f]->d_name);
+                string ext2Str = string(fl_filename_ext(anName.c_str()));
+                if(ext2Str.compare(".png")==0 || ext2Str.compare(".jpg")==0) {
+                    Fl_Shared_Image* newAn=Fl_Shared_Image::get(anName.c_str(), 
+                                                                  m_texWidth, 
+                                                                  m_texHeight);
+                    if(newAn) {
+                        ans.push_back(newAn);
+                    }
+                }
+            }
+            if(ans.size()>0) {
+                RevealedLayerAnim* layAn = new RevealedLayerAnim();
+                layAn->m_images = ans;
+                m_layers.push_back(layAn);
+				m_textureCanDelete=false;
+            }
+        }
+    }
+
+    if(m_layers.size()>0) {
+        //create data buffer of corresponding depth, width and height
+        if(m_layersData) {
+            delete [] m_layersData;
+        }
+        m_layersNb=m_layers.size();
+        int nbBytes = m_texWidth*m_texHeight*m_layersNb*3;
+        m_layersData = new char[nbBytes];
+
+        //first texture update
+        int d=0;
+        vector<RevealedLayer*>::iterator itLa = m_layers.begin();
+        for(; itLa!=m_layers.end(); ++itLa, ++d) {
+            (*itLa)->update(0, d, m_layersData, m_texWidth, m_texHeight);
+			if(m_textureCanDelete) {
+				(*itLa)->releaseData();
+			}
+        }
+
+        //ask for reinitializing texture uniform
+        map<int, bool>::iterator itUp = m_insideUpMap.begin();
+        for(; itUp!=m_insideUpMap.end(); ++itUp) {
+            itUp->second=true;
+        }
+    }
+}
+
+void RevealedModule::setAnimPos(const float& pos) {
+    vector<RevealedLayer*>::iterator itLa = m_layers.begin();
+    for(; itLa!=m_layers.end(); ++itLa) {
+        (*itLa)->setAnimPos(pos/100.0);
+    }
+}
+
+void RevealedModule::setAnimPlay(const bool& play) {
+    vector<RevealedLayer*>::iterator itLa = m_layers.begin();
+    for(; itLa!=m_layers.end(); ++itLa) {
+        (*itLa)->setAnimPlay(play);
+    }
+    if(play) {
+        Reveal::getInstance()->addUpdateObserver(this);
+    }
+    else {
+        Reveal::getInstance()->removeUpdateObserver(this);
+    }
+}
+
+void RevealedModule::setAnimSpeed(const float& speed) {
+    vector<RevealedLayer*>::iterator itLa = m_layers.begin();
+    for(; itLa!=m_layers.end(); ++itLa) {
+        (*itLa)->setAnimSpeed(speed);
+    }
+}
+
+//Surface
+void RevealedModule::setSurface(const std::string& surface) {
+    int sur=0;
+    vector<string>::iterator itSur=m_surfaces.begin();
+    for(; itSur!=m_surfaces.end(); ++itSur, ++sur) {
+        if((*itSur).compare(surface)==0) {
+            m_surface=sur;
+        }
+    }
+    map<int, bool>::iterator itUp = m_surfaceUpMap.begin();
+    for(; itUp!=m_surfaceUpMap.end(); ++itUp) {
+        itUp->second=true;
+    }
+}
+
+void RevealedModule::setSurfaceColor(const vector<float>& hsv) {
+    hsv2rgb(hsv, m_surfaceColor);
+}
+
+void RevealedModule::setSurfaceTexture(const std::string& f) {
+    Fl_Shared_Image* newImage = Fl_Shared_Image::get(f.c_str(), 
+                                                     m_texWidth, 
+                                                     m_texHeight);
+    if(newImage) {
+        m_surfaceImage = newImage;
+        //ask for reinitializing texture uniform
+        map<int, bool>::iterator itUp = m_surfaceUpMap.begin();
+        for(; itUp!=m_surfaceUpMap.end(); ++itUp) {
+            itUp->second=true;
+        }
+    }
+}
+
+void RevealedModule::setSurfaceThickness(const float& surface) {
+    m_surfaceThickness=surface;
+}
+
+void RevealedModule::gotAttributeListenersUpdate(Attribute* att) {
+    bool active=false;
+    vector<Attribute*>::iterator itAtt = m_revAttributes.begin();
+    for(; itAtt!=m_revAttributes.end(); ++itAtt) {
+        if((*itAtt)->editListeners().size()>0) {
+            active=true;
+        }
+    } 
+    if(active) {
+        Reveal::getInstance()->registerOutputRevealed(this);
+    }
+    else {
+        Reveal::getInstance()->unregisterOutputRevealed(this);
+
+		//reset offsets
+		unsigned int off=0;
+		updateRevOffset(off);
+		m_revSize=0;
+    }
+}
+
+
+void RevealedModule::updateRevOffset(unsigned int& offset) {
+	//Test all reveal output attributes
+	m_revSize=1;
+	//inside is always active so that we can check for other attributes
+	m_revIns=0;
+	if(m_attributesMap["revealed_inside"]->editListeners().size()>0) {
+		m_revIns=m_revSize;
+	}
+	m_revSize+=1;
+
+	m_revSurf=0;
+	if(m_attributesMap["revealed_surface"]->editListeners().size()>0) {
+		m_revSurf=m_revSize;
+	}
+	m_revSize+=1;
+
+	m_revCent=0;
+	if(m_attributesMap["revealed_center"]->editListeners().size()>0
+			|| m_attributesMap["revealed_extent"]->editListeners().size()>0) {
+		m_revCent=m_revSize;
+	}
+	m_revSize+=6;
+
+	m_revCol=0;
+	if(m_attributesMap["revealed_color"]->editListeners().size()>0) {
+		m_revCol=m_revSize;
+	}
+	m_revSize+=4;
+
+	m_revHis=0;
+	if(m_attributesMap["revealed_histo"]->editListeners().size()>0) {
+		m_revHis=m_revSize;
+	}
+	m_revSize+=(m_outHistoSize+1);
+
+	m_revVox=0;
+	if(m_attributesMap["revealed_voxels"]->editListeners().size()>0) {
+		m_revVox=m_revSize;
+	}
+	m_revSize+=(m_outVoxelSize*5);
+}
+
+void RevealedModule::processReveal(const unsigned int& depthID,
+								   const string& depthName,
+								   const unsigned int& depthNb,
+								   unsigned int* outputImg) {
+
+	int offset = ((m_revID-1)*depthNb+(depthID-1))*m_revSize;
+
+	//test if shape revealed
+	int revealed = outputImg[offset];
+	bool send=false;
+    if(m_depthModsMap.find(depthID)==m_depthModsMap.end()) {
+        if(revealed) {
+            send=true;
+            m_depthModsMap[depthID]=true;
+        }
+    }
+    else {
+        send=true;
+        if(!revealed) {
+            m_depthModsMap.erase(depthID);
+        }
+    }
+
+	if(send) {
+		vector<string> names(1, depthName);
+		m_attributesMap["revealed_name"]->setStringsIfChanged(names);
+
+		if(m_revIns>0) {
+			vector<float> inside(1, outputImg[offset+m_revIns]);
+			m_attributesMap["revealed_inside"]->setFloatsIfChangedOrCount(inside);
+		}
+
+		if(m_revSurf>0) {
+			vector<float> vals(1, outputImg[offset+m_revSurf]);
+			m_attributesMap["revealed_surface"]->setFloatsIfChangedOrCount(vals);
+		}
+
+		if(m_revCent>0 && revealed&1) {
+			float fMinX = (1000.0-float(outputImg[offset+m_revCent]))/1000.0;
+			float fMaxX = float(outputImg[offset+m_revCent+1])/1000.0;
+			float fMinY = (1000.0-float(outputImg[offset+m_revCent+2]))/1000.0;
+			float fMaxY = float(outputImg[offset+m_revCent+3])/1000.0;
+			float fMinZ = (1000.0-float(outputImg[offset+m_revCent+4]))/1000.0;
+			float fMaxZ = float(outputImg[offset+m_revCent+5])/1000.0;
+
+			vector<float> center = {(fMaxX+fMinX)/2.0f,
+									(fMaxY+fMinY)/2.0f,
+									(fMaxZ+fMinZ)/2.0f};
+			m_attributesMap["revealed_center"]->setFloatsIfChanged(center);
+			vector<float> extent = {fabs(fMaxX-fMinX),
+									fabs(fMaxY-fMinY),
+									fabs(fMaxZ-fMinZ),
+									(fabs(fMaxX-fMinX) +
+										fabs(fMaxY-fMinY) + 
+										fabs(fMaxZ-fMinZ))/3.0f};
+			m_attributesMap["revealed_extent"]->setFloatsIfChanged(extent);
+		}
+
+		if(m_revCol>0 && revealed&1) {
+			float nbPoints = float(outputImg[offset+m_revCol]);
+			if(nbPoints>0) {
+				vector<float> color = 
+				 {(float(outputImg[offset+m_revCol+1])/1000.0f)/float(nbPoints),
+				 (float(outputImg[offset+m_revCol+2])/1000.0f)/float(nbPoints),
+				 (float(outputImg[offset+m_revCol+3])/1000.0f)/float(nbPoints)};
+				m_attributesMap["revealed_color"]->setFloatsIfChanged(color);
+			}
+		}
+
+		if(m_revHis>0 && revealed&1) {
+			float nbPoints = float(outputImg[offset+m_revHis]);
+			if(nbPoints>0) {
+				vector<float> histo;
+				for(int i=1; i<m_outHistoSize+1; i++) {
+				  histo.push_back(float(outputImg[offset+m_revHis+i])/nbPoints);
+				}
+				m_attributesMap["revealed_histo"]->setFloatsIfChanged(histo);
+			}
+		}
+
+		if(m_revVox>0 && revealed&1) {
+			vector<float> voxels;
+			for(int i=0; i<m_outVoxelSize; i++) {
+				float nbPoints = float(outputImg[offset+m_revVox+i*5]);
+				if(nbPoints>0) {
+					//coords average
+					voxels.push_back((float(outputImg[offset+m_revVox+i*5+1])/1000.0)
+										/ nbPoints);
+					voxels.push_back((float(outputImg[offset+m_revVox+i*5+2])/1000.0)
+										/ nbPoints);
+					voxels.push_back((float(outputImg[offset+m_revVox+i*5+3])/1000.0)
+										/ nbPoints);
+					//luminance average
+					voxels.push_back((float(outputImg[offset+m_revVox+i*5+4])/1000.0)
+										/ nbPoints);
+				}
+				else {
+					voxels.push_back(0);
+					voxels.push_back(0);
+					voxels.push_back(0);
+					voxels.push_back(0);
+				}
+			}
+			m_attributesMap["revealed_voxels"]->setFloatsIfChanged(voxels);
+		}
+	}
+}
+
+void RevealedModule::hsv2rgb(const vector<float>& hsv, 
+                             vector<float>& rgb) {
+    float hh, p, q, t, ff;
+    long   i;
+    if(hsv[1] <= 0.0) {
+        rgb[0] = hsv[2]/100.0;
+        rgb[1] = hsv[2]/100.0;
+        rgb[2] = hsv[2]/100.0;
+        return;
+    }
+    hh = hsv[0];
+    if(hh >= 360.0) { 
+        hh = 0.0;
+    }
+    hh /= 60.0;
+    i = (long)hh;
+    ff = hh - i;
+    p = hsv[2]/100.0 * (1.0 - hsv[1]/100.0);
+    q = hsv[2]/100.0 * (1.0 - (hsv[1]/100.0 * ff));
+    t = hsv[2]/100.0 * (1.0 - (hsv[1]/100.0 * (1.0 - ff)));
+    switch(i) {
+        case 0:
+            rgb[0] = hsv[2]/100.0;
+            rgb[1] = t;
+            rgb[2] = p;
+            break;
+        case 1:
+            rgb[0] = q;
+            rgb[1] = hsv[2]/100.0;
+            rgb[2] = p;
+            break;
+        case 2:
+            rgb[0] = p;
+            rgb[1] = hsv[2]/100.0;
+            rgb[2] = t;
+            break;
+        case 3:
+            rgb[0] = p;
+            rgb[1] = q;
+            rgb[2] = hsv[2]/100.0;
+            break;
+        case 4:
+            rgb[0] = t;
+            rgb[1] = p;
+            rgb[2] = hsv[2]/100.0;
+            break;
+        case 5:
+        default:
+            rgb[0] = hsv[2]/100.0;
+            rgb[1] = p;
+            rgb[2] = q;
+            break;
+    }
+}                          
+
+
+//----------------------Simulation--------------------------
+void* reactThreadFunction(void* pvParam) {
+    ((RevealedModule*)pvParam)->textureReact();
+    return NULL;
+}
+
+void RevealedModule::setTextureReact(const std::string& type) {
+    int t=0;
+    vector<string>::iterator itType=m_reactivityTypes.begin();
+    for(; itType!=m_reactivityTypes.end(); ++itType, ++t) {
+        if((*itType).compare(type)==0) {
+            m_reactivityType = t;
+        }
+    }
+	//stop reactive thread
+	if(m_reactThread) {
+		m_reactActive=false;
+		m_reactThread->join();
+		delete m_reactThread;
+		m_reactThread=NULL;
+	}
+	
+	//start it again if reactive
+	if(m_reactivityType>0) {
+		m_reactActive=true;
+		m_reactThread = new std::thread(reactThreadFunction, this);
+	}
+}
+
+void RevealedModule::textureReact() {
+	while(m_reactActive) {
+		//get voxel output from attribute
+		m_reactLock.lock();
+		vector<float> voxels(m_attributesMap["revealed_voxels"]->getFloats());
+		int inside = m_attributesMap["revealed_inside"]->getFloats()[0];
+		m_reactLock.unlock();
+
+		//reset input texture
+		for(int v=0; v<m_voxSize; ++v) {
+			m_reactTexInput[v]=0;
+		}
+
+		//store revealed in input texture
+		if(inside>0) {
+			for(int v=0; v<m_outVoxelSize; ++v) {
+				if(voxels[v*4]>0) { //if coord active
+					int coord = int((voxels[v*4])*float(m_voxDim)) //x
+						+ int((voxels[v*4+1])*float(m_voxDim))*m_voxDim //y
+						+ int((voxels[v*4+2])*float(m_voxDim))*m_voxDim*m_voxDim;
+					m_reactTexInput[coord] = 1.0;
+				}
+			}
+		}
+		
+		//update voxels
+		float step=1;
+		for(int v=0; v<m_voxSize; ++v) {
+			if(m_reactTexInput[v]>0) {
+				m_reactTexInternal[v]=min<float>(m_reactTexInternal[v]+step, 
+												 250.0);
+			}
+			else {
+				m_reactTexInternal[v]=max<float>(m_reactTexInternal[v]-step, 
+												0.0);
+			}
+		}
+
+		//update react texture and update map
+		m_reactLock.lock();
+			for(int v=0; v<m_voxSize; ++v) {
+				m_reactTexOutput[v*3]=char(10*sqrt(m_reactTexInternal[v]));
+				m_reactTexOutput[v*3+1]=char(10*sqrt(m_reactTexInternal[v]));
+				m_reactTexOutput[v*3+2]=char(10*sqrt(m_reactTexInternal[v]));
+			}
+			for(auto& m : m_reactUpMap) {
+				m.second=true;
+			}
+		m_reactLock.unlock();
+		usleep(10000);
+	}
+}
+
+
+//-----------------------------Layers-------------------------------------
+
+RevealedLayer::RevealedLayer(): m_playing(false), m_speed(1), 
+                                m_update(true), m_accumTimeDiff(0){}
+
+bool RevealedLayerImage::update(const int& timeDiffMs, const int& depth, 
+                                char* data,
+                                const int& width, const int& height) {
+    if(m_update) {
+        for(int i=0; i<width; ++i) {
+            for(int j=0; j<height; ++j) {
+                if(m_image->d()==4) {
+                    data[(depth*width*height+j*width+i)*3]
+                       =m_image->data()[0][(j*m_image->w()+i)*m_image->d()]
+                       *((m_image->data()[0][(j*m_image->w()+i)*m_image->d()+3]
+                                   ==0)?0:1);
+                    data[(depth*width*height+j*width+i)*3+1]
+                       =m_image->data()[0][(j*m_image->w()+i)*m_image->d()+1]
+                       *((m_image->data()[0][(j*m_image->w()+i)*m_image->d()+3]
+                                   ==0)?0:1);
+                    data[(depth*width*height+j*width+i)*3+2]
+                       =m_image->data()[0][(j*m_image->w()+i)*m_image->d()+2]
+                       *((m_image->data()[0][(j*m_image->w()+i)*m_image->d()+3]
+                                   ==0)?0:1);
+                }
+                else {
+					data[(depth*width*height+j*width+i)*3]
+						= m_image->data()[0][(j*m_image->w()+i)*m_image->d()];
+					data[(depth*width*height+j*width+i)*3+1]
+						= m_image->data()[0][(j*m_image->w()+i)*m_image->d()+1];
+					data[(depth*width*height+j*width+i)*3+2]
+						= m_image->data()[0][(j*m_image->w()+i)*m_image->d()+2];
+                }
+            }
+        }
+        m_update=false;
+    }
+    return false;
+}
+
+bool RevealedLayerVideo::update(const int& timeDiffMs, const int& depth, 
+                                char* data,
+                                const int& width, const int& height) {
+    bool res=false;
+    //try lock 
+    if(m_gotFrame) {
+        if(m_lock.try_lock()) {
+            //copy frame to data
+            memcpy(&data[depth*width*height*3], &m_data[0], width*height*3);
+            res=true;
+            m_gotFrame=false;
+            m_lock.unlock();
+        }
+    }
+
+    return res;
+}
+
+
+void RevealedLayerVideo::read() {
+    m_video.set(cv::CAP_PROP_POS_FRAMES, 0);
+    while(m_playing) {
+
+		int nbFrames=0;
+		bool gotFrame=false;
+        if(m_playing) {
+
+            timeval curTime, timeDiff;
+            gettimeofday(&curTime,NULL);
+            timersub(&curTime, &m_prevTime, &timeDiff);
+            int timeDiffMs = timeDiff.tv_sec*1000.0+timeDiff.tv_usec/1000.0;
+            m_accumTimeDiff=float(timeDiffMs)*m_speed;
+			int supFrame = m_accumTimeDiff
+								/(1000.0/m_vidFps);
+			if(supFrame>m_curFrame) {
+                m_update=true;
+				nbFrames=supFrame-m_curFrame;
+			}
+        }
+
+        for(; nbFrames>0; nbFrames--) {
+			try {
+				//if(!m_video.read(m_frame)) {
+				if(!m_video.grab()) {
+					/*
+					m_video.set(cv::CAP_PROP_POS_FRAMES, 0);
+					gettimeofday(&m_prevTime,NULL);
+					m_curFrame=0;
+					*/
+					m_playing=false;
+				}
+				else {
+					gotFrame=true;
+					m_curFrame++;
+				}
+			}catch(const std::exception& e) {
+
+			}
+		}
+        if(m_update) {
+			if(gotFrame) {
+				cv::Mat frame;
+				m_video.retrieve(frame);
+                m_lock.lock();
+                float scaX = float(m_vidWidth)/float(m_texWidth);
+                float scaY = float(m_vidHeight)/float(m_texHeight);
+                for(float i=0; i<m_texWidth; ++i) {
+                    for(float j=0; j<m_texHeight; ++j) {
+                        m_data[int(j*m_texWidth+i)*3]
+                           = frame.data[(int(j*scaY)*m_vidWidth+int(i*scaX))*3+2];
+                        m_data[int(j*m_texWidth+i)*3+1]
+                           = frame.data[(int(j*scaY)*m_vidWidth+int(i*scaX))*3+1];
+                        m_data[int(j*m_texWidth+i)*3+2]
+                           = frame.data[(int(j*scaY)*m_vidWidth+int(i*scaX))*3];
+                    }
+                }
+                m_gotFrame=true;
+                m_lock.unlock();
+            }
+            m_update=false;
+        }
+
+		
+		/*
+        if(m_playing) {
+            timeval curTime, timeDiff;
+            gettimeofday(&curTime,NULL);
+            timersub(&curTime, &m_prevTime, &timeDiff);
+            int timeDiffMs = timeDiff.tv_sec*1000.0+timeDiff.tv_usec/1000.0;
+            m_accumTimeDiff=float(timeDiffMs)*m_speed;
+			int nextFrame = m_accumTimeDiff
+								/(1000.0/m_vidFps);
+			if(nextFrame!=m_curFrame) {
+				if(nextFrame>=m_vidFrames) {
+					m_curFrame = nextFrame-m_vidFrames;;
+				}
+				else {
+					m_curFrame=nextFrame;
+				}
+                m_update=true;
+			}
+        }
+
+		cout<<"blup?"<<endl;
+		if(m_update) {
+			cout<<"blip?"<<endl;
+			m_video.set(cv::CAP_PROP_POS_FRAMES, m_curFrame);
+			if(m_video.read(m_frame)) {
+                m_lock.lock();
+                float scaX = m_vidWidth/m_texWidth;
+                float scaY = m_vidHeight/m_texHeight;
+                for(int i=0; i<m_texWidth; ++i) {
+                    for(int j=0; j<m_texHeight; ++j) {
+                        m_data[(j*m_texWidth+i)*3]
+                           = m_frame.data[int(j*scaY*m_vidWidth+i*scaX)*3+2];
+                        m_data[(j*m_texWidth+i)*3+1]
+                           = m_frame.data[int(j*scaY*m_vidWidth+i*scaX)*3+1];
+                        m_data[(j*m_texWidth+i)*3+2]
+                           = m_frame.data[int(j*scaY*m_vidWidth+i*scaX)*3];
+                    }
+                }
+                m_gotFrame=true;
+                m_lock.unlock();
+				m_update=false;
+			}
+		}
+		*/
+
+		/*
+		//img test
+        if(m_playing) {
+
+            timeval curTime, timeDiff;
+            gettimeofday(&curTime,NULL);
+            timersub(&curTime, &m_prevTime, &timeDiff);
+            int timeDiffMs = timeDiff.tv_sec*1000.0+timeDiff.tv_usec/1000.0;
+            m_accumTimeDiff=float(timeDiffMs)*m_speed;
+			int nextFrame = m_accumTimeDiff
+								/(1000.0/m_vidFps);
+			if(nextFrame!=m_curFrame) {
+				if(nextFrame>=m_vidFrames) {
+					m_curFrame = nextFrame-m_vidFrames;;
+				}
+				else {
+					m_curFrame=nextFrame;
+				}
+                m_update=true;
+			}
+        }
+
+		if(m_update) {
+			m_lock.lock();
+				memcpy(&m_data[0], 
+						&m_vidData[m_curFrame*m_texWidth*m_texHeight*3], 
+						m_texWidth*m_texHeight*3);
+			m_gotFrame=true;
+			m_lock.unlock();
+		}
+		*/
+
+
+
+        usleep(5000);
+    }
+}
+
+void RevealedLayerVideo::setVideo(cv::VideoCapture vid) {
+	m_video=vid;
+	m_vidWidth = m_video.get(cv::CAP_PROP_FRAME_WIDTH);
+	m_vidHeight = m_video.get(cv::CAP_PROP_FRAME_HEIGHT);
+	m_vidFps = vid.get(cv::CAP_PROP_FPS);
+	m_vidFrames = vid.get(cv::CAP_PROP_FRAME_COUNT);
+
+	/*
+	//test with images
+	m_video=vid;
+	m_vidWidth = vid.get(cv::CAP_PROP_FRAME_WIDTH);
+	m_vidHeight = vid.get(cv::CAP_PROP_FRAME_HEIGHT);
+	
+	if(m_vidData!=NULL) {
+		delete [] m_vidData;
+	}
+	
+	m_vidData = new char[m_vidFrames*m_texWidth*m_texHeight*3];
+	float scaX = m_vidWidth/m_texWidth;
+	float scaY = m_vidHeight/m_texHeight;
+
+	for(int f=0; f<m_vidFrames; ) {
+		if(vid.read(m_frame)) {
+			for(int i=0; i<m_texWidth; ++i) {
+				for(int j=0; j<m_texHeight; ++j) {
+					m_vidData[(f*m_texWidth*m_texHeight+j*m_texWidth+i)*3]
+					   = m_frame.data[int(j*scaY*m_vidWidth+i*scaX)*3+2];
+					m_vidData[(f*m_texWidth*m_texHeight+j*m_texWidth+i)*3+1]
+					   = m_frame.data[int(j*scaY*m_vidWidth+i*scaX)*3+1];
+					m_vidData[(f*m_texWidth*m_texHeight+j*m_texWidth+i)*3+2]
+					   = m_frame.data[int(j*scaY*m_vidWidth+i*scaX)*3];
+				}
+			}
+			f++;
+		}
+		usleep(1000);
+	}
+
+	vid.release();
+	*/
+}
+
+void RevealedLayerVideo::setAnimPos(const float& pos) {
+    m_video.set(cv::CAP_PROP_POS_FRAMES, 
+                float(m_video.get(cv::CAP_PROP_FRAME_COUNT))*pos);
+    m_update=true;
+}
+
+RevealedLayerAnim::RevealedLayerAnim():RevealedLayer() {
+    m_current=0;
+}
+
+bool RevealedLayerAnim::update(const int& timeDiffMs, const int& depth, 
+                               char* data,
+                               const int& width, const int& height) {
+    bool res=false;
+    if(m_playing) {
+        m_accumTimeDiff+=float(timeDiffMs)*m_speed;
+        if(m_accumTimeDiff>200.0) {
+            m_current++;
+            if(m_current>=int(m_images.size())) {
+                m_current=0;
+            }
+            m_accumTimeDiff=0;
+            m_update=true;
+        }
+    }
+    if(m_update) {
+        Fl_Shared_Image* im = m_images[m_current];
+        for(int i=0; i<width; ++i) {
+            for(int j=0; j<height; ++j) {
+                data[(depth*width*height+j*width+i)*3]
+                   =im->data()[0][(j*im->w()+i)*im->d()];
+                data[(depth*width*height+j*width+i)*3+1]
+                   =im->data()[0][(j*im->w()+i)*im->d()+1];
+                data[(depth*width*height+j*width+i)*3+2]
+                   =im->data()[0][(j*im->w()+i)*im->d()+2];
+            }
+        }
+        res=true;
+        m_update=false;
+    }
+    return res;
+}
+
+void RevealedLayerAnim::setAnimPos(const float& pos) {
+    m_current = float(m_images.size()-1)*pos;
+    m_update=true;
+}
+
+/*
+    GLenum err;
+    while ((err = glGetError()) != GL_NO_ERROR) {
+    }
+    while ((err = glGetError()) != GL_NO_ERROR) {
+        string error;
+        switch(err) {
+            case GL_INVALID_OPERATION:  error="INVALID_OPERATION"; break;
+            case GL_INVALID_ENUM:  error="INVALID_ENUM";           break;
+            case GL_INVALID_VALUE: error="INVALID_VALUE"; break;
+            case GL_OUT_OF_MEMORY: error="OUT_OF_MEMORY"; break;
+            case GL_INVALID_FRAMEBUFFER_OPERATION:  error="INVALID_FRAMEBUFFER_OPERATION";  break;
+        }
+        cout << "OpenGL error before draw: " << error << endl;
+    }
+*/
+
diff --git a/src/modules/RevealedModule.hpp b/src/modules/RevealedModule.hpp
new file mode 100644
index 0000000..72b4ff4
--- /dev/null
+++ b/src/modules/RevealedModule.hpp
@@ -0,0 +1,469 @@
+/***************************************************************************
+ *  RevealedModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef RevealedModule_h
+#define RevealedModule_h
+
+#include "GeomModule.hpp"
+#include "opencv2/opencv.hpp"
+#include <FL/Fl_Shared_Image.H>
+#include <sys/time.h>
+#include <thread>
+#include <mutex>
+
+struct RevealedLayer;
+
+class RevealedModule : public virtual GeomModule {
+    public:
+        RevealedModule();
+        virtual ~RevealedModule();
+        void deleteModule();
+
+        void draw(const int& contextID,
+                  const Reveal::REVIL_PROGRAM& prog, 
+                  std::map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                  const unsigned int& comp=0);
+
+        static void colorCallback(Module* mod, 
+                                  const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setColor(vals);
+        }
+        virtual void setColor(const std::vector<float>&);
+
+        static void insideVisibleCallback(Module* mod, 
+									   const std::vector<bool>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setInsideVisible(vals[0]);
+        }
+        virtual void setInsideVisible(bool v){m_insideVisible=v;}
+
+        static void insideAxesCallback(Module* mod, 
+                                       const std::vector<std::string>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setInsideAxes(vals[0]);
+        }
+        virtual void setInsideAxes(const std::string&);
+
+        static void insideStructureCallback(Module* mod, 
+                                       const std::vector<std::string>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setInsideStructure(vals[0]);
+        }
+        virtual void setInsideStructure(const std::string&);
+
+        virtual void generateSurfaceDistanceTexture(const std::string& f);
+        virtual void openSurfaceDistanceTexture(const std::string& f);
+
+        static void structureRatioCallback(Module* mod, 
+                                    const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setStructureRatio(vals[0]);
+        }
+        virtual void setStructureRatio(const float& r){m_structureRatio=r;}
+
+		//Gradient
+        static void gradientAlphaCallback(Module* mod, 
+                                    const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setGradientAlpha(vals[0]);
+        }
+        virtual void setGradientAlpha(const float& a){m_insideGradientAlpha=a;}
+
+        static void gradientTypeCallback(Module* mod, 
+                                       const std::vector<std::string>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setGradientType(vals[0]);
+        }
+        virtual void setGradientType(const std::string&);
+
+        static void gradientStepsCallback(Module* mod, 
+                                    const std::vector<int>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setGradientSteps(vals[0]);
+        }
+        virtual void setGradientSteps(const int& s){m_insideGradientSteps=s;}
+
+        static void gradientCurveRatioCallback(Module* mod, 
+                                    const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setGradientCurveRatio(vals[0]);
+        }
+        virtual void setGradientCurveRatio(const float& r){
+			m_insideGradientCurveRatio=r;
+		}
+
+        static void gradientTextureCallback(Module* mod, 
+											const std::string& val) {
+            dynamic_cast<RevealedModule*>(mod)->setGradientTexture(val);
+        }
+        virtual void setGradientTexture(const std::string&);
+
+
+		//Texture
+        static void textureAlphaCallback(Module* mod, 
+                                    const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setTextureAlpha(vals[0]);
+        }
+        virtual void setTextureAlpha(const float& a){m_insideTextureAlpha=a;}
+
+        static void textureBlendCallback(Module* mod, 
+                                    const std::vector<bool>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setTextureBlend(vals[0]);
+        }
+        virtual void setTextureBlend(bool b);
+
+        static void textureGrayscaleCallback(Module* mod, 
+                                    const std::vector<bool>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setTextureGrayscale(vals[0]);
+        }
+        virtual void setTextureGrayscale(bool b){m_textureGrayscale=b;}
+
+
+        static void textureCallback(Module* mod, const std::string& f) {
+            dynamic_cast<RevealedModule*>(mod)->setTexture(f);
+        }
+        virtual void setTexture(const std::string& f);
+
+        static void textureLayersFolderCallback(Module* mod, 
+                                                const std::string& f) {
+            dynamic_cast<RevealedModule*>(mod)->setTextureLayersFolder(f);
+        }
+        virtual void setTextureLayersFolder(const std::string& f);
+
+
+        static void textureOffsetCallback(Module* mod, 
+                                          const std::vector<float>& f) {
+            dynamic_cast<RevealedModule*>(mod)
+                                ->setTextureOffset(f[0],f[1],f[2]);
+        }
+        virtual void setTextureOffset(const float& x, 
+                                      const float& y,
+                                      const float& z);
+        static void textureScaleCallback(Module* mod, 
+                                         const std::vector<float>& f) {
+            dynamic_cast<RevealedModule*>(mod)
+                                ->setTextureScale(f[0],f[1],f[2]);
+        }
+        virtual void setTextureScale(const float& x, 
+                                     const float& y,
+                                     const float& z);
+		
+        static void textureReactCallback(Module* mod, 
+                                         const std::vector<std::string>& s) {
+            dynamic_cast<RevealedModule*>(mod)->setTextureReact(s[0]);
+        }
+        virtual void setTextureReact(const std::string& s);
+
+        static void animPosCallback(Module* mod, 
+                                      const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setAnimPos(vals[0]);
+        }
+        virtual void setAnimPos(const float&);
+        static void animPlayCallback(Module* mod, 
+                                     const std::vector<bool>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setAnimPlay(vals[0]);
+        }
+        virtual void setAnimPlay(const bool&);
+        static void animSpeedCallback(Module* mod, 
+                                      const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setAnimSpeed(vals[0]);
+        }
+        virtual void setAnimSpeed(const float&);
+
+		//Density
+        static void densityAlphaCallback(Module* mod, 
+                                    const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setDensityAlpha(vals[0]);
+        }
+        virtual void setDensityAlpha(const float& a){m_insideDensityAlpha=a;}
+
+        static void densityTypeCallback(Module* mod, 
+                                    const std::vector<std::string>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setDensityType(vals[0]);
+        }
+        virtual void setDensityType(const std::string& t);
+
+        static void densityRatioCallback(Module* mod, 
+                                    const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setDensityRatio(vals[0]);
+        }
+        virtual void setDensityRatio(const float& r){m_insideDensityRatio=r;}
+
+        static void densitySizeCallback(Module* mod, 
+                                    const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setDensitySize(vals[0]);
+        }
+        virtual void setDensitySize(const float& s){m_insideDensitySize=s;}
+
+        static void densityCurveRatioCallback(Module* mod, 
+                                    const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setDensityCurveRatio(vals[0]);
+        }
+        virtual void setDensityCurveRatio(const float& r) { 
+			m_insideDensityCurveRatio=r;
+		}
+
+		//Surface
+        static void surfaceCallback(Module* mod, 
+                                   const std::vector<std::string>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setSurface(vals[0]);
+        }
+        virtual void setSurface(const std::string&);
+
+        static void surfaceColorCallback(Module* mod, 
+                                   const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setSurfaceColor(vals);
+        }
+        virtual void setSurfaceColor(const std::vector<float>&);
+
+        static void surfaceThicknessCallback(Module* mod, 
+                                    const std::vector<float>& vals) {
+            dynamic_cast<RevealedModule*>(mod)->setSurfaceThickness(vals[0]);
+        }
+        virtual void setSurfaceThickness(const float&);
+
+        static void surfaceTextureCallback(Module* mod, const std::string& f) {
+            dynamic_cast<RevealedModule*>(mod)->setSurfaceTexture(f);
+        }
+        virtual void setSurfaceTexture(const std::string& f);
+
+		//Revealed 
+        static void revnamCallback(Module* mod, 
+                                   const std::vector<std::string>& vals){}
+        static void revsurCallback(Module* mod,const std::vector<float>& vals){}
+        static void revinsCallback(Module* mod,const std::vector<float>& vals){}
+        static void revcentCallback(Module* mod,const std::vector<float>&vals){}
+        static void revextCallback(Module* mod,const std::vector<float>&vals){}
+        static void revcolCallback(Module* mod,const std::vector<float>& vals){}
+        static void revhistoCallback(Module* mod,const std::vector<float>&vals){}
+        static void revvoxelCallback(Module* mod,const std::vector<float>&vals){}
+
+
+        inline bool isOutputActive(){return m_outputActive;}
+
+        inline void setRevID(const unsigned int& id) { 
+            m_revID = id;
+            m_revIDBit = double(1<<(int(id)%15));
+        }
+        inline const unsigned int& getRevID(){return m_revID;}
+        inline const float& getRevIDBit(){return m_revIDBit;}
+		void updateRevOffset(unsigned int& offset);
+
+        void gotAttributeListenersUpdate(Attribute*);
+
+
+		//Updating
+        virtual void update(const int& timeDiffMs);
+
+        virtual void processReveal(const unsigned int& depthId,
+                                   const std::string& depthName, 
+								   const unsigned int& depthNb,
+								   unsigned int* outputImg);
+		void textureReact();
+
+
+		//utilities
+        void hsv2rgb(const std::vector<float>& hsv, 
+                     std::vector<float>& rgb);
+
+        void addRevealedAttributes();
+        void addRevealedInsideAttributes();
+        void addRevealedInsideStructureAttributes();
+        void addRevealedInsideGradientAttributes();
+        void addRevealedInsideDensityAttributes();
+        void addRevealedInsideTextureAttributes();
+        void addRevealedOutputAttributes();
+
+		void parsePvm(const std::string& file, 
+					  glm::ivec3& dimensions, 
+					  std::vector<float>& data);
+
+    protected:
+        unsigned int m_revID;
+        float m_revIDBit;
+        std::vector<float> m_color;
+        std::vector<float> m_surfaceColor;
+		int m_shapeGeom;
+        int m_surface;
+        std::vector<std::string> m_surfaces;
+        float m_surfaceThickness;
+
+        int m_inside;
+		bool m_insideVisible;
+
+        std::vector<std::string> m_insideAxes;
+		int m_insideStructure;
+        std::vector<std::string> m_insideStructures;
+		float m_structureRatio;
+
+		float m_insideGradientAlpha;
+        int m_gradientType;
+        std::vector<std::string> m_gradientTypes;
+		int m_insideGradientSteps; //0-10
+		float m_insideGradientCurveRatio; //sign/linearity (-y -> -pow(x,y))
+        std::map<int, bool> m_gradientUpMap;
+        std::map<int, GLuint> m_gradientIDMap;
+        Fl_Shared_Image* m_gradientImage;
+
+		float m_insideDensityAlpha;
+		int m_insideDensityType;
+        std::vector<std::string> m_insideDensityTypes;
+		float m_insideDensityRatio;
+		float m_insideDensitySize;
+		float m_insideDensityCurveRatio;
+
+		float m_insideTextureAlpha;
+		bool m_insideTextureBlend;
+        float m_textureOffset[3];
+        float m_textureScale[3];
+        std::vector<std::string> m_reactivityTypes;
+		int m_reactivityType;
+		bool m_textureGrayscale;
+		bool m_textureCanDelete;
+
+        std::map<int, bool> m_surfaceUpMap;
+        std::map<int, GLuint> m_surfaceIDMap;
+        Fl_Shared_Image* m_surfaceImage;
+        char* m_layersData;
+        std::map<int, bool> m_insideUpMap;
+        std::map<int, GLuint> m_insideIDMap;
+        int m_layersNb;
+        std::vector<Fl_Shared_Image*> m_layersImages;
+        Fl_Shared_Image* m_insideImage;
+        std::vector<RevealedLayer*> m_layers;
+        std::map<int, GLuint> m_coordsIDMap;
+        std::map<int, bool> m_coordsUpMap;
+        std::map<unsigned int, bool> m_depthModsMap;
+        int m_volumeTextureWidth;
+        int m_volumeTextureHeight;
+
+        //std::vector<std::string> m_texMirrors;
+
+        bool m_outputActive;
+        std::vector<Attribute*> m_revAttributes;
+		int m_revOffset, m_revSize;
+        int m_revSurf, m_revIns, m_revCent, m_revCol, m_revHis, m_revVox;
+        int m_outShapeSize;
+        int m_outVoxelSize;
+        int m_outHistoSize;
+        int m_outDepthSize;
+        int m_outNbDepth;
+
+        std::thread* m_reactThread;
+        std::mutex m_reactLock;
+		bool m_reactActive;
+		int m_voxDim;
+		int m_voxSize;
+		float *m_reactTexInput, *m_reactTexInternal;
+	   	char *m_reactTexOutput;
+        std::map<int, bool> m_reactUpMap;
+        std::map<int, GLuint> m_reactIDMap;
+
+		glm::ivec3 m_surfDistDims;
+		std::vector<float> m_surfDistData;
+
+        int m_timeDiffMs;
+};
+
+class RevealedLayer {
+    public:
+        RevealedLayer();
+        virtual ~RevealedLayer(){}
+        virtual bool update(const int& timeDiffMs, const int& depth, 
+                            char* data, const int& width, const int& height)=0;
+        virtual void setAnimPos(const float& pos){}
+        virtual void setAnimPlay(const bool& play){m_playing=play;}
+        virtual void setAnimSpeed(const float& speed){m_speed=speed;}
+		virtual void releaseData(){}
+    protected:
+        bool m_playing;
+        float m_speed;
+        bool m_update;
+        int m_accumTimeDiff;
+};
+
+class RevealedLayerVideo: public RevealedLayer {
+    public:
+        RevealedLayerVideo(const int& w, const int& h):RevealedLayer(){
+            m_texWidth=w;
+            m_texHeight=h;
+            m_thread=NULL;
+            m_data = new char[w*h*3];
+            m_gotFrame=false;
+			m_vidData = NULL;
+        }
+        virtual bool update(const int& timeDiffMs, const int& depth, 
+                            char* data, const int& width, const int& height);
+        virtual void setAnimPos(const float& pos);
+		virtual void setVideo(cv::VideoCapture vid);
+        static void* videoReadThreadFunction(void* pvParam) {
+            RevealedLayerVideo *pThis=(RevealedLayerVideo*)pvParam;
+            pThis->read();
+            return NULL;
+        }
+
+        virtual void setAnimPlay(const bool& play) {
+            if(play && !m_playing) {
+                m_playing=play;
+                gettimeofday(&m_prevTime,NULL);
+				m_curFrame=0;
+                m_thread = new std::thread(videoReadThreadFunction, this);
+            }
+            else if(!play && m_playing) {
+                if(m_thread) {
+                    m_playing=play;
+                    m_thread->join();
+                    delete m_thread;
+                    m_thread=NULL;
+                }
+            }
+        }
+        void read();
+
+        cv::VideoCapture m_video;
+        cv::Mat m_frame;
+		int m_texWidth, m_texHeight;
+		int m_vidWidth, m_vidHeight;
+		int m_vidFrames, m_vidFps;
+		char* m_vidData;
+        std::thread* m_thread;
+        std::mutex m_lock;
+        bool m_gotFrame;
+        char* m_data;
+        timeval m_prevTime;
+		int m_curFrame;
+};
+
+class RevealedLayerImage : public RevealedLayer {
+    public:
+        RevealedLayerImage():RevealedLayer(){}
+        virtual bool update(const int& timeDiffMs, const int& depth, 
+                            char* data, const int& width, const int& height);
+		virtual void releaseData(){m_image->release();}
+        Fl_Shared_Image* m_image;
+};
+
+class RevealedLayerAnim : public RevealedLayer {
+    public:
+        RevealedLayerAnim();
+        virtual bool update(const int& timeDiffMs, const int& depth, 
+                            char* data, const int& width, const int& height);
+        virtual void setAnimPos(const float& pos);
+        std::vector<Fl_Shared_Image*> m_images;
+        int m_current;
+};
+
+#endif
+
diff --git a/src/modules/RevealedPathModule.cpp b/src/modules/RevealedPathModule.cpp
new file mode 100644
index 0000000..b78eed0
--- /dev/null
+++ b/src/modules/RevealedPathModule.cpp
@@ -0,0 +1,446 @@
+/***************************************************************************
+ *  RevealedPathModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "RevealedPathModule.hpp" 
+
+#include <iostream>
+#include <glm/gtx/quaternion.hpp>
+
+#include "../Reveal.hpp"
+
+#include "../geoms/Geometry.hpp"
+
+using namespace std;
+using namespace glm;
+
+RevealedPathModule::RevealedPathModule(): RevealedModule() {
+    m_type="Path";
+    m_name="path";
+
+    m_pathGeom = new Geometry();
+    Reveal::getInstance()->registerGeom(m_pathGeom);
+    m_pathGeom->registerModule(this);
+
+    addNameAttribute();
+    addRemoveAttribute();
+    addVisibleAttribute();
+    addVisibleFromAttribute();
+    addRevealedByAttribute();
+    addAttribute(new Attribute("add_point", 
+                                Attribute::ACTION_FLOAT_ATTRIBUTE,
+                                addPointCallback, this, 3));
+    addAttribute(new Attribute("add_module_point", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addModulePointCallback, this, 1));
+    addAttribute(new Attribute("remove_last_point", 
+                                Attribute::ACTION_ATTRIBUTE,
+                                removePointCallback, this));
+    addAttribute(new Attribute("clear_points", 
+                                Attribute::ACTION_ATTRIBUTE,
+                                clearPointsCallback, this));
+    addAttribute(new Attribute("thickness", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                thicknessCallback, this, 1));
+    addAttribute(new Attribute("edges", 
+                                Attribute::INT_ATTRIBUTE,
+                                edgesCallback, this, 1));
+    //addTransformationAttributes();
+    addRevealedAttributes();
+    addRevealedInsideAttributes();
+    addRevealedOutputAttributes();
+
+    m_attributesMap["inside_structure"]->setStrings(vector<string>(1,"along_z"));
+    m_attributesMap["surface_thickness"]->setFloats(vector<float>(1,0.05));
+
+    m_attributesMap["thickness"]->setFloats(vector<float>(1,100));
+    m_attributesMap["edges"]->setInts(vector<int>(1,8));
+    m_attributesMap["gradient_type"]->setStrings(vector<string>(1, "along_z"));
+    vector<string> mods(1, "select_module");
+    m_attributesMap["add_module_point"]->editStringValuesChoices()
+                                            .assign(1,mods);
+    Reveal::getInstance()->addModuleListObserver(this);
+
+    m_shapeGeom=Reveal::GEOM_PATH;
+	m_pathInitialised=2;
+}
+
+RevealedPathModule::~RevealedPathModule() {
+    Reveal::getInstance()->unregisterGeom(m_pathGeom);
+}
+
+void RevealedPathModule::load(xmlNodePtr node) {
+    Module::load(node);
+    xmlNodePtr pntsNode;
+    for(pntsNode=node->children; pntsNode; pntsNode=pntsNode->next){
+        if(pntsNode->type == XML_ELEMENT_NODE &&
+                !xmlStrcmp(pntsNode->name, (const xmlChar *) "Points")) {
+            xmlNodePtr pntNode;
+            for(pntNode=pntsNode->children; pntNode; pntNode=pntNode->next){
+                if(pntNode->type == XML_ELEMENT_NODE) {
+                    if(!xmlStrcmp(pntNode->name, (const xmlChar *) "Point")) {
+                        m_points.push_back(new PathPoint(glm::vec4(0,0,0,1)));
+                        m_points.back()->loadPnt(pntNode);
+                    }
+                    else if(!xmlStrcmp(pntNode->name, 
+                                       (const xmlChar *) "PointModule")) {
+                        m_points.push_back(new PathPointModule(this));
+                        m_points.back()->loadPnt(pntNode);
+                    }
+                }
+            }
+        }
+    }
+    refreshGeometry();    
+}
+
+xmlNodePtr RevealedPathModule::save(xmlNodePtr parentNode) {
+    xmlNodePtr newNode = Module::save(parentNode);
+    xmlNodePtr pntsNode = xmlNewChild(newNode, NULL, BAD_CAST"Points", NULL);
+    vector<PathPoint*>::iterator itPnt = m_points.begin();
+    for(; itPnt!=m_points.end(); ++itPnt) {
+        (*itPnt)->savePnt(pntsNode);
+    }
+    return newNode;
+}
+
+void RevealedPathModule::addPoint(const float& x,   
+                                  const float& y, 
+                                  const float& z) {
+    m_points.push_back(new PathPoint(glm::vec4(x, y, z, 1)));
+    refreshGeometry();
+}
+
+void RevealedPathModule::updateModulesList(const map<string, Module*>& mods) {
+
+    vector<vector<string> >& moduleNames = m_attributesMap["add_module_point"]
+                                                ->editStringValuesChoices();
+    moduleNames.clear();
+    moduleNames.push_back(vector<string>());
+    map<string, Module*>::const_iterator itMod = mods.begin();
+    for(; itMod!=mods.end(); ++itMod) { //select names from scene modules
+        if(itMod->first.find("/revil/scene/")==0) {
+            moduleNames[0].push_back(itMod->first);
+        }
+    }
+}
+
+void RevealedPathModule::addModulePoint(const std::string& moduleStr) {
+    Module* mod = NULL;
+    mod = Reveal::getInstance()->findModule(moduleStr);
+    if(mod) {
+        m_points.push_back(new PathPointModule(this, mod));
+        refreshGeometry();
+    }
+}
+
+void RevealedPathModule::removePoint() {
+    if(m_points.size()>0) {
+        PathPoint* pnt = m_points.back();
+        delete pnt;
+        m_points.pop_back();
+        refreshGeometry();
+    }
+}
+
+void RevealedPathModule::clearPoints() {
+    for(unsigned int p=0; p<m_points.size(); ++p) {
+        PathPoint* pnt = m_points[p];
+        delete pnt;
+    }
+    m_points.clear();
+    refreshGeometry();
+}
+
+void RevealedPathModule::refreshGeometry() {
+    //refresh local position of all points 
+    for(unsigned int p=0; p<m_points.size(); ++p) {
+        m_points[p]->refreshPos();
+    }
+
+    vector<GLfloat>& vertices = m_pathGeom->editVertexBufferData();
+    vector<GLuint>& indices = m_pathGeom->editIndexBufferData();
+    vector<int>& sizes = m_pathGeom->editCompoSizes();
+    
+    vertices.clear();
+    indices.clear();
+    sizes.clear();
+    m_compoLocalSizes.clear();
+    m_compoVertices.clear();
+    m_compoRots.clear();
+
+    m_subShapeInvMats.clear();
+
+    if(m_points.size()>0) {
+        //create all vertices
+        glm::vec3 dirZ(0, 0, 1);
+        unsigned int preC=0;
+        unsigned int nexC=0;
+        for(unsigned int p=0; p<m_points.size(); ++p) {
+            glm::mat4 rot=glm::mat4(1.0);
+
+            //find the corresponding component
+            if(m_points.size()<3) {
+                preC=0;
+                nexC=0;
+            }
+            else {
+                preC=(p<=0)?0:int(p)-1;
+                nexC=(p>=(m_points.size()-1))?p-1:p;
+            }
+			
+			glm::vec3 dir(0.0);
+            if(p>0) {
+                dir = glm::vec3(m_points[p]->editPos()
+                                - m_points[int(p)-1]->editPos());
+                glm::vec3 dirN = normalize(dir);
+                //rot = toMat4(rotation(dirZ, dirN));
+				glm::vec3 markR(1.0,0.0,0.0);
+				glm::vec3 markUp = 
+					glm::normalize(glm::cross(markR, dirN));
+				rot = glm::mat4x4( //r,up,n
+					markR[0], markR[1], markR[2], 0.0,
+					markUp[0], markUp[1], markUp[2],0.0,
+					dirN[0], dirN[1], dirN[2], 0.0,
+					0.0, 0.0, 0.0, 1.0
+					);
+                m_compoLocalSizes[preC] = 
+                    glm::vec4(m_thickness, m_thickness, length(dir), 1.0);
+
+				//build and store sub inverse matrix
+				mat4 subMat = scale(vec3(m_thickness,
+										m_thickness,
+										length(dir)));
+				subMat = rot * subMat;
+				subMat = translate(vec3(m_points[int(p)-1]->editPos()
+									+ vec4(dir.x/2.0,dir.y/2.0,dir.z/2.0,1.0)))
+						 * subMat;
+				m_subShapeInvMats.push_back(inverse(subMat));
+            }
+            else if(m_points.size()>1) {
+                dir = glm::vec3(m_points[p+1]->editPos()
+								- m_points[p]->editPos());
+                glm::vec3 dirN = normalize(dir);
+                rot = toMat4(rotation(dirZ, dirN));
+                m_compoLocalSizes[preC] = 
+                    glm::vec4(m_thickness,m_thickness, length(dir), 1.0);
+            }
+
+            //add the vertices
+            float angle=0;
+            float angleStep=M_PI*2.0/float(m_nbEdges);
+            for(int v=0; v<m_nbEdges; ++v, angle+=angleStep) {
+                glm::vec4 pnt = m_points[p]->editPos()
+                                  +rot*glm::vec4(cos(angle)*m_thickness, 
+                                                 sin(angle)*m_thickness, 
+                                                 0, 1);
+                vertices.push_back(pnt[0]);
+                vertices.push_back(pnt[1]);
+                vertices.push_back(pnt[2]);
+                vertices.push_back(0);
+                vertices.push_back(0);
+
+                m_compoVertices[nexC].push_back(pnt);
+                m_compoVertices[preC].push_back(pnt);
+            }
+
+            //save rotations/dirs
+            m_compoRots[nexC]=rot;
+            m_compoRots[preC]=rot;
+        }
+
+        //indices
+        if(m_points.size()>1) {
+            //create segments and backs
+            for(int s=0; s<int(m_points.size())-1; ++s) {
+                for(int v=0; v<m_nbEdges-2; ++v) {
+                    indices.push_back(s*m_nbEdges+v);
+                    indices.push_back(s*m_nbEdges+m_nbEdges-1);
+                    indices.push_back(s*m_nbEdges+v+1);
+                }
+                for(int v=0; v<m_nbEdges; ++v) {
+                    indices.push_back((s*m_nbEdges)+v);
+                    indices.push_back((s*m_nbEdges)+(v+1)%m_nbEdges);
+                    indices.push_back(((s+1)*m_nbEdges)+v);
+
+                    indices.push_back(((s+1)*m_nbEdges)+v);
+                    indices.push_back((s*m_nbEdges)+(v+1)%m_nbEdges);
+                    indices.push_back(((s+1)*m_nbEdges)+(v+1)%m_nbEdges);
+                }
+                for(int v=0; v<m_nbEdges-2; ++v) {
+                    indices.push_back((s+1)*m_nbEdges+v);
+                    indices.push_back((s+1)*m_nbEdges+v+1);
+                    indices.push_back((s+1)*m_nbEdges+m_nbEdges-1);
+                }
+                sizes.push_back(m_nbEdges*6+2*(m_nbEdges-2)*3);
+            }
+        }
+    }
+    m_pathGeom->refresh();
+}
+
+void RevealedPathModule::setThickness(const float& t) {
+    if(t>0) {
+        m_thickness=t;
+    }
+    refreshGeometry();
+}
+
+void RevealedPathModule::setEdges(const int& e) {
+    if(e>=3) {
+        m_nbEdges=e;
+    }
+    refreshGeometry();
+}
+
+void RevealedPathModule::updateModelMatrix() {
+    GeomModule::updateModelMatrix();
+    
+}
+
+void RevealedPathModule::processReveal(const vector<string>& names,
+                                       const vector<float>& surfaces, 
+                                       const vector<float>& insides,
+                                       const vector<float>& center, 
+                                       const vector<float>& extent,
+                                       const vector<float>& color) {
+
+    m_attributesMap["revealed_name"]->setStringsIfChanged(names);
+    m_attributesMap["revealed_surface"]->setFloatsIfChanged(surfaces);
+    m_attributesMap["revealed_inside"]->setFloatsIfChanged(insides);
+    m_attributesMap["revealed_center"]->setFloatsIfChanged(center);
+    m_attributesMap["revealed_extent"]->setFloatsIfChanged(extent);
+    m_attributesMap["revealed_color"]->setFloatsIfChanged(color);
+}
+
+void RevealedPathModule::draw(const int& contextID,
+							  const Reveal::REVIL_PROGRAM& prog, 
+							  map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+							  const unsigned int& comp){
+
+	RevealedModule::draw(contextID,prog,uniforms,comp);
+
+	if(m_pathInitialised>0) {
+		refreshGeometry();
+		m_pathInitialised--;
+	}
+}
+
+
+//-------------------------Path Points---------------------------------------
+
+void PathPoint::loadPnt(xmlNodePtr node) {
+    char* value = (char*)xmlGetProp(node, (xmlChar*)"x");
+    if(value!=NULL) {
+        m_point[0]=atof(value);
+    }
+    value = (char*)xmlGetProp(node, (xmlChar*)"y");
+    if(value!=NULL) {
+        m_point[1]=atof(value);
+    }
+    value = (char*)xmlGetProp(node, (xmlChar*)"z");
+    if(value!=NULL) {
+        m_point[2]=atof(value);
+    }
+}
+
+xmlNodePtr PathPoint::savePnt(xmlNodePtr parentNode) {
+    ostringstream oss, oss1, oss2;
+    xmlNodePtr pntNode = xmlNewChild(parentNode, NULL, BAD_CAST "Point", NULL);
+    oss<<m_point[0];
+    oss1<<m_point[1];
+    oss2<<m_point[2];
+    xmlNewProp(pntNode, BAD_CAST "x", BAD_CAST oss.str().c_str());
+    xmlNewProp(pntNode, BAD_CAST "y", BAD_CAST oss1.str().c_str());
+    xmlNewProp(pntNode, BAD_CAST "z", BAD_CAST oss2.str().c_str());
+    return pntNode;
+}
+
+PathPointModule::PathPointModule(RevealedPathModule* path): 
+                                    PathPoint(), Listener(), m_module(NULL) {
+    m_path=path;
+    m_listenerType="PathListener";
+}
+
+PathPointModule::PathPointModule(RevealedPathModule* path, 
+                                 Module* mod): PathPoint(), Listener() {
+    m_path=path;
+    m_listenerType="PathListener";
+    m_module=mod;
+    m_module->getAttribute("absolute_position")->addListener(this);
+}
+
+PathPointModule::~PathPointModule() {
+    if(m_module) {
+        m_module->getAttribute("absolute_position")->removeListener(this);
+    }
+}
+
+void PathPointModule::update(vector<float>& floatValues,
+                             vector<int>& intValues,
+                             vector<bool>& boolValues,
+                             vector<string>& stringValues) {
+    if(floatValues.size()>=3) {
+        m_path->refreshGeometry();
+    }
+}
+
+void PathPointModule::refreshPos() {
+    if(m_module) {
+        const vector<float>& floatValues = m_module
+                                            ->getAttribute("absolute_position")
+                                                ->getFloats();
+        m_absPoint[0]=floatValues[0];
+        m_absPoint[1]=floatValues[1];
+        m_absPoint[2]=floatValues[2];
+        m_absPoint[3]=1;
+        m_point = inverse(m_path->getModelMat())*m_absPoint;
+    }
+    else {
+        m_module=Reveal::getInstance()->findModule(m_moduleName);
+        if(m_module) {
+            m_module->getAttribute("absolute_position")->addListener(this);
+        }
+    }
+}
+
+void PathPointModule::loadPnt(xmlNodePtr node) {
+    char* value = (char*)xmlGetProp(node, (xmlChar*)"module_name");
+    if(value!=NULL) {
+        m_moduleName=string(value);
+        m_module=Reveal::getInstance()->findModule(m_moduleName);
+        if(m_module) {
+            m_module->getAttribute("absolute_position")->addListener(this);
+        }
+    }
+}
+
+xmlNodePtr PathPointModule::savePnt(xmlNodePtr parentNode) {
+    xmlNodePtr pntNode=xmlNewChild(parentNode, NULL, 
+                                   BAD_CAST"PointModule",NULL);
+    if(m_module) {
+        xmlNewProp(pntNode, BAD_CAST"module_name", 
+                            BAD_CAST m_module->getFullName().c_str());
+    }
+    return pntNode;
+}
+
diff --git a/src/modules/RevealedPathModule.hpp b/src/modules/RevealedPathModule.hpp
new file mode 100644
index 0000000..c815025
--- /dev/null
+++ b/src/modules/RevealedPathModule.hpp
@@ -0,0 +1,134 @@
+/***************************************************************************
+ *  RevealedPathModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef RevealedPathModule_h
+#define RevealedPathModule_h
+
+#include "RevealedModule.hpp"
+
+class PathPoint;
+class PathPointModule;
+
+class RevealedPathModule : public RevealedModule, public ModuleListObserver {
+    public:
+        RevealedPathModule();
+        virtual ~RevealedPathModule();
+
+        virtual void load(xmlNodePtr node);
+        virtual xmlNodePtr save(xmlNodePtr parentNode);
+
+        static void addPointCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            dynamic_cast<RevealedPathModule*>(mod)->addPoint(vals[0], 
+                                                             vals[1], 
+                                                             vals[2]);
+        }
+        void addPoint(const float& x, const float& y, const float& z);
+        static void addModulePointCallback(Module* mod,
+                                    const std::vector<std::string>& vals) {
+            dynamic_cast<RevealedPathModule*>(mod)->addModulePoint(vals[0]);
+        }
+        void addModulePoint(const std::string&);
+        static void removePointCallback(Module* mod) {
+            dynamic_cast<RevealedPathModule*>(mod)->removePoint();
+        }
+        void removePoint();
+
+        static void clearPointsCallback(Module* mod) {
+            dynamic_cast<RevealedPathModule*>(mod)->clearPoints();
+        }
+        void clearPoints();
+        static void thicknessCallback(Module* mod, 
+                                      const std::vector<float>& vals) {
+            dynamic_cast<RevealedPathModule*>(mod)->setThickness(vals[0]);
+        }
+        void setThickness(const float& t);
+        static void edgesCallback(Module* mod, 
+                                  const std::vector<int>& vals) {
+            dynamic_cast<RevealedPathModule*>(mod)->setEdges(vals[0]);
+        }
+        void setEdges(const int& e);
+
+        void refreshGeometry();
+        void updateModelMatrix();
+        virtual void processReveal(const std::vector<std::string>&, 
+                           const std::vector<float>&,const std::vector<float>&,
+                           const std::vector<float>&,const std::vector<float>&,
+                           const std::vector<float>&);
+
+        virtual void updateModulesList(const std::map<std::string, Module*>&);
+
+        void draw(const int& contextID,
+                  const Reveal::REVIL_PROGRAM& prog, 
+                  std::map<Reveal::REVIL_UNIFORM, GLint>& uniforms,
+                  const unsigned int& comp=0);
+
+    protected:
+        std::vector<PathPoint*> m_points;
+        std::map<unsigned int, std::vector<glm::vec4> > m_compoVertices;
+        std::map<unsigned int, glm::mat4> m_compoRots;
+        std::map<unsigned int, glm::vec4> m_compoLocalSizes;
+        float m_thickness;
+        int m_nbEdges;
+        Geometry* m_pathGeom;
+		int m_pathInitialised;
+};
+
+class PathPoint {
+    public:
+        PathPoint(){}
+        PathPoint(glm::vec4 pnt):m_point(pnt){}
+        virtual ~PathPoint(){}
+        inline const glm::vec4& getPos(){return m_point;}
+        inline glm::vec4& editPos(){return m_point;}
+        virtual void loadPnt(xmlNodePtr node);
+        virtual xmlNodePtr savePnt(xmlNodePtr parentNode);
+        virtual void refreshPos(){}
+
+    protected:
+        glm::vec4 m_point;
+        glm::vec4 m_absPoint;
+};
+
+class PathPointModule : public PathPoint, public Listener {
+    public:
+        PathPointModule(RevealedPathModule*);
+        PathPointModule(RevealedPathModule*, Module*);
+        virtual ~PathPointModule();
+        virtual void update(std::vector<float>& floatValues, 
+                            std::vector<int>& intValues,
+                            std::vector<bool>& boolValues,
+                            std::vector<std::string>& stringValues);
+        virtual void loadPnt(xmlNodePtr node);
+        virtual xmlNodePtr savePnt(xmlNodePtr parentNode);
+        virtual void refreshPos();
+
+    protected:
+        RevealedPathModule* m_path;
+        Module* m_module;
+        std::string m_moduleName;
+};
+
+
+#endif
+
diff --git a/src/modules/RevealedShapeModule.cpp b/src/modules/RevealedShapeModule.cpp
new file mode 100644
index 0000000..16440fc
--- /dev/null
+++ b/src/modules/RevealedShapeModule.cpp
@@ -0,0 +1,76 @@
+/***************************************************************************
+ *  RevealedShapeModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "RevealedShapeModule.hpp" 
+
+#include "../geoms/Geometry.hpp"
+
+using namespace std;
+
+RevealedShapeModule::RevealedShapeModule(): ShapeModule(), RevealedModule(){
+    m_type="Shape";
+    m_name="shape";
+    addNameAttribute();
+    addRemoveAttribute();
+    addVisibleAttribute();
+    addVisibleFromAttribute();
+    addRevealedByAttribute();
+    addShapeAttributes();
+    addTransformationAttributes();
+	addFollowMarkerAttribute();
+    addRevealedAttributes();
+    addRevealedInsideAttributes();
+    addRevealedOutputAttributes();
+	/*
+    vector<string> inside(1, "color_gradient");
+    m_attributesMap["inside"]->setStrings(inside);
+	*/
+    vector<string> shape(1, "sphere");
+    m_attributesMap["shape"]->setStrings(shape);
+    vector<float> dims(3,200.0);
+    m_attributesMap["dimensions"]->setFloats(dims);
+}
+
+RevealedShapeModule::~RevealedShapeModule() {
+    Reveal::getInstance()
+                ->getGeom(m_shapesMap[m_currentShape])
+                                ->unregisterModule(this);
+}
+
+void RevealedShapeModule::setShape(const std::string& shape) {
+	if(m_shapesMap.find(shape)!=m_shapesMap.end()) {
+        if(m_currentShape.compare("")!=0) {
+            Reveal::getInstance()
+                ->getGeom(m_shapesMap[m_currentShape])
+                    ->unregisterModule(this);
+        }
+        m_currentShape=shape;
+        Reveal::getInstance()
+            ->getGeom(m_shapesMap[m_currentShape])
+                ->registerModule(this);
+        m_currentGeom=Reveal::getInstance()
+                        ->getGeom(m_shapesMap[m_currentShape]);
+		m_shapeGeom = m_shapesMap[m_currentShape];
+    }
+}
+
diff --git a/src/modules/RevealedShapeModule.hpp b/src/modules/RevealedShapeModule.hpp
new file mode 100644
index 0000000..fdfdfc4
--- /dev/null
+++ b/src/modules/RevealedShapeModule.hpp
@@ -0,0 +1,44 @@
+/***************************************************************************
+ *  RevealedShapeModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef RevealedShapeModule_h
+#define RevealedShapeModule_h
+
+#include "ShapeModule.hpp"
+#include "RevealedModule.hpp"
+
+class RevealedShapeModule : public ShapeModule, public RevealedModule {
+    public:
+        RevealedShapeModule();
+        virtual ~RevealedShapeModule();
+        void gotAttributeListenersUpdate(Attribute* att) { 
+            RevealedModule::gotAttributeListenersUpdate(att);
+        }
+        void setShape(const std::string&);
+
+    protected:
+};
+
+
+#endif
+
diff --git a/src/modules/RevealedTextModule.cpp b/src/modules/RevealedTextModule.cpp
new file mode 100644
index 0000000..c88aa4a
--- /dev/null
+++ b/src/modules/RevealedTextModule.cpp
@@ -0,0 +1,200 @@
+/***************************************************************************
+ *  RevealedTextModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "RevealedTextModule.hpp" 
+
+#include <iostream>
+#include <glm/gtx/quaternion.hpp>
+
+#include "../Reveal.hpp"
+
+#include "../geoms/Geometry.hpp"
+
+using namespace std;
+
+RevealedTextModule::RevealedTextModule(): ShapeModule(), RevealedModule() {
+    m_type="Text";
+    m_name="text";
+
+    m_layersNb=1;
+    int nbBytes = m_texWidth*m_texHeight*m_layersNb*3;
+    m_layersData = new char[nbBytes];
+    m_surf = new Fl_Image_Surface(m_texWidth, m_texHeight);
+
+    m_label = new Fl_Box(0, 0, m_texWidth, m_texHeight, "text");
+    m_label->color(FL_BLACK);
+    m_label->labelcolor(FL_WHITE);
+    m_label->box(FL_FLAT_BOX);
+
+    addNameAttribute();
+    addRemoveAttribute();
+    addVisibleAttribute();
+    addVisibleFromAttribute();
+    addRevealedByAttribute();
+
+    addAttribute(new Attribute("text", 
+                               Attribute::STRING_ATTRIBUTE,
+                               textCallback, this, 1));
+    vector<string> txt(1,"text");
+    m_attributesMap["text"]->setStrings(txt);
+/*
+    addAttribute(new Attribute("font_size", 
+                               Attribute::INT_ATTRIBUTE,
+                               fontSizeCallback, this, 1));
+    addAttribute(new Attribute("dimensions", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                dimensionsCallback, this, 3));
+    m_attributesMap["dimensions"]->setFloats(vector<float>(3,100.0));
+*/
+
+    addShapeAttributes();
+    addTransformationAttributes();
+    addRevealedAttributes();
+    addRevealedOutputAttributes();
+    m_localInsideAxes=true;
+	m_insideDensityAlpha=0;
+	m_insideGradientAlpha=0;
+	m_insideTextureAlpha=1.0;
+	m_insideVisible=true;
+    m_insideTextureBlend=false;
+
+
+    vector<string> shp(1,"frame");
+    m_attributesMap["shape"]->setStrings(shp);
+
+    vector<float> dims(3,200.0);
+    m_attributesMap["dimensions"]->setFloats(dims);
+
+	//set default text
+//	setText("text");
+}
+
+RevealedTextModule::~RevealedTextModule() {
+    Reveal::getInstance()
+                ->getGeom(m_shapesMap[m_currentShape])
+                                ->unregisterModule(this);
+}
+
+void RevealedTextModule::setColor(const vector<float>& hsv) {
+    RevealedModule::setColor(hsv);
+    m_label->labelcolor(fl_rgb_color(m_color[0]*255, 
+                                     m_color[1]*255, 
+                                     m_color[2]*255));
+    setText(m_text);
+}
+
+void RevealedTextModule::setFontSize(const int& size) {
+    m_label->labelsize(size);
+    setText(m_text);
+}
+
+void RevealedTextModule::setText(const std::string& text) {
+    m_text=text;
+
+
+    //layers in text are separated by  | 
+    vector<int> sizes;
+    string token;
+    m_tokens.clear();
+    istringstream tokenStream(m_text);
+    while (getline(tokenStream, token, '|')) {
+		sizes.push_back(0);
+
+		//for each token recreate lines separated by ; 
+		bool done=false;
+		size_t linePos=-1;
+		while(!done) {
+		  size_t newPos = token.find(";",linePos+1);
+		  if(newPos!=string::npos) {
+			token.replace(newPos, size_t(1), "\n");
+			sizes.back()=max<int>(sizes.back(), 
+					  int(newPos-linePos));
+		  }
+		  else {
+			sizes.back()=max<int>(sizes.back(), 
+					  int(token.length()-linePos));
+			done=true;
+		  }
+		  linePos=newPos;
+		}
+        m_tokens.push_back(token);
+    }
+
+    //recreate layers data
+    if(int(m_tokens.size())>m_layersNb || !m_layersData) {
+    	if(m_layersData) {
+            delete [] m_layersData;
+        }
+        int nbBytes = m_texWidth*m_texHeight*m_tokens.size()*3;
+        m_layersData = new char[nbBytes];
+    }
+    m_layersNb=m_tokens.size();
+
+    //fill data with each part of the string
+    for(unsigned int d=0; d<m_tokens.size(); ++d) {
+		//find ; to split in lines
+        m_label->label(m_tokens[(m_layersNb-1)-d].c_str());
+
+        m_label->labelsize(float(900)
+			  / float(sizes[(m_layersNb-1)-d]));//FIXME 
+
+        m_surf->set_current();
+        m_surf->draw(m_label);
+        m_textImg = m_surf->image();
+        Fl_Display_Device::display_device()->set_current();
+        for(int i=0; i<m_texWidth; ++i) {
+            for(int j=0; j<m_texHeight; ++j) {
+                m_layersData[(d*m_texHeight*m_texWidth+j*m_texWidth+i)*3]
+                   =m_textImg->data()[0][(j*m_textImg->w()+i)*m_textImg->d()];
+                m_layersData[(d*m_texHeight*m_texWidth+j*m_texWidth+i)*3+1]
+                   =m_textImg->data()[0][(j*m_textImg->w()+i)*m_textImg->d()+1];
+                m_layersData[(d*m_texHeight*m_texWidth+j*m_texWidth+i)*3+2]
+                   =m_textImg->data()[0][(j*m_textImg->w()+i)*m_textImg->d()+2];
+            }
+        }
+		delete m_textImg;
+    }
+    map<int, bool>::iterator itUp = m_insideUpMap.begin();
+    for(; itUp!=m_insideUpMap.end(); ++itUp) {
+        itUp->second=true;
+    }
+}
+
+void RevealedTextModule::setShape(const std::string& shape) {
+	if(m_shapesMap.find(shape)!=m_shapesMap.end()) {
+        if(m_currentShape.compare("")!=0) {
+            Reveal::getInstance()
+                ->getGeom(m_shapesMap[m_currentShape])
+                    ->unregisterModule(this);
+        }
+        m_currentShape=shape;
+		m_shapeGeom=m_shapesMap[m_currentShape];
+        Reveal::getInstance()
+            ->getGeom(m_shapesMap[m_currentShape])
+                ->registerModule(this);
+        m_currentGeom=Reveal::getInstance()
+                        ->getGeom(m_shapesMap[m_currentShape]);
+    }
+}
+
+
diff --git a/src/modules/RevealedTextModule.hpp b/src/modules/RevealedTextModule.hpp
new file mode 100644
index 0000000..875e866
--- /dev/null
+++ b/src/modules/RevealedTextModule.hpp
@@ -0,0 +1,68 @@
+/***************************************************************************
+ *  RevealedTextModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef RevealedTextModule_h
+#define RevealedTextModule_h
+
+#include "ShapeModule.hpp"
+#include "RevealedModule.hpp"
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Multiline_Output.H>
+#include <FL/Fl_Image_Surface.H>
+
+class RevealedTextModule : public ShapeModule, public RevealedModule {
+    public:
+        RevealedTextModule();
+        virtual ~RevealedTextModule();
+
+        static void textCallback(Module* mod, 
+                                 const std::vector<std::string>& vals) {
+            dynamic_cast<RevealedTextModule*>(mod)->setText(vals[0]);
+        }
+        void setText(const std::string& text);
+        static void fontSizeCallback(Module* mod, 
+                                     const std::vector<int>& vals) {
+            dynamic_cast<RevealedTextModule*>(mod)->setFontSize(vals[0]);
+        }
+        void setFontSize(const int& size);
+        virtual void setColor(const std::vector<float>& hsv);
+
+        static void dimensionsCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            dynamic_cast<RevealedTextModule*>(mod)->setDimensions(vals[0], 
+                                                                  vals[1], 
+                                                                  vals[2]);
+        }
+        void setShape(const std::string&);
+
+    protected:
+        std::string m_text;
+	std::vector<std::string> m_tokens;
+        Fl_RGB_Image* m_textImg;
+        Fl_Box* m_label;
+        Fl_Image_Surface* m_surf;
+};
+
+
+#endif
+
diff --git a/src/modules/RootSceneGroupModule.cpp b/src/modules/RootSceneGroupModule.cpp
new file mode 100644
index 0000000..64b223c
--- /dev/null
+++ b/src/modules/RootSceneGroupModule.cpp
@@ -0,0 +1,131 @@
+/***************************************************************************
+ *  RootSceneGroupModule.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "RootSceneGroupModule.hpp"
+#include "RevealedShapeModule.hpp"
+#include "RevealedPathModule.hpp"
+#include "RevealedTextModule.hpp"
+#include "RevealedCutModule.hpp"
+#include "RevealedArrowModule.hpp"
+#include "RevealedGridModule.hpp"
+#include "RevealedModelModule.hpp"
+#include "SceneGroupModule.hpp"
+#include "../Reveal.hpp"
+
+using namespace std;
+
+RootSceneGroupModule::RootSceneGroupModule(): GroupModule() {
+    m_type="Scene";
+    m_name="scene";
+}
+
+void RootSceneGroupModule::addGroupAttributes() {
+    addAttribute(new Attribute("add_shape", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addShapeCallback, this, 1));
+    m_attributesMap["add_shape"]->initStrings(vector<string>(1, "shape"));
+    addAttribute(new Attribute("add_model", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addModelCallback, this, 1));
+    m_attributesMap["add_model"]->initStrings(vector<string>(1, "model"));
+    addAttribute(new Attribute("add_path", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addPathCallback, this, 1));
+    m_attributesMap["add_path"]->initStrings(vector<string>(1, "path"));
+    addAttribute(new Attribute("add_text", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addTextCallback, this, 1));
+    m_attributesMap["add_text"]->initStrings(vector<string>(1, "text"));
+    addAttribute(new Attribute("add_cut", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addCutCallback, this, 1));
+    m_attributesMap["add_cut"]->initStrings(vector<string>(1, "cut"));
+    addAttribute(new Attribute("add_arrow", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addArrowCallback, this, 1));
+    m_attributesMap["add_arrow"]->initStrings(vector<string>(1, "arrow"));
+    addAttribute(new Attribute("add_grid", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addGridCallback, this, 1));
+    m_attributesMap["add_grid"]->initStrings(vector<string>(1, "grid"));
+    addAttribute(new Attribute("add_group", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addGroupCallback, this, 1));
+    m_attributesMap["add_group"]->initStrings(vector<string>(1, "group"));
+}
+
+void RootSceneGroupModule::addShape(const std::string& name) {
+    RevealedShapeModule* tmp = new RevealedShapeModule();
+    addChild(tmp);
+    tmp->getAttribute("name")->setStrings(vector<string>(1,name));
+    Reveal::getInstance()->refreshModules();
+}
+
+void RootSceneGroupModule::addModel(const std::string& name) {
+    RevealedModelModule* tmp = new RevealedModelModule();
+    addChild(tmp);
+    tmp->getAttribute("name")->setStrings(vector<string>(1,name));
+    Reveal::getInstance()->refreshModules();
+}
+
+void RootSceneGroupModule::addPath(const std::string& name) {
+    RevealedPathModule* tmp = new RevealedPathModule();
+    addChild(tmp);
+    tmp->getAttribute("name")->setStrings(vector<string>(1,name));
+    Reveal::getInstance()->refreshModules();
+}
+
+void RootSceneGroupModule::addText(const std::string& name) {
+    RevealedTextModule* tmp = new RevealedTextModule();
+    addChild(tmp);
+    tmp->getAttribute("name")->setStrings(vector<string>(1,name));
+    Reveal::getInstance()->refreshModules();
+}
+
+void RootSceneGroupModule::addCut(const std::string& name) {
+    RevealedCutModule* tmp = new RevealedCutModule();
+    addChild(tmp);
+    tmp->getAttribute("name")->setStrings(vector<string>(1,name));
+    Reveal::getInstance()->refreshModules();
+}
+
+void RootSceneGroupModule::addArrow(const std::string& name) {
+    RevealedArrowModule* tmp = new RevealedArrowModule();
+    addChild(tmp);
+    tmp->getAttribute("name")->setStrings(vector<string>(1,name));
+    Reveal::getInstance()->refreshModules();
+}
+
+void RootSceneGroupModule::addGrid(const std::string& name) {
+    RevealedGridModule* tmp = new RevealedGridModule();
+    addChild(tmp);
+    tmp->getAttribute("name")->setStrings(vector<string>(1,name));
+    Reveal::getInstance()->refreshModules();
+}
+
+void RootSceneGroupModule::addGroup(const std::string& name) {
+    SceneGroupModule* tmp = new SceneGroupModule();
+    addChild(tmp);
+    tmp->getAttribute("name")->setStrings(vector<string>(1,name));
+    Reveal::getInstance()->refreshModules();
+}
+
diff --git a/src/modules/RootSceneGroupModule.hpp b/src/modules/RootSceneGroupModule.hpp
new file mode 100644
index 0000000..2e47658
--- /dev/null
+++ b/src/modules/RootSceneGroupModule.hpp
@@ -0,0 +1,77 @@
+/***************************************************************************
+ *  RootSceneGroupModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef RootSceneGroupModule_h
+#define RootSceneGroupModule_h
+
+#include "GroupModule.hpp"
+
+class RootSceneGroupModule: public GroupModule {
+    public:
+        RootSceneGroupModule();
+        virtual ~RootSceneGroupModule(){}
+
+        void addGroupAttributes();
+        static void addShapeCallback(Module* mod,
+                                     const std::vector<std::string>& vals) {
+            dynamic_cast<RootSceneGroupModule*>(mod)->addShape(vals[0]);
+        }
+        void addShape(const std::string&);
+        static void addModelCallback(Module* mod,
+                                     const std::vector<std::string>& vals) {
+            dynamic_cast<RootSceneGroupModule*>(mod)->addModel(vals[0]);
+        }
+        void addModel(const std::string&);
+        static void addPathCallback(Module* mod,
+                                    const std::vector<std::string>& vals) {
+            dynamic_cast<RootSceneGroupModule*>(mod)->addPath(vals[0]);
+        }
+        void addPath(const std::string&);
+        static void addTextCallback(Module* mod,
+                                    const std::vector<std::string>& vals) {
+            dynamic_cast<RootSceneGroupModule*>(mod)->addText(vals[0]);
+        }
+        void addText(const std::string&);
+        static void addCutCallback(Module* mod,
+                                    const std::vector<std::string>& vals) {
+            dynamic_cast<RootSceneGroupModule*>(mod)->addCut(vals[0]);
+        }
+        void addCut(const std::string&);
+        static void addArrowCallback(Module* mod,
+                                    const std::vector<std::string>& vals) {
+            dynamic_cast<RootSceneGroupModule*>(mod)->addArrow(vals[0]);
+        }
+        void addArrow(const std::string&);
+        static void addGridCallback(Module* mod,
+                                    const std::vector<std::string>& vals) {
+            dynamic_cast<RootSceneGroupModule*>(mod)->addGrid(vals[0]);
+        }
+        void addGrid(const std::string&);
+        static void addGroupCallback(Module* mod,
+                                     const std::vector<std::string>& vals) {
+            dynamic_cast<RootSceneGroupModule*>(mod)->addGroup(vals[0]);
+        }
+        void addGroup(const std::string&);
+};
+
+#endif
+
diff --git a/src/modules/SceneGroupModule.cpp b/src/modules/SceneGroupModule.cpp
new file mode 100644
index 0000000..9dd29f1
--- /dev/null
+++ b/src/modules/SceneGroupModule.cpp
@@ -0,0 +1,40 @@
+/***************************************************************************
+ *  SceneGroupModule.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "SceneGroupModule.hpp"
+
+using namespace std;
+
+SceneGroupModule::SceneGroupModule(): RootSceneGroupModule() {
+    m_type="SceneGroup";
+    m_name="group";
+    addNameAttribute();
+    addRemoveAttribute();
+    addVisibleAttribute();
+    addTransformationAttributes();
+	addFollowMarkerAttribute();
+    addGroupAttributes();
+    vector<float> initPos(3,0);
+    m_attributesMap["position"]->setFloats(initPos);
+}
+
+
diff --git a/src/modules/SceneGroupModule.hpp b/src/modules/SceneGroupModule.hpp
new file mode 100644
index 0000000..d3bbf64
--- /dev/null
+++ b/src/modules/SceneGroupModule.hpp
@@ -0,0 +1,66 @@
+/***************************************************************************
+ *  SceneGroupModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef SceneGroupModule_h
+#define SceneGroupModule_h
+
+#include "RootSceneGroupModule.hpp"
+
+class SceneGroupModule: public RootSceneGroupModule {
+    public:
+        SceneGroupModule();
+        virtual ~SceneGroupModule(){}
+
+        static void nameCallback(Module* mod, 
+                                 const std::vector<std::string>& vals) {
+            dynamic_cast<SceneGroupModule*>(mod)->setName(vals[0]);
+        }
+        static void deleteCallback(Module* mod) {
+            dynamic_cast<SceneGroupModule*>(mod)->deleteModule();
+        }
+        static void visibleCallback(Module* mod, 
+                                    const std::vector<bool>& vals) {
+            dynamic_cast<SceneGroupModule*>(mod)->setVisible(vals[0]);
+        }
+        static void positionCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            dynamic_cast<SceneGroupModule*>(mod)->setPosition(vals[0], 
+                                                             vals[1], 
+                                                             vals[2]);
+        }
+        static void scaleCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            dynamic_cast<SceneGroupModule*>(mod)->setScale(vals[0], 
+                                                          vals[1], 
+                                                          vals[2]);
+        }
+        static void rotationCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            dynamic_cast<SceneGroupModule*>(mod)->setRotation(vals[0], 
+                                                             vals[1], 
+                                                             vals[2]);
+        }
+};
+
+#endif
+
+
diff --git a/src/modules/ShapeModule.cpp b/src/modules/ShapeModule.cpp
new file mode 100644
index 0000000..f287bd9
--- /dev/null
+++ b/src/modules/ShapeModule.cpp
@@ -0,0 +1,123 @@
+/***************************************************************************
+ *  ShapeModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "ShapeModule.hpp" 
+
+#include <iostream>
+
+#include "../Reveal.hpp"
+#include <glm/gtx/matrix_decompose.hpp>
+#include <glm/gtx/quaternion.hpp>
+#include <glm/gtx/euler_angles.hpp> 
+
+using namespace std;
+using namespace glm;
+
+ShapeModule::ShapeModule(): GeomModule() {
+    m_shapes.push_back("box");
+    m_shapesMap["box"]=Reveal::GEOM_BOX;
+    m_shapes.push_back("sphere");
+    m_shapesMap["sphere"]=Reveal::GEOM_SPHERE;
+    m_shapes.push_back("tube");
+    m_shapesMap["tube"]=Reveal::GEOM_TUBE;
+    m_shapes.push_back("cone");
+    m_shapesMap["cone"]=Reveal::GEOM_CONE;
+    m_shapes.push_back("frame");
+    m_shapesMap["frame"]=Reveal::GEOM_FRAME;
+    m_dimensions=vec3(200.0, 200.0, 200.0);
+}
+
+ShapeModule::~ShapeModule() {}
+
+void ShapeModule::setDimensions(const float& x, const float& y,const float& z) {
+    m_dimensions=vec3(x, y, z);
+    updateModelMatrix();
+}
+
+void ShapeModule::addShapeAttributes() {
+    addAttribute(new Attribute("shape", 
+                                Attribute::STRING_ATTRIBUTE,
+                                shapeCallback, this, 1));
+    m_attributesMap["shape"]->editStringValuesChoices().assign(1, m_shapes);
+    m_attributesMap["shape"]->initStrings(vector<string>(1, m_shapes[0]));
+
+    addAttribute(new Attribute("dimensions", 
+                                Attribute::FLOAT_ATTRIBUTE,
+                                dimensionsCallback, this, 3));
+    m_attributesMap["dimensions"]->setFloats(vector<float>(3,100.0));
+}
+
+void ShapeModule::updateModelMatrix() {
+    Module::updateModelMatrix();
+    mat4 dimMat = scale(m_dimensions);
+    m_modelMat = m_modelMat * dimMat;
+	m_invModelMat = inverse(m_modelMat);
+    vec3 decTrans, decSkew;
+    quat decRot;
+    vec4 decPers;
+    decompose(m_modelMat, m_modelScale, decRot, decTrans, decSkew, decPers);
+
+    //update bounding box as well 
+	vec4 pnts[8];
+    vec4 locpnts[8];
+    int p=0;
+    for(float x=-0.5; x<1; x+=1.0) {
+        for(float y=-0.5; y<1; y+=1.0) {
+            for(float z=-0.5; z<1; z+=1.0) {
+                pnts[p] = m_modelMat*vec4(x, y, z, 1.0);
+                locpnts[p] = vec4(m_modelScale[0]*x, 
+                                  m_modelScale[1]*y, 
+                                  m_modelScale[2]*z, 
+                                  1.0);
+                ++p;
+            }
+        }
+    }
+    m_bbPnts[0]=pnts[0];
+    m_bbPnts[1]=pnts[0];
+    for(p=1; p<8; ++p) {
+        for(int c=0; c<3;++c) {
+            m_bbPnts[0][c]=std::min<float>(pnts[p][c], m_bbPnts[0][c]);
+            m_bbPnts[1][c]=std::max<float>(pnts[p][c], m_bbPnts[1][c]);
+        }
+    }
+
+	/*
+    //store min and size (max-min)
+    m_bboxSizes[0] = bboxMax-m_bboxMins[0];
+    m_bboxLocalSizes[0] = bboxLocMax-m_bboxLocalMin[0];
+    
+    if(m_localInsideAxes) {
+        m_bboxRots[0] = glm::inverse(toMat4(decRot));
+    }
+    else {
+        m_bboxRots[0] = mat4(1.0);
+    }
+	*/
+
+
+	for(auto &up : m_boundingRectUpdate) {
+		up.second=true;
+	}
+}
+
diff --git a/src/modules/ShapeModule.hpp b/src/modules/ShapeModule.hpp
new file mode 100644
index 0000000..edd564a
--- /dev/null
+++ b/src/modules/ShapeModule.hpp
@@ -0,0 +1,59 @@
+/***************************************************************************
+ *  ShapeModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef ShapeModule_h
+#define ShapeModule_h
+
+#include "GeomModule.hpp"
+
+class ShapeModule : public virtual GeomModule {
+    public:
+        ShapeModule();
+        virtual ~ShapeModule();
+
+        static void shapeCallback(Module* mod, 
+                                  const std::vector<std::string>& vals) {
+            dynamic_cast<ShapeModule*>(mod)->setShape(vals[0]);
+        }
+        virtual void setShape(const std::string&){}
+        static void dimensionsCallback(Module* mod, 
+                                     const std::vector<float>& vals) {
+            dynamic_cast<ShapeModule*>(mod)->setDimensions(vals[0], 
+                                                           vals[1], 
+                                                           vals[2]);
+        }
+        void setDimensions(const float&, const float&, const float&);
+
+        virtual void updateModelMatrix();
+        void addShapeAttributes();
+
+    protected:
+        std::vector<std::string> m_shapes;
+        std::map<std::string, Reveal::GEOM_ID> m_shapesMap;
+        glm::vec3 m_dimensions;
+        std::string m_currentShape;
+};
+
+
+#endif
+
diff --git a/src/modules/SpaceModule.cpp b/src/modules/SpaceModule.cpp
new file mode 100644
index 0000000..a1729de
--- /dev/null
+++ b/src/modules/SpaceModule.cpp
@@ -0,0 +1,315 @@
+/***************************************************************************
+ *  SpaceModule.cpp
+ *  Part of Reveal 
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*////////////
+Calibration heavily relies on code from : 
+https://github.com/Kj1/ofxSpaceKinectCalibration
+*/////////////////////
+
+#include "SpaceModule.hpp" 
+
+#include <iostream>
+
+#include "../Reveal.hpp"
+#include "DepthCamModule.hpp"
+#include "ProjectorModule.hpp"
+#include "DepthShapeModule.hpp"
+#include "DepthMeshModule.hpp"
+
+#include "../geoms/BoxGeometry.hpp"
+#include "../geoms/CamGeometry.hpp"
+#include "../geoms/QuadGeometry.hpp"
+#include "../geoms/SphereGeometry.hpp"
+#include "../geoms/TubeGeometry.hpp"
+#include "../geoms/ConeGeometry.hpp"
+
+using namespace std;
+
+SpaceModule::SpaceModule(): DepthGroupModule() {
+    m_type="Space";
+    m_name="space";
+    m_space=this;
+
+    /*
+    addAttribute(new Attribute("name", 
+                                Attribute::STRING_ATTRIBUTE,
+                                nameCallback, this, 1, Attribute::LOCAL));
+    m_attributesMap["name"]->setStrings(vector<string>(1, m_name));
+    addAttribute(new Attribute("add_projector", 
+                                Attribute::ACTION_ATTRIBUTE,
+                                addProjCallback, this, Attribute::LOCAL));
+    addAttribute(new Attribute("add_depth_group", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addDepthGroupCallback, this, 1));
+    addAttribute(new Attribute("add_depth_camera", 
+                                Attribute::ACTION_ATTRIBUTE,
+                                addCamCallback, this, Attribute::LOCAL));
+    addAttribute(new Attribute("add_depth_shape", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addDepthShapeCallback, this, 1));
+    m_attributesMap["add_depth_shape"]->initStrings(vector<string>(1,"shape"));
+    addAttribute(new Attribute("add_depth_mesh", 
+                                Attribute::ACTION_STRING_ATTRIBUTE,
+                                addDepthMeshCallback, this, 1));
+    m_attributesMap["add_depth_mesh"]->initStrings(vector<string>(1,"mesh"));
+*/
+    //create all depth geometries 
+    m_geomsMap[Reveal::GEOM_BOX] = new BoxGeometry();
+    m_geomsMap[Reveal::GEOM_QUAD] = new QuadGeometry();
+    m_geomsMap[Reveal::GEOM_CAM1280] = new CamGeometry(1280, 960);
+    m_geomsMap[Reveal::GEOM_CAM640] = new CamGeometry(640, 480);
+    m_geomsMap[Reveal::GEOM_CAM320] = new CamGeometry(320, 240);
+    m_geomsMap[Reveal::GEOM_SPHERE] = new SphereGeometry();
+    m_geomsMap[Reveal::GEOM_TUBE] = new TubeGeometry();
+    m_geomsMap[Reveal::GEOM_CONE] = new ConeGeometry();
+    map<Reveal::GEOM_ID, Geometry*>::iterator itGeom = m_geomsMap.begin();
+    for(; itGeom!=m_geomsMap.end(); ++itGeom) {
+        itGeom->second->setGeomID(itGeom->first);
+        m_geoms.push_back(itGeom->second);
+    }
+    m_attributesMap["name"]->setStrings(vector<string>(1, m_name));
+}
+
+SpaceModule::~SpaceModule() {}
+
+void SpaceModule::draw() {
+    vector<ProjectorModule*>::iterator itProj=m_projModules.begin();
+    for(; itProj!=m_projModules.end(); ++itProj) {
+        (*itProj)->draw();
+    }
+}
+
+void SpaceModule::removeProj(ProjectorModule* proj) {
+    vector<ProjectorModule*>::iterator itProj=m_projModules.begin();
+    for(; itProj!=m_projModules.end();) {
+        if((*itProj)->getFullName().compare(proj->getFullName())==0) {
+            itProj = m_projModules.erase(itProj);
+        }
+        else {
+            itProj++;   
+        }
+    }
+    removeChild(proj);
+    refreshDepthCamList();
+    refreshProjList();
+}
+
+void SpaceModule::removeCam(DepthCamModule* cam) {
+    vector<DepthCamModule*>::iterator itCam=m_depthCamModules.begin();
+    for(; itCam!=m_depthCamModules.end();) {
+        if((*itCam)->getFullName().compare(cam->getFullName())==0) {
+            itCam = m_depthCamModules.erase(itCam);
+        }
+        else {
+            itCam++;   
+        }
+    }
+    removeDepthModule(cam);
+    removeChild(cam);
+    refreshDepthCamList();
+    refreshProjList();
+}
+
+void SpaceModule::refreshDepthCamList() {
+    vector<ProjectorModule*>::iterator itProj=m_projModules.begin();
+    for(; itProj!=m_projModules.end(); ++itProj) {
+        (*itProj)->refreshDepthCamList(m_depthCamModules);
+    }
+}
+
+void SpaceModule::refreshProjList() {
+    vector<DepthCamModule*>::iterator itCam=m_depthCamModules.begin();
+    for(; itCam!=m_depthCamModules.end(); ++itCam) {
+        (*itCam)->refreshProjList(m_projModules);
+    }
+}
+
+void SpaceModule::addChild(Module* mod) {
+    if(mod->getType().compare("Projector")==0) {
+        ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
+        proj->setSpace(this);
+    }
+    else {
+        DepthModule* dep = dynamic_cast<DepthModule*>(mod);
+        dep->setSpace(this);
+    }
+    DepthGroupModule::addChild(mod);
+}
+
+
+DepthCamModule* SpaceModule::getDepthCamModule(const std::string& name) {
+    DepthCamModule* cam=NULL;
+    vector<DepthCamModule*>::const_iterator itCam=m_depthCamModules.begin();
+    for(; itCam!=m_depthCamModules.end(); ++itCam) {
+        if((*itCam)->getName().compare(name)==0) {
+            cam=(*itCam);
+        }
+    }
+    return cam;
+}
+
+void SpaceModule::addSpaceModule(Module* mod) {
+    if(mod->getType().compare("Projector")==0) {
+        ProjectorModule* proj = static_cast<ProjectorModule*>(mod);
+        m_projModules.push_back(proj);
+        proj->setSpace(this);
+    }
+    else if(mod->getType().compare("DepthCam")==0) {
+        DepthCamModule* cam = dynamic_cast<DepthCamModule*>(mod);
+        m_depthCamModules.push_back(cam);
+        m_depthModules.push_back(cam);
+        cam->setSpace(this);
+    }
+    else if(mod->getType().compare("DepthShape")==0) {
+        DepthShapeModule* sha = dynamic_cast<DepthShapeModule*>(mod);
+        m_depthShapeModules.push_back(sha);
+        m_depthModules.push_back(sha);
+        sha->setSpace(this);
+    }
+    else if(mod->getType().compare("DepthMesh")==0) {
+        DepthMeshModule* mes = dynamic_cast<DepthMeshModule*>(mod);
+        m_depthMeshModules.push_back(mes);
+        m_depthModules.push_back(mes);
+        mes->setSpace(this);
+    }
+    else if(mod->getType().compare("DepthGroup")==0) {
+        DepthGroupModule* gro = dynamic_cast<DepthGroupModule*>(mod);
+        gro->setSpace(this);
+    }
+
+
+    updateDepthModules();
+    refreshDepthCamList();
+    refreshProjList();
+}
+
+void SpaceModule::removeDepthModule(DepthModule* mod) {
+    vector<DepthModule*>::iterator itMod = m_depthModules.begin();
+    for(; itMod!=m_depthModules.end();) {
+        if((*itMod)->getDepthID()==mod->getDepthID()) {
+            itMod=m_depthModules.erase(itMod);
+        }
+        else {
+            ++itMod;
+        }
+    }
+}
+
+void SpaceModule::updateDepthModules() {
+    unsigned int id=1;
+    //assign depth ids 
+    m_depthIDsModules.clear();
+    vector<DepthModule*>::iterator itMod = m_depthModules.begin();
+    for(; itMod!=m_depthModules.end(); ++itMod) {
+        (*itMod)->setDepthID(id);
+        for(int s=0; s<(*itMod)->getNbSubDepthIDs(); ++s, ++id) {
+            m_depthIDsModules[id]=*itMod;
+        }
+    }
+    //reorder things : depths then projs 
+    m_children.clear();
+    vector<DepthModule*>::iterator itDe = m_depthModules.begin();
+    for(; itDe!=m_depthModules.end(); ++itDe) {
+        m_children.push_back(*itDe);
+    }
+    vector<ProjectorModule*>::iterator itProj = m_projModules.begin();
+    for(; itProj!=m_projModules.end(); ++itProj) {
+        m_children.push_back(*itProj);
+    }
+}
+
+void SpaceModule::getVisibleFromList(vector<string>& modVec, 
+                                     map<string, int>& modMap) {
+    int spaceMask = 1 << modVec.size();
+    modVec.push_back(m_name);
+    modMap[modVec.back()] = spaceMask;
+
+    vector<ProjectorModule*>::iterator itProj=m_projModules.begin();
+    for(; itProj!=m_projModules.end(); ++itProj) {
+        int projMask = (1 << modVec.size());
+        modVec.push_back((*itProj)->getName());
+        modMap[modVec.back()] = projMask;
+        (*itProj)->setVisibilityMask(projMask | spaceMask | 1);
+    }
+}
+
+void SpaceModule::registerGeom(Geometry* geom) {
+    if(geom->getGeomID()<0) {
+        Reveal::GEOM_ID newID = Reveal::GEOM_MODEL;
+        while(m_geomsMap.find(newID)!=m_geomsMap.end()) {
+            newID = Reveal::GEOM_ID(int(newID)+1);
+        }
+        geom->setGeomID(newID);
+        m_geomsMap[newID]=geom;
+        m_geoms.push_back(geom);
+    }
+}
+
+void SpaceModule::unregisterGeom(Geometry* geom) {
+    m_geomsMap.erase(geom->getGeomID());
+    vector<Geometry*>::iterator itGeom = m_geoms.begin();
+    for(; itGeom!=m_geoms.end(); ) {
+        if((*itGeom)->getGeomID()==geom->getGeomID()) {
+            itGeom = m_geoms.erase(itGeom);
+        }
+        else {
+            ++itGeom;
+        }
+    }
+}
+
+//SPACES
+void SpacesModule::addSpace() {
+    SpaceModule* proj = new SpaceModule();
+    addChild(proj);
+	m_spaces.push_back(proj);
+    Reveal::getInstance()->refreshModules();
+}
+
+void SpacesModule::load(xmlNodePtr node) {
+    Module::load(node);
+    xmlNodePtr modsNode;
+    for(modsNode=node->children; modsNode; modsNode=modsNode->next){
+        if(modsNode->type == XML_ELEMENT_NODE &&
+                !xmlStrcmp(modsNode->name, (const xmlChar *) "Modules")) {
+            xmlNodePtr modNode;
+            for(modNode=modsNode->children; modNode; modNode=modNode->next){
+                if(modNode->type == XML_ELEMENT_NODE) {
+                    if(!xmlStrcmp(modNode->name, (const xmlChar *)"Preview")) {
+                        m_children[0]->load(modNode);
+                    }
+                    else {
+                        string typeStr((char*) modNode->name);
+                        Module* mod = 
+                            Reveal::getInstance()->createModule(typeStr);
+                        if(mod) {
+                            addChild(mod);
+                            mod->load(modNode);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
diff --git a/src/modules/SpaceModule.hpp b/src/modules/SpaceModule.hpp
new file mode 100644
index 0000000..765793e
--- /dev/null
+++ b/src/modules/SpaceModule.hpp
@@ -0,0 +1,111 @@
+/***************************************************************************
+ *  SpaceModule.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef SpaceModule_h
+#define SpaceModule_h
+
+#include "DepthGroupModule.hpp"
+#include <iostream>
+
+class Geometry;
+
+class SpaceModule : public DepthGroupModule {
+    public:
+        SpaceModule();
+        virtual ~SpaceModule();
+
+        virtual void draw();
+
+        void removeProj(ProjectorModule*);
+
+        void removeCam(DepthCamModule*);
+		inline const unsigned int getNbDepthCamModules() { 
+			return m_depthCamModules.size();
+		}
+        inline DepthCamModule* getDepthCamModule(const unsigned int& mod) {
+            if(mod<m_depthCamModules.size()) {
+                return m_depthCamModules[mod];
+            }
+            return NULL;
+        }
+        DepthCamModule* getDepthCamModule(const std::string& name);
+
+        void addSpaceModule(Module*);
+        void removeDepthModule(DepthModule*);
+        void updateDepthModules();
+        DepthModule* getDepthModuleFromID(const unsigned int& id){ 
+            if(m_depthIDsModules.find(id)!=m_depthIDsModules.end()) {
+                return m_depthIDsModules[id];
+            }
+            return NULL;
+        }
+        unsigned int getNbDepthModulesFromID(){return m_depthIDsModules.size();}
+
+        virtual void addChild(Module* mod);
+        void refreshDepthCamList();
+        void refreshProjList();
+
+        const std::vector<Geometry*>& getGeoms(){return m_geoms;}
+        Geometry* getGeom(const Reveal::GEOM_ID& geomStr) { 
+            return m_geomsMap[geomStr];
+        }
+        void registerGeom(Geometry* geom);
+        void unregisterGeom(Geometry* geom);
+        virtual void getVisibleFromList(std::vector<std::string>& modVec, 
+                                        std::map<std::string, int>& modMap);
+
+    private:
+        std::vector<DepthCamModule*> m_depthCamModules;
+        std::vector<DepthShapeModule*> m_depthShapeModules;
+        std::vector<DepthMeshModule*> m_depthMeshModules;
+        std::vector<ProjectorModule*> m_projModules;
+        std::vector<DepthModule*> m_depthModules;
+        std::map<unsigned int, DepthModule*> m_depthIDsModules;
+        std::map<Reveal::GEOM_ID, Geometry*> m_geomsMap;
+        std::vector<Geometry*> m_geoms;
+};
+
+class SpacesModule: public GroupModule {
+    public:
+        SpacesModule(): GroupModule() {
+            m_type="Spaces";
+            m_name="spaces";
+            addAttribute(new Attribute("add_space", 
+                                        Attribute::ACTION_ATTRIBUTE,
+                                        addSpaceCallback, this, 
+                                        Attribute::LOCAL));
+        }
+        static void addSpaceCallback(Module* mod) {
+            dynamic_cast<SpacesModule*>(mod)->addSpace();
+        }
+        void addSpace();
+        void updateVisibleFrom(std::vector<std::string>& modVec, 
+                               std::map<std::string, int>& modMap);
+        virtual void load(xmlNodePtr node);
+		const std::vector<SpaceModule*>& getSpaces(){return m_spaces;}
+	private:
+		std::vector<SpaceModule*> m_spaces;
+};
+
+#endif
+
diff --git a/src/osc/OscListener.cpp b/src/osc/OscListener.cpp
new file mode 100644
index 0000000..ec4529d
--- /dev/null
+++ b/src/osc/OscListener.cpp
@@ -0,0 +1,188 @@
+/***************************************************************************
+ *  OscListener.cpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "OscListener.hpp"
+#include <iostream>
+#include <sstream>
+#include "OscManager.hpp"
+#include "../modules/Attribute.hpp"
+
+using namespace std;
+
+OscListener::OscListener(const std::string& adPort):Listener() {
+    m_listenerType="OscListener";
+    m_parameters.push_back("");
+    m_parametersValues.push_back(vector<string>());
+    m_parameters.push_back(adPort);
+    m_parametersValues.push_back(vector<string>());
+
+    vector<string> vals;
+    vals.push_back("grouped");
+    vals.push_back("separated");
+    m_parameters.push_back(vals[0]);
+    m_parametersValues.push_back(vals);
+    m_attribute=NULL;
+    m_grouped=true;
+    updateNet();
+}
+
+OscListener::OscListener():Listener() {
+    m_listenerType="OscListener";
+    m_parameters.push_back("");
+    m_parametersValues.push_back(vector<string>());
+    m_parameters.push_back("127.0.0.1:7000");
+    m_parametersValues.push_back(vector<string>());
+
+    vector<string> vals;
+    vals.push_back("grouped");
+    vals.push_back("separated");
+    m_parameters.push_back(vals[0]);
+    m_parametersValues.push_back(vals);
+    m_attribute=NULL;
+    m_grouped=true;
+    updateNet();
+
+	//FIXME, define listener attributes with different types
+}
+
+void OscListener::setAttribute(Attribute* att) { 
+    m_attribute=att;
+    updateNet();
+}
+
+void OscListener::setParameters(const std::vector<std::string>& params) {
+    Listener::setParameters(params);
+    updateNet();
+}
+
+void OscListener::updateNet() {
+    if(m_parameters[0].size()==0) {
+        if(m_attribute!=NULL) {
+            m_parameters[0]=m_attribute->getFullName();
+        }
+    }
+    m_url = m_parameters[0];
+    size_t sep = m_parameters[1].find(':');
+    if(sep!=string::npos) {
+        istringstream iss;
+        iss.str(m_parameters[1].substr(sep+1));
+        iss >> m_port;
+        m_adress=m_parameters[1].substr(0, sep);
+    }
+    if(m_parameters[2].compare("grouped")==0) {
+        m_grouped=true;
+    }
+    else {
+        m_grouped=false;
+    }
+}
+
+void OscListener::update(vector<float>& floatValues, 
+                         vector<int>& intValues,
+                         vector<bool>& boolValues,
+                         vector<string>& stringValues) {
+	//FIXME get OutputManager -> selected output
+    OscManager* osc = OscManager::getInstance();
+    if(m_grouped) {
+		//if(floatValues.size()<10) {
+			osc->sendMessage(m_parameters[1], 
+							 m_adress, 
+							 m_port, 
+							 m_url, 
+							 floatValues, 
+							 intValues,
+							 boolValues,
+							 stringValues);
+		//}
+		/*else { //FIXME
+			osc->sendBlobMessage(m_parameters[1],
+								 m_adress,
+								 m_port,
+								 m_url,
+								 floatValues);
+		}*/
+    }
+    else {
+        int vi = 1;
+        for(float& v : floatValues) {
+            ostringstream oss;
+            oss << vi;
+            osc->sendMessage(m_parameters[1], 
+                             m_adress, 
+                             m_port, 
+                             m_url+"/"+oss.str(), 
+                             vector<float>(1, v), 
+                             intValues,
+                             boolValues,
+                             stringValues);
+            vi++;
+        }
+
+        vi=1;
+        for(int& i : intValues) {
+            ostringstream oss;
+            oss << vi;
+            osc->sendMessage(m_parameters[1], 
+                             m_adress, 
+                             m_port, 
+                             m_url+"/"+oss.str(), 
+                             floatValues,
+                             vector<int>(1, i), 
+                             boolValues,
+                             stringValues);
+            vi++;
+        }
+
+        vi=1;
+        for(bool b : boolValues) {
+            ostringstream oss;
+            oss << vi;
+            osc->sendMessage(m_parameters[1], 
+                             m_adress, 
+                             m_port, 
+                             m_url+"/"+oss.str(), 
+                             floatValues,
+                             intValues,
+                             vector<bool>(1, b), 
+                             stringValues);
+            vi++;
+        }
+
+        vi=1;
+        for(string& s : stringValues) {
+            ostringstream oss;
+            oss << vi;
+            osc->sendMessage(m_parameters[1], 
+                             m_adress, 
+                             m_port, 
+                             m_url+"/"+oss.str(), 
+                             floatValues,
+                             intValues,
+                             boolValues,
+                             vector<string>(1, s));
+            vi++;
+        }
+    }
+}
+
+
+
diff --git a/src/osc/OscListener.hpp b/src/osc/OscListener.hpp
new file mode 100644
index 0000000..1f94a27
--- /dev/null
+++ b/src/osc/OscListener.hpp
@@ -0,0 +1,49 @@
+/***************************************************************************
+ *  OscListener.hpp
+ *  Part of Reveal
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef OscListener_h
+#define OscListener_h
+
+#include "../modules/Listener.hpp"
+
+class OscListener: public Listener {
+    public:
+        OscListener();
+        OscListener(const std::string& adPort);
+        virtual ~OscListener(){}
+        virtual void setAttribute(Attribute* att);
+        virtual void update(std::vector<float>& floatValues, 
+                            std::vector<int>& intValues,
+                            std::vector<bool>& boolValues,
+                            std::vector<std::string>& stringValues);
+        void updateNet();
+        virtual void setParameters(const std::vector<std::string>& par);
+
+    protected:
+        std::string m_adress;
+        unsigned int m_port;
+        std::string m_url;
+        bool m_grouped;
+};
+
+#endif
diff --git a/src/osc/OscManager.cpp b/src/osc/OscManager.cpp
new file mode 100644
index 0000000..8cf1e26
--- /dev/null
+++ b/src/osc/OscManager.cpp
@@ -0,0 +1,264 @@
+/***************************************************************************
+ *  OscManager.cpp
+ *  Part of OscManager
+ *  2015-  Florent Berthaut
+ *  hitmuri.net
+ ****************************************************************************/
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "OscManager.hpp" 
+
+#include <iostream>
+#include <pthread.h>
+
+#include "../Reveal.hpp"
+#include "OscListener.hpp"
+
+using namespace std;
+
+OscManager* OscManager::getInstance() {
+    static OscManager rev;
+    return &rev;
+}
+
+OscManager::OscManager(): osc::OscPacketListener() {}
+OscManager::~OscManager() {}
+
+void* oscThreadFunction(void* pvParam) {
+    OscManager *pThis=(OscManager*)pvParam;
+    pThis->m_socket->Run();
+    return 0;
+}
+
+void OscManager::init() {
+    //initialize osc input 
+    try{
+        m_socket = new UdpListeningReceiveSocket(
+                            IpEndpointName(IpEndpointName::ANY_ADDRESS, 8327),
+                            (osc::OscPacketListener*)this);
+	m_thread = new std::thread(oscThreadFunction, this);
+    }
+    catch(const exception& e) {
+        DEBUG("Error in the OscManager "<<e.what());
+    }
+}
+
+void OscManager::update() {
+    //retrieve osc messages
+	if(m_msgLock.try_lock()) {
+		while(m_messages.size()>0) {
+			OscMessage firstMess = m_messages.front();
+			m_messages.pop_front();
+			OscMessage *mess = &firstMess;
+
+			std::string name = mess->m_name;
+			if(Reveal::getInstance()->getDebugOSC()) {
+				cout<<"OSC: "<<name<<endl;
+			}
+			//try attributes first then modules 
+			Attribute *att = Reveal::getInstance()->findAttribute(name);
+			if(att) {
+				if(att->getAccessibility()==Attribute::GLOBAL 
+						|| att->getAccessibility()==Attribute::OUTPUT) {
+
+					//test first register / unregister listeners 
+					if(mess->m_strValues.size()>0 
+							&& mess->m_strValues[0].compare("register")==0) {
+						att->addListener(new OscListener(mess->m_strValues[1]));
+					}
+					else if(mess->m_strValues.size()>0 
+							&& mess->m_strValues[0].compare("unregister")==0) {
+						//FIXME
+					}
+					else  //test set attributes
+					if(att->getType()==Attribute::FLOAT_ATTRIBUTE 
+						 || att->getType()==Attribute::ACTION_FLOAT_ATTRIBUTE) {
+						if(mess->m_floatValues.size()>0) {
+							att->setFloats(mess->m_floatValues);
+						}
+						else if(mess->m_intValues.size()>0) {
+							att->setInts(mess->m_intValues);
+						}
+					}
+					else if((att->getType()==Attribute::INT_ATTRIBUTE 
+							 || att->getType()==Attribute::ACTION_INT_ATTRIBUTE)
+							&& mess->m_intValues.size()>0) {
+						att->setInts(mess->m_intValues);
+					}
+					else if(att->getType()==Attribute::BOOL_ATTRIBUTE 
+								&& mess->m_boolValues.size()>0) {
+						att->setBools(mess->m_boolValues);
+					}
+					else if((att->getType()==Attribute::STRING_ATTRIBUTE 
+						  || att->getType()==Attribute::ACTION_STRING_ATTRIBUTE)
+							&& mess->m_strValues.size()>0) {
+						att->setStrings(mess->m_strValues);
+					}
+					else if((att->getType()==Attribute::FILE_OPEN_ATTRIBUTE 
+						   || att->getType()==Attribute::FOLDER_OPEN_ATTRIBUTE)
+							&& mess->m_strValues.size()>0) {
+						att->setFile(mess->m_strValues[0]);
+					}
+					else if(att->getType()==Attribute::ACTION_ATTRIBUTE){
+						att->setAction();
+					}
+				}
+			}
+		}
+		m_msgLock.unlock();
+    }
+
+    //send created bundles 
+	/*
+    vector<OscStream*>::iterator itStream = m_streamsVec.begin();
+    for(; itStream!=m_streamsVec.end(); ++itStream) {
+        if((*itStream)->m_bundleStarted) {
+            try {
+                *((*itStream)->m_stream) << osc::EndBundle;   
+                UdpSocket socket;
+                socket.SetEnableBroadcast(true);
+                socket.SendTo(IpEndpointName((*itStream)->m_adress.c_str(), 
+                                             (*itStream)->m_port),
+                              (*itStream)->m_stream->Data(), 
+                              (*itStream)->m_stream->Size());
+            }
+            catch(const exception& e) {
+                cout<<"Error in the osc output "<<e.what()<<endl;
+            }
+        }
+        (*itStream)->m_bundleStarted=false;
+    }*/
+}
+
+void OscManager::stop() {
+
+}
+
+void OscManager::ProcessMessage(const osc::ReceivedMessage& mess,
+                                const IpEndpointName& remoteEndpoint) {
+    //OscMessage *newMessage = new OscMessage();
+    OscMessage newMessage;
+    try {
+        newMessage.m_name=std::string(mess.AddressPattern());
+        osc::ReceivedMessage::const_iterator itArg = mess.ArgumentsBegin();
+        for(; itArg!=mess.ArgumentsEnd(); ++itArg) {
+            if(itArg->IsFloat()) {
+                newMessage.m_floatValues.push_back(itArg->AsFloatUnchecked());
+                newMessage.m_boolValues.push_back((itArg->AsFloatUnchecked()));
+            }
+            else if( itArg->IsInt32() ) {
+              newMessage.m_intValues.push_back(
+                (float)(itArg->AsInt32Unchecked()));
+              newMessage.m_boolValues.push_back((itArg->AsInt32Unchecked()));
+            }
+            else if( itArg->IsString() ) {
+                newMessage.m_strValues.push_back(
+                                            std::string(itArg->AsString()));
+            }
+        }
+    } 
+    catch(const exception& e) {
+        cout<<"Exception when receiving osc message "<<e.what()<<endl;
+    }
+
+	m_msgLock.lock();
+		m_messages.push_back(newMessage);
+	m_msgLock.unlock();
+	/*
+    if(jack_ringbuffer_write_space(m_messagesRingBuffer)>=m_messageSize 
+            && received) {
+        jack_ringbuffer_write(m_messagesRingBuffer, 
+                                (char*)(&newMessage),
+                                    m_messageSize);    
+    }
+    else {
+        delete newMessage;
+    }*/
+}
+
+void OscManager::sendMessage(const string& id,
+                             const string& adress,
+                             const int& port,
+                             const string& name, 
+                             const vector<float>& fValues,
+                             const vector<int>& iValues,
+                             const vector<bool>& bValues,
+                             const vector<string>& sValues) {
+    //create the stream to the destination if it does not exist
+    if(m_streamsMap.find(id)==m_streamsMap.end()) {
+        OscStream* newStream = new OscStream();
+        newStream->m_id=id;
+        newStream->m_adress=adress;
+        newStream->m_port=port;
+        newStream->m_stream=new osc::OutboundPacketStream(newStream->m_buffer, 
+                                                          IP_MTU_SIZE);
+        newStream->m_bundleStarted=false;
+        m_streamsMap[id]=newStream;
+        m_streamsVec.push_back(newStream);
+    }
+
+    OscStream* stream = m_streamsMap[id];
+
+    //start a bundle if it is not started
+    if(!stream->m_bundleStarted) {
+        stream->m_stream->Clear();
+        *(stream->m_stream) << osc::BeginBundleImmediate;
+        stream->m_bundleStarted=true;
+    }
+
+    //add a message 
+    try {
+        *(stream->m_stream) << osc::BeginMessage(name.c_str());
+        vector<string>::const_iterator itS;    
+        for(itS=sValues.begin(); itS!=sValues.end(); ++itS) {
+            *(stream->m_stream)<<(*itS).c_str();
+        }
+        vector<float>::const_iterator itF;    
+        for(itF=fValues.begin(); itF!=fValues.end(); ++itF) {
+            *(stream->m_stream)<<(float)(*itF);
+        }
+        vector<int>::const_iterator itI;    
+        for(itI=iValues.begin(); itI!=iValues.end(); ++itI) {
+            *(stream->m_stream)<<(int)(*itI);
+        }
+        vector<bool>::const_iterator itB;    
+        for(itB=bValues.begin(); itB!=bValues.end(); ++itB) {
+            *(stream->m_stream)<<(bool)(*itB);
+        }
+        *(stream->m_stream) << osc::EndMessage;   
+    }
+    catch(const exception& e) {
+        DEBUG("Error in the osc output "<<e.what());
+    }
+	//FIXME :not efficient, but bundles become too big because of voxels/histo
+	//FIXME: change voxels/histo to blobs or test bundle size
+	try {
+		*(stream->m_stream) << osc::EndBundle;   
+		UdpSocket socket;
+		socket.SetEnableBroadcast(true);
+		socket.SendTo(IpEndpointName(stream->m_adress.c_str(), 
+									 stream->m_port),
+					  stream->m_stream->Data(), 
+					  stream->m_stream->Size());
+        stream->m_bundleStarted=false;
+	}
+	catch(const exception& e) {
+		cout<<"Error in the osc output "<<e.what()<<endl;
+	}
+}
+
diff --git a/src/osc/OscManager.hpp b/src/osc/OscManager.hpp
new file mode 100644
index 0000000..bf63855
--- /dev/null
+++ b/src/osc/OscManager.hpp
@@ -0,0 +1,97 @@
+/***************************************************************************
+ *	OscManager.hpp
+ *	Part of OscManager
+ *	2015-  Florent Berthaut
+ *	hitmuri.net
+ ****************************************************************************/
+/*
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef OscManager_h
+#define OscManager_h
+
+#include <string>
+#include <vector>
+#include <deque>
+#include <map>
+#include <thread>
+#include <mutex>
+#include "oscPack/ip/IpEndpointName.h"
+#include "oscPack/osc/OscReceivedElements.h"
+#include "oscPack/osc/OscOutboundPacketStream.h"
+#include "oscPack/ip/UdpSocket.h"
+#include "oscPack/osc/OscPacketListener.h"
+
+#define IP_MTU_SIZE 10000
+
+struct OscMessage {
+	std::string m_name;
+	std::vector<float> m_floatValues;
+	std::vector<int> m_intValues;
+	std::vector<bool> m_boolValues;
+	std::vector<std::string> m_strValues;
+};
+
+struct OscStream {
+	std::string m_id;
+	std::string m_adress;
+	int m_port;
+	char m_buffer[IP_MTU_SIZE];
+	osc::OutboundPacketStream* m_stream;
+	bool m_bundleStarted;
+};
+
+class OscManager :	public osc::OscPacketListener {
+	public:
+		static OscManager* getInstance();
+		~OscManager();
+
+		void init();
+		int run();
+		void update();
+		void stop();
+		virtual void ProcessMessage(const osc::ReceivedMessage& m,
+									const IpEndpointName& remoteEndpoint);
+		
+		void sendMessage(const std::string& id,
+						 const std::string& adress,
+						 const int& port,
+						 const std::string& name, 
+						 const std::vector<float>& fValues,
+						 const std::vector<int>& iValues,
+						 const std::vector<bool>& bValues,
+						 const std::vector<std::string>& sValues);
+
+	public:
+		UdpListeningReceiveSocket* m_socket;
+
+	private:
+		OscManager();
+
+	private:
+		size_t m_messageSize;
+		char m_buffer[IP_MTU_SIZE];
+		std::deque<OscMessage> m_messages;
+		std::map<std::string, OscStream*> m_streamsMap;
+		std::vector<OscStream*> m_streamsVec;
+		std::thread* m_thread;
+		std::mutex m_msgLock;
+
+};
+
+#endif
+
diff --git a/src/osc/oscPack/ip/IpEndpointName.cpp b/src/osc/oscPack/ip/IpEndpointName.cpp
new file mode 100644
index 0000000..556da3a
--- /dev/null
+++ b/src/osc/oscPack/ip/IpEndpointName.cpp
@@ -0,0 +1,88 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#include "IpEndpointName.h"
+
+#include <cstdio>
+
+#include "NetworkingUtils.h"
+
+
+unsigned long IpEndpointName::GetHostByName( const char *s )
+{
+	return ::GetHostByName(s);
+}
+
+
+void IpEndpointName::AddressAsString( char *s ) const
+{
+	if( address == ANY_ADDRESS ){
+		std::sprintf( s, "<any>" );
+	}else{
+		std::sprintf( s, "%d.%d.%d.%d",
+				(int)((address >> 24) & 0xFF),
+				(int)((address >> 16) & 0xFF),
+				(int)((address >> 8) & 0xFF),
+				(int)(address & 0xFF) );
+	}
+}
+
+
+void IpEndpointName::AddressAndPortAsString( char *s ) const
+{
+	if( port == ANY_PORT ){
+		if( address == ANY_ADDRESS ){
+			std::sprintf( s, "<any>:<any>" );
+		}else{
+			std::sprintf( s, "%d.%d.%d.%d:<any>",
+				(int)((address >> 24) & 0xFF),
+				(int)((address >> 16) & 0xFF),
+				(int)((address >> 8) & 0xFF),
+				(int)(address & 0xFF) );
+		}
+	}else{
+		if( address == ANY_ADDRESS ){
+			std::sprintf( s, "<any>:%d", port );
+		}else{
+			std::sprintf( s, "%d.%d.%d.%d:%d",
+				(int)((address >> 24) & 0xFF),
+				(int)((address >> 16) & 0xFF),
+				(int)((address >> 8) & 0xFF),
+				(int)(address & 0xFF),
+				(int)port );
+		}
+	}	
+}
diff --git a/src/osc/oscPack/ip/IpEndpointName.h b/src/osc/oscPack/ip/IpEndpointName.h
new file mode 100644
index 0000000..4b3159a
--- /dev/null
+++ b/src/osc/oscPack/ip/IpEndpointName.h
@@ -0,0 +1,83 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_IPENDPOINTNAME_H
+#define INCLUDED_OSCPACK_IPENDPOINTNAME_H
+
+
+class IpEndpointName{
+    static unsigned long GetHostByName( const char *s );
+public:
+    static const unsigned long ANY_ADDRESS = 0xFFFFFFFF;
+    static const int ANY_PORT = -1;
+
+    IpEndpointName()
+		: address( ANY_ADDRESS ), port( ANY_PORT ) {}
+    IpEndpointName( int port_ ) 
+		: address( ANY_ADDRESS ), port( port_ ) {}
+    IpEndpointName( unsigned long ipAddress_, int port_ ) 
+		: address( ipAddress_ ), port( port_ ) {}
+    IpEndpointName( const char *addressName, int port_=ANY_PORT )
+		: address( GetHostByName( addressName ) )
+		, port( port_ ) {}
+    IpEndpointName( int addressA, int addressB, int addressC, int addressD, int port_=ANY_PORT )
+		: address( ( (addressA << 24) | (addressB << 16) | (addressC << 8) | addressD ) )
+		, port( port_ ) {}
+
+	// address and port are maintained in host byte order here
+    unsigned long address;
+    int port;
+
+    bool IsMulticastAddress() const { return ((address >> 24) & 0xFF) >= 224 && ((address >> 24) & 0xFF) <= 239; }
+
+	enum { ADDRESS_STRING_LENGTH=17 };
+	void AddressAsString( char *s ) const;
+
+	enum { ADDRESS_AND_PORT_STRING_LENGTH=23};
+	void AddressAndPortAsString( char *s ) const;
+};
+
+inline bool operator==( const IpEndpointName& lhs, const IpEndpointName& rhs )
+{	
+	return (lhs.address == rhs.address && lhs.port == rhs.port );
+}
+
+inline bool operator!=( const IpEndpointName& lhs, const IpEndpointName& rhs )
+{
+	return !(lhs == rhs);
+}
+
+#endif /* INCLUDED_OSCPACK_IPENDPOINTNAME_H */
diff --git a/src/osc/oscPack/ip/NetworkingUtils.h b/src/osc/oscPack/ip/NetworkingUtils.h
new file mode 100644
index 0000000..516e9d2
--- /dev/null
+++ b/src/osc/oscPack/ip/NetworkingUtils.h
@@ -0,0 +1,56 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_NETWORKINGUTILS_H
+#define INCLUDED_OSCPACK_NETWORKINGUTILS_H
+
+
+// in general NetworkInitializer is only used internally, but if you're 
+// application creates multiple sockets from different threads at runtime you
+// should instantiate one of these in main just to make sure the networking
+// layer is initialized.
+class NetworkInitializer{
+public:
+    NetworkInitializer();
+    ~NetworkInitializer();
+};
+
+
+// return ip address of host name in host byte order
+unsigned long GetHostByName( const char *name );
+
+
+#endif /* INCLUDED_OSCPACK_NETWORKINGUTILS_H */
diff --git a/src/osc/oscPack/ip/PacketListener.h b/src/osc/oscPack/ip/PacketListener.h
new file mode 100644
index 0000000..2a8cf63
--- /dev/null
+++ b/src/osc/oscPack/ip/PacketListener.h
@@ -0,0 +1,50 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_PACKETLISTENER_H
+#define INCLUDED_OSCPACK_PACKETLISTENER_H
+
+
+class IpEndpointName;
+
+class PacketListener{
+public:
+    virtual ~PacketListener() {}
+    virtual void ProcessPacket( const char *data, int size, 
+			const IpEndpointName& remoteEndpoint ) = 0;
+};
+
+#endif /* INCLUDED_OSCPACK_PACKETLISTENER_H */
diff --git a/src/osc/oscPack/ip/TimerListener.h b/src/osc/oscPack/ip/TimerListener.h
new file mode 100644
index 0000000..61e262b
--- /dev/null
+++ b/src/osc/oscPack/ip/TimerListener.h
@@ -0,0 +1,47 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_TIMERLISTENER_H
+#define INCLUDED_OSCPACK_TIMERLISTENER_H
+
+
+class TimerListener{
+public:
+    virtual ~TimerListener() {}
+    virtual void TimerExpired() = 0;
+};
+
+#endif /* INCLUDED_OSCPACK_TIMERLISTENER_H */
diff --git a/src/osc/oscPack/ip/UdpSocket.h b/src/osc/oscPack/ip/UdpSocket.h
new file mode 100644
index 0000000..8bebb27
--- /dev/null
+++ b/src/osc/oscPack/ip/UdpSocket.h
@@ -0,0 +1,176 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_UDPSOCKET_H
+#define INCLUDED_OSCPACK_UDPSOCKET_H
+
+#include <cstring> // size_t
+
+#include "NetworkingUtils.h"
+#include "IpEndpointName.h"
+
+
+class PacketListener;
+class TimerListener;
+
+class UdpSocket;
+
+class SocketReceiveMultiplexer{
+    class Implementation;
+    Implementation *impl_;
+
+	friend class UdpSocket;
+
+public:
+    SocketReceiveMultiplexer();
+    ~SocketReceiveMultiplexer();
+
+	// only call the attach/detach methods _before_ calling Run
+
+    // only one listener per socket, each socket at most once
+    void AttachSocketListener( UdpSocket *socket, PacketListener *listener );
+    void DetachSocketListener( UdpSocket *socket, PacketListener *listener );
+
+    void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener );
+	void AttachPeriodicTimerListener(
+            int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener );
+    void DetachPeriodicTimerListener( TimerListener *listener );  
+
+    void Run();      // loop and block processing messages indefinitely
+	void RunUntilSigInt();
+    void Break();    // call this from a listener to exit once the listener returns
+    void AsynchronousBreak(); // call this from another thread or signal handler to exit the Run() state
+};
+
+
+class UdpSocket{
+    class Implementation;
+    Implementation *impl_;
+    
+	friend class SocketReceiveMultiplexer::Implementation;
+    
+public:
+
+	// Ctor throws std::runtime_error if there's a problem
+	// initializing the socket.
+	UdpSocket();
+	virtual ~UdpSocket();
+
+	// Enable broadcast addresses (e.g. x.x.x.255)
+	// Sets SO_BROADCAST socket option.
+	void SetEnableBroadcast( bool enableBroadcast );
+
+	// Enable multiple listeners for a single port on same 
+	// network interface*
+	// Sets SO_REUSEADDR (also SO_REUSEPORT on OS X).
+	// [*] The exact behavior of SO_REUSEADDR and 
+	// SO_REUSEPORT is undefined for some common cases 
+	// and may have drastically different behavior on different
+	// operating systems.
+	void SetAllowReuse( bool allowReuse );
+
+
+	// The socket is created in an unbound, unconnected state
+	// such a socket can only be used to send to an arbitrary
+	// address using SendTo(). To use Send() you need to first
+	// connect to a remote endpoint using Connect(). To use
+	// ReceiveFrom you need to first bind to a local endpoint
+	// using Bind().
+
+	// Retrieve the local endpoint name when sending to 'to'
+	IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const;
+
+	// Connect to a remote endpoint which is used as the target
+	// for calls to Send()
+	void Connect( const IpEndpointName& remoteEndpoint );	
+	void Send( const char *data, std::size_t size );
+    void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size );
+
+
+	// Bind a local endpoint to receive incoming data. Endpoint
+	// can be 'any' for the system to choose an endpoint
+	void Bind( const IpEndpointName& localEndpoint );
+	bool IsBound() const;
+
+    std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size );
+};
+
+
+// convenience classes for transmitting and receiving
+// they just call Connect and/or Bind in the ctor.
+// note that you can still use a receive socket
+// for transmitting etc
+
+class UdpTransmitSocket : public UdpSocket{
+public:
+	UdpTransmitSocket( const IpEndpointName& remoteEndpoint )
+		{ Connect( remoteEndpoint ); }
+};
+
+
+class UdpReceiveSocket : public UdpSocket{
+public:
+	UdpReceiveSocket( const IpEndpointName& localEndpoint )
+		{ Bind( localEndpoint ); }
+};
+
+
+// UdpListeningReceiveSocket provides a simple way to bind one listener
+// to a single socket without having to manually set up a SocketReceiveMultiplexer
+
+class UdpListeningReceiveSocket : public UdpSocket{
+    SocketReceiveMultiplexer mux_;
+    PacketListener *listener_;
+public:
+	UdpListeningReceiveSocket( const IpEndpointName& localEndpoint, PacketListener *listener )
+        : listener_( listener )
+    {
+        Bind( localEndpoint );
+        mux_.AttachSocketListener( this, listener_ );
+    }
+
+    ~UdpListeningReceiveSocket()
+        { mux_.DetachSocketListener( this, listener_ ); }
+
+    // see SocketReceiveMultiplexer above for the behaviour of these methods...
+    void Run() { mux_.Run(); }
+	void RunUntilSigInt() { mux_.RunUntilSigInt(); }
+    void Break() { mux_.Break(); }
+    void AsynchronousBreak() { mux_.AsynchronousBreak(); }
+};
+
+
+#endif /* INCLUDED_OSCPACK_UDPSOCKET_H */
diff --git a/src/osc/oscPack/ip/posix/NetworkingUtils.cpp b/src/osc/oscPack/ip/posix/NetworkingUtils.cpp
new file mode 100644
index 0000000..941507f
--- /dev/null
+++ b/src/osc/oscPack/ip/posix/NetworkingUtils.cpp
@@ -0,0 +1,64 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+	http://www.rossbencina.com/code/oscpack
+
+	Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#include "../NetworkingUtils.h"
+
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <cstring>
+
+
+
+NetworkInitializer::NetworkInitializer() {}
+
+NetworkInitializer::~NetworkInitializer() {}
+
+
+unsigned long GetHostByName( const char *name )
+{
+    unsigned long result = 0;
+
+    struct hostent *h = gethostbyname( name );
+    if( h ){
+        struct in_addr a;
+        std::memcpy( &a, h->h_addr_list[0], h->h_length );
+        result = ntohl(a.s_addr);
+    }
+
+    return result;
+}
diff --git a/src/osc/oscPack/ip/posix/UdpSocket.cpp b/src/osc/oscPack/ip/posix/UdpSocket.cpp
new file mode 100644
index 0000000..fc04585
--- /dev/null
+++ b/src/osc/oscPack/ip/posix/UdpSocket.cpp
@@ -0,0 +1,605 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+	http://www.rossbencina.com/code/oscpack
+
+	Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#include "../UdpSocket.h"
+
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h> // for sockaddr_in
+
+#include <signal.h>
+#include <math.h>
+#include <errno.h>
+#include <string.h> 
+#include <iostream> 
+
+#include <algorithm>
+#include <cassert>
+#include <cstring> // for memset
+#include <stdexcept>
+#include <vector>
+
+#include "../PacketListener.h"
+#include "../TimerListener.h"
+
+
+#if defined(__APPLE__) && !defined(_SOCKLEN_T)
+// pre system 10.3 didn't have socklen_t
+typedef ssize_t socklen_t;
+#endif
+
+
+static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )
+{
+    std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+    sockAddr.sin_family = AF_INET;
+
+	sockAddr.sin_addr.s_addr = 
+		(endpoint.address == IpEndpointName::ANY_ADDRESS)
+		? INADDR_ANY
+		: htonl( endpoint.address );
+
+	sockAddr.sin_port =
+		(endpoint.port == IpEndpointName::ANY_PORT)
+		? 0
+		: htons( endpoint.port );
+}
+
+
+static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )
+{
+	return IpEndpointName( 
+		(sockAddr.sin_addr.s_addr == INADDR_ANY) 
+			? IpEndpointName::ANY_ADDRESS 
+			: ntohl( sockAddr.sin_addr.s_addr ),
+		(sockAddr.sin_port == 0)
+			? IpEndpointName::ANY_PORT
+			: ntohs( sockAddr.sin_port )
+		);
+}
+
+
+class UdpSocket::Implementation{
+	bool isBound_;
+	bool isConnected_;
+
+	int socket_;
+	struct sockaddr_in connectedAddr_;
+	struct sockaddr_in sendToAddr_;
+
+public:
+
+	Implementation()
+		: isBound_( false )
+		, isConnected_( false )
+		, socket_( -1 )
+	{
+		if( (socket_ = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 ){
+            throw std::runtime_error("unable to create udp socket\n");
+        }
+
+		std::memset( &sendToAddr_, 0, sizeof(sendToAddr_) );
+        sendToAddr_.sin_family = AF_INET;
+	}
+
+	~Implementation()
+	{
+		if (socket_ != -1) close(socket_);
+	}
+
+	void SetEnableBroadcast( bool enableBroadcast )
+	{
+		int broadcast = (enableBroadcast) ? 1 : 0; // int on posix
+		if(setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, 
+                              &broadcast, sizeof(broadcast))<0) {
+                  std::cout<<"Error setting broadcast"<<std::endl;
+                }
+	}
+
+	void SetAllowReuse( bool allowReuse )
+	{
+		int reuseAddr = (allowReuse) ? 1 : 0; // int on posix
+		setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr));
+
+#ifdef __APPLE__
+		// needed also for OS X - enable multiple listeners for a single port on same network interface
+		int reusePort = (allowReuse) ? 1 : 0; // int on posix
+		setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &reusePort, sizeof(reusePort));
+#endif
+	}
+
+	IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+	{
+		assert( isBound_ );
+
+		// first connect the socket to the remote server
+        
+        struct sockaddr_in connectSockAddr;
+		SockaddrFromIpEndpointName( connectSockAddr, remoteEndpoint );
+       
+        if (connect(socket_, (struct sockaddr *)&connectSockAddr, sizeof(connectSockAddr)) < 0) {
+            throw std::runtime_error("unable to connect udp socket\n");
+        }
+
+        // get the address
+
+        struct sockaddr_in sockAddr;
+        std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+        socklen_t length = sizeof(sockAddr);
+        if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
+            throw std::runtime_error("unable to getsockname\n");
+        }
+        
+		if( isConnected_ ){
+			// reconnect to the connected address
+			
+			if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+				throw std::runtime_error("unable to connect udp socket\n");
+			}
+
+		}else{
+			// unconnect from the remote address
+		
+			struct sockaddr_in unconnectSockAddr;
+			std::memset( (char *)&unconnectSockAddr, 0, sizeof(unconnectSockAddr ) );
+			unconnectSockAddr.sin_family = AF_UNSPEC;
+			// address fields are zero
+			int connectResult = connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr));
+			if ( connectResult < 0 && errno != EAFNOSUPPORT ) {
+				throw std::runtime_error("unable to un-connect udp socket\n");
+			}
+		}
+
+		return IpEndpointNameFromSockaddr( sockAddr );
+	}
+
+	void Connect( const IpEndpointName& remoteEndpoint )
+	{
+		SockaddrFromIpEndpointName( connectedAddr_, remoteEndpoint );
+       
+        if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+            throw std::runtime_error("unable to connect udp socket\n");
+        }
+
+		isConnected_ = true;
+	}
+
+	void Send( const char *data, std::size_t size )
+	{
+		assert( isConnected_ );
+              send( socket_, data, size, 0 );
+	}
+
+    void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )
+	{
+		sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address );
+        sendToAddr_.sin_port = htons( remoteEndpoint.port );
+
+        sendto( socket_, data, size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) );
+	}
+
+	void Bind( const IpEndpointName& localEndpoint )
+	{
+		struct sockaddr_in bindSockAddr;
+		SockaddrFromIpEndpointName( bindSockAddr, localEndpoint );
+
+        if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
+            throw std::runtime_error("unable to bind udp socket\n");
+        }
+
+		isBound_ = true;
+	}
+
+	bool IsBound() const { return isBound_; }
+
+    std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )
+	{
+		assert( isBound_ );
+
+		struct sockaddr_in fromAddr;
+        socklen_t fromAddrLen = sizeof(fromAddr);
+             	 
+        ssize_t result = recvfrom(socket_, data, size, MSG_DONTWAIT,
+                    (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
+		if( result < 0 )
+			return 0;
+
+		remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
+		remoteEndpoint.port = ntohs(fromAddr.sin_port);
+
+		return (std::size_t)result;
+	}
+
+	int Socket() { return socket_; }
+};
+
+UdpSocket::UdpSocket()
+{
+	impl_ = new Implementation();
+}
+
+UdpSocket::~UdpSocket()
+{
+	delete impl_;
+}
+
+void UdpSocket::SetEnableBroadcast( bool enableBroadcast )
+{
+    impl_->SetEnableBroadcast( enableBroadcast );
+}
+
+void UdpSocket::SetAllowReuse( bool allowReuse )
+{
+    impl_->SetAllowReuse( allowReuse );
+}
+
+IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+{
+	return impl_->LocalEndpointFor( remoteEndpoint );
+}
+
+void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
+{
+	impl_->Connect( remoteEndpoint );
+}
+
+void UdpSocket::Send( const char *data, std::size_t size )
+{
+	impl_->Send( data, size );
+}
+
+void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )
+{
+	impl_->SendTo( remoteEndpoint, data, size );
+}
+
+void UdpSocket::Bind( const IpEndpointName& localEndpoint )
+{
+	impl_->Bind( localEndpoint );
+}
+
+bool UdpSocket::IsBound() const
+{
+	return impl_->IsBound();
+}
+
+std::size_t UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )
+{
+	return impl_->ReceiveFrom( remoteEndpoint, data, size );
+}
+
+
+struct AttachedTimerListener{
+	AttachedTimerListener( int id, int p, TimerListener *tl )
+		: initialDelayMs( id )
+		, periodMs( p )
+		, listener( tl ) {}
+	int initialDelayMs;
+	int periodMs;
+	TimerListener *listener;
+};
+
+
+static bool CompareScheduledTimerCalls( 
+		const std::pair< double, AttachedTimerListener > & lhs, const std::pair< double, AttachedTimerListener > & rhs )
+{
+	return lhs.first < rhs.first;
+}
+
+
+SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;
+
+extern "C" /*static*/ void InterruptSignalHandler( int );
+/*static*/ void InterruptSignalHandler( int )
+{
+	multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
+	signal( SIGINT, SIG_DFL );
+}
+
+
+class SocketReceiveMultiplexer::Implementation{
+	std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
+	std::vector< AttachedTimerListener > timerListeners_;
+
+	volatile bool break_;
+	int breakPipe_[2]; // [0] is the reader descriptor and [1] the writer
+
+	double GetCurrentTimeMs() const
+	{
+		struct timeval t;
+
+		gettimeofday( &t, 0 );
+
+		return ((double)t.tv_sec*1000.) + ((double)t.tv_usec / 1000.);
+	}
+
+public:
+    Implementation()
+	{
+		if( pipe(breakPipe_) != 0 )
+			throw std::runtime_error( "creation of asynchronous break pipes failed\n" );
+	}
+
+    ~Implementation()
+	{
+		close( breakPipe_[0] );
+		close( breakPipe_[1] );
+	}
+
+    void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+	{
+		assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
+		// we don't check that the same socket has been added multiple times, even though this is an error
+		socketListeners_.push_back( std::make_pair( listener, socket ) );
+	}
+
+    void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+	{
+		std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = 
+				std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
+		assert( i != socketListeners_.end() );
+
+		socketListeners_.erase( i );
+	}
+
+    void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+	{
+		timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
+	}
+
+	void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+	{
+		timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
+	}
+
+    void DetachPeriodicTimerListener( TimerListener *listener )
+	{
+		std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+		while( i != timerListeners_.end() ){
+			if( i->listener == listener )
+				break;
+			++i;
+		}
+
+		assert( i != timerListeners_.end() );
+
+		timerListeners_.erase( i );
+	}
+
+    void Run()
+	{
+		break_ = false;
+        char *data = 0;
+        
+        try{
+            
+            // configure the master fd_set for select()
+
+            fd_set masterfds, tempfds;
+            FD_ZERO( &masterfds );
+            FD_ZERO( &tempfds );
+            
+            // in addition to listening to the inbound sockets we
+            // also listen to the asynchronous break pipe, so that AsynchronousBreak()
+            // can break us out of select() from another thread.
+            FD_SET( breakPipe_[0], &masterfds );
+            int fdmax = breakPipe_[0];		
+
+            for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+                    i != socketListeners_.end(); ++i ){
+
+                if( fdmax < i->second->impl_->Socket() )
+                    fdmax = i->second->impl_->Socket();
+                FD_SET( i->second->impl_->Socket(), &masterfds );
+            }
+
+
+            // configure the timer queue
+            double currentTimeMs = GetCurrentTimeMs();
+
+            // expiry time ms, listener
+            std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
+            for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+                    i != timerListeners_.end(); ++i )
+                timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
+            std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+
+            const int MAX_BUFFER_SIZE = 4098;
+            data = new char[ MAX_BUFFER_SIZE ];
+            IpEndpointName remoteEndpoint;
+
+            struct timeval timeout;
+
+            while( !break_ ){
+                tempfds = masterfds;
+
+                struct timeval *timeoutPtr = 0;
+                if( !timerQueue_.empty() ){
+                    double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs();
+                    if( timeoutMs < 0 )
+                        timeoutMs = 0;
+                
+                    long timoutSecondsPart = (long)(timeoutMs * .001);
+                    timeout.tv_sec = (time_t)timoutSecondsPart;
+                    // 1000000 microseconds in a second
+                    timeout.tv_usec = (suseconds_t)((timeoutMs - (timoutSecondsPart * 1000)) * 1000);
+                    timeoutPtr = &timeout;
+                }
+
+                if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 ){
+                    if( break_ ){
+                        break;
+                    }else if( errno == EINTR ){
+                        // on returning an error, select() doesn't clear tempfds.
+                        // so tempfds would remain all set, which would cause read( breakPipe_[0]...
+                        // below to block indefinitely. therefore if select returns EINTR we restart
+                        // the while() loop instead of continuing on to below.
+                        continue;
+                    }else{
+                        throw std::runtime_error("select failed\n");
+                    }
+                }
+
+                if( FD_ISSET( breakPipe_[0], &tempfds ) ){
+                    // clear pending data from the asynchronous break pipe
+                    char c;
+                    read( breakPipe_[0], &c, 1 );
+                }
+                
+                if( break_ )
+                    break;
+
+                for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+                        i != socketListeners_.end(); ++i ){
+
+                    if( FD_ISSET( i->second->impl_->Socket(), &tempfds ) ){
+
+                        std::size_t size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
+                        if( size > 0 ){
+                            i->first->ProcessPacket( data, (int)size, remoteEndpoint );
+                            if( break_ )
+                                break;
+                        }
+                    }
+                }
+
+                // execute any expired timers
+                currentTimeMs = GetCurrentTimeMs();
+                bool resort = false;
+                for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
+                        i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
+
+                    i->second.listener->TimerExpired();
+                    if( break_ )
+                        break;
+
+                    i->first += i->second.periodMs;
+                    resort = true;
+                }
+                if( resort )
+                    std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+            }
+
+            delete [] data;
+        }catch(...){
+            if( data )
+                delete [] data;
+            throw;
+        }
+	}
+
+    void Break()
+	{
+		break_ = true;
+	}
+
+    void AsynchronousBreak()
+	{
+		break_ = true;
+
+		// Send a termination message to the asynchronous break pipe, so select() will return
+		write( breakPipe_[1], "!", 1 );
+	}
+};
+
+
+
+SocketReceiveMultiplexer::SocketReceiveMultiplexer()
+{
+	impl_ = new Implementation();
+}
+
+SocketReceiveMultiplexer::~SocketReceiveMultiplexer()
+{	
+	delete impl_;
+}
+
+void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+	impl_->AttachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+	impl_->DetachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+{
+	impl_->AttachPeriodicTimerListener( periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+{
+	impl_->AttachPeriodicTimerListener( initialDelayMilliseconds, periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )
+{
+	impl_->DetachPeriodicTimerListener( listener );
+}
+
+void SocketReceiveMultiplexer::Run()
+{
+	impl_->Run();
+}
+
+void SocketReceiveMultiplexer::RunUntilSigInt()
+{
+	assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
+	multiplexerInstanceToAbortWithSigInt_ = this;
+	signal( SIGINT, InterruptSignalHandler );
+	impl_->Run();
+	signal( SIGINT, SIG_DFL );
+	multiplexerInstanceToAbortWithSigInt_ = 0;
+}
+
+void SocketReceiveMultiplexer::Break()
+{
+	impl_->Break();
+}
+
+void SocketReceiveMultiplexer::AsynchronousBreak()
+{
+	impl_->AsynchronousBreak();
+}
+
diff --git a/src/osc/oscPack/ip/win32/NetworkingUtils.cpp b/src/osc/oscPack/ip/win32/NetworkingUtils.cpp
new file mode 100644
index 0000000..a3f4f6a
--- /dev/null
+++ b/src/osc/oscPack/ip/win32/NetworkingUtils.cpp
@@ -0,0 +1,95 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#include "../NetworkingUtils.h"
+
+#include <winsock2.h>   // this must come first to prevent errors with MSVC7
+#include <windows.h>
+
+#include <cstring>
+
+
+static LONG initCount_ = 0;
+static bool winsockInitialized_ = false;
+
+NetworkInitializer::NetworkInitializer()
+{
+    if( InterlockedIncrement( &initCount_ ) == 1 ){
+        // there is a race condition here if one thread tries to access
+        // the library while another is still initializing it. 
+        // i can't think of an easy way to fix it so i'm telling you here
+        // incase you need to init the library from two threads at once.
+        // this is why the header file advises to instantiate one of these 
+        // in main() so that the initialization happens globally
+
+        // initialize winsock
+	    WSAData wsaData;
+	    int nCode = WSAStartup(MAKEWORD(1, 1), &wsaData);
+	    if( nCode != 0 ){
+	        //std::cout << "WSAStartup() failed with error code " << nCode << "\n";
+        }else{
+            winsockInitialized_ = true;
+        }
+    }
+}
+
+
+NetworkInitializer::~NetworkInitializer()
+{
+    if( InterlockedDecrement( &initCount_ ) == 0 ){
+        if( winsockInitialized_ ){
+            WSACleanup();
+            winsockInitialized_ = false;
+        }
+    }
+}
+
+
+unsigned long GetHostByName( const char *name )
+{
+    NetworkInitializer networkInitializer;
+
+    unsigned long result = 0;
+
+    struct hostent *h = gethostbyname( name );
+    if( h ){
+        struct in_addr a;
+        std::memcpy( &a, h->h_addr_list[0], h->h_length );
+        result = ntohl(a.s_addr);
+    }
+
+    return result;
+}
diff --git a/src/osc/oscPack/ip/win32/UdpSocket.cpp b/src/osc/oscPack/ip/win32/UdpSocket.cpp
new file mode 100644
index 0000000..9967c0a
--- /dev/null
+++ b/src/osc/oscPack/ip/win32/UdpSocket.cpp
@@ -0,0 +1,571 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+
+#include <winsock2.h>   // this must come first to prevent errors with MSVC7
+#include <windows.h>
+#include <mmsystem.h>   // for timeGetTime()
+
+#ifndef WINCE
+#include <signal.h>
+#endif
+
+#include <algorithm>
+#include <cassert>
+#include <cstring> // for memset
+#include <stdexcept>
+#include <vector>
+
+#include "../UdpSocket.h" // usually I'd include the module header first
+                          // but this is causing conflicts with BCB4 due to
+                          // std::size_t usage.
+
+#include "../NetworkingUtils.h"
+#include "../PacketListener.h"
+#include "../TimerListener.h"
+
+
+typedef int socklen_t;
+
+
+static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )
+{
+    std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+    sockAddr.sin_family = AF_INET;
+
+	sockAddr.sin_addr.s_addr = 
+		(endpoint.address == IpEndpointName::ANY_ADDRESS)
+		? INADDR_ANY
+		: htonl( endpoint.address );
+
+	sockAddr.sin_port =
+		(endpoint.port == IpEndpointName::ANY_PORT)
+		? (short)0
+		: htons( (short)endpoint.port );
+}
+
+
+static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )
+{
+	return IpEndpointName( 
+		(sockAddr.sin_addr.s_addr == INADDR_ANY) 
+			? IpEndpointName::ANY_ADDRESS 
+			: ntohl( sockAddr.sin_addr.s_addr ),
+		(sockAddr.sin_port == 0)
+			? IpEndpointName::ANY_PORT
+			: ntohs( sockAddr.sin_port )
+		);
+}
+
+
+class UdpSocket::Implementation{
+    NetworkInitializer networkInitializer_;
+
+	bool isBound_;
+	bool isConnected_;
+
+	SOCKET socket_;
+	struct sockaddr_in connectedAddr_;
+	struct sockaddr_in sendToAddr_;
+
+public:
+
+	Implementation()
+		: isBound_( false )
+		, isConnected_( false )
+		, socket_( INVALID_SOCKET )
+	{
+		if( (socket_ = socket( AF_INET, SOCK_DGRAM, 0 )) == INVALID_SOCKET ){
+            throw std::runtime_error("unable to create udp socket\n");
+        }
+
+		std::memset( &sendToAddr_, 0, sizeof(sendToAddr_) );
+        sendToAddr_.sin_family = AF_INET;
+	}
+
+	~Implementation()
+	{
+		if (socket_ != INVALID_SOCKET) closesocket(socket_);
+	}
+
+	void SetEnableBroadcast( bool enableBroadcast )
+	{
+		char broadcast = (char)((enableBroadcast) ? 1 : 0); // char on win32
+		setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
+	}
+
+	void SetAllowReuse( bool allowReuse )
+	{
+		// Note: SO_REUSEADDR is non-deterministic for listening sockets on Win32. See MSDN article:
+		// "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
+		// http://msdn.microsoft.com/en-us/library/ms740621%28VS.85%29.aspx
+
+		char reuseAddr = (char)((allowReuse) ? 1 : 0); // char on win32
+		setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr));
+	}
+
+	IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+	{
+		assert( isBound_ );
+
+		// first connect the socket to the remote server
+        
+        struct sockaddr_in connectSockAddr;
+		SockaddrFromIpEndpointName( connectSockAddr, remoteEndpoint );
+       
+        if (connect(socket_, (struct sockaddr *)&connectSockAddr, sizeof(connectSockAddr)) < 0) {
+            throw std::runtime_error("unable to connect udp socket\n");
+        }
+
+        // get the address
+
+        struct sockaddr_in sockAddr;
+        std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
+        socklen_t length = sizeof(sockAddr);
+        if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
+            throw std::runtime_error("unable to getsockname\n");
+        }
+        
+		if( isConnected_ ){
+			// reconnect to the connected address
+			
+			if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+				throw std::runtime_error("unable to connect udp socket\n");
+			}
+
+		}else{
+			// unconnect from the remote address
+		
+			struct sockaddr_in unconnectSockAddr;
+			SockaddrFromIpEndpointName( unconnectSockAddr, IpEndpointName() );
+
+			if( connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr)) < 0 
+					&& WSAGetLastError() != WSAEADDRNOTAVAIL ){
+				throw std::runtime_error("unable to un-connect udp socket\n");
+			}
+		}
+
+		return IpEndpointNameFromSockaddr( sockAddr );
+	}
+
+	void Connect( const IpEndpointName& remoteEndpoint )
+	{
+		SockaddrFromIpEndpointName( connectedAddr_, remoteEndpoint );
+       
+        if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
+            throw std::runtime_error("unable to connect udp socket\n");
+        }
+
+		isConnected_ = true;
+	}
+
+	void Send( const char *data, std::size_t size )
+	{
+		assert( isConnected_ );
+
+        send( socket_, data, (int)size, 0 );
+	}
+
+    void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )
+	{
+		sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address );
+        sendToAddr_.sin_port = htons( (short)remoteEndpoint.port );
+
+        sendto( socket_, data, (int)size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) );
+	}
+
+	void Bind( const IpEndpointName& localEndpoint )
+	{
+		struct sockaddr_in bindSockAddr;
+		SockaddrFromIpEndpointName( bindSockAddr, localEndpoint );
+
+        if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
+            throw std::runtime_error("unable to bind udp socket\n");
+        }
+
+		isBound_ = true;
+	}
+
+	bool IsBound() const { return isBound_; }
+
+    std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )
+	{
+		assert( isBound_ );
+
+		struct sockaddr_in fromAddr;
+        socklen_t fromAddrLen = sizeof(fromAddr);
+             	 
+        int result = recvfrom(socket_, data, (int)size, 0,
+                    (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
+		if( result < 0 )
+			return 0;
+
+		remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
+		remoteEndpoint.port = ntohs(fromAddr.sin_port);
+
+		return result;
+	}
+
+	SOCKET& Socket() { return socket_; }
+};
+
+UdpSocket::UdpSocket()
+{
+	impl_ = new Implementation();
+}
+
+UdpSocket::~UdpSocket()
+{
+	delete impl_;
+}
+
+void UdpSocket::SetEnableBroadcast( bool enableBroadcast )
+{
+    impl_->SetEnableBroadcast( enableBroadcast );
+}
+
+void UdpSocket::SetAllowReuse( bool allowReuse )
+{
+    impl_->SetAllowReuse( allowReuse );
+}
+
+IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
+{
+	return impl_->LocalEndpointFor( remoteEndpoint );
+}
+
+void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
+{
+	impl_->Connect( remoteEndpoint );
+}
+
+void UdpSocket::Send( const char *data, std::size_t size )
+{
+	impl_->Send( data, size );
+}
+
+void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )
+{
+	impl_->SendTo( remoteEndpoint, data, size );
+}
+
+void UdpSocket::Bind( const IpEndpointName& localEndpoint )
+{
+	impl_->Bind( localEndpoint );
+}
+
+bool UdpSocket::IsBound() const
+{
+	return impl_->IsBound();
+}
+
+std::size_t UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )
+{
+	return impl_->ReceiveFrom( remoteEndpoint, data, size );
+}
+
+
+struct AttachedTimerListener{
+	AttachedTimerListener( int id, int p, TimerListener *tl )
+		: initialDelayMs( id )
+		, periodMs( p )
+		, listener( tl ) {}
+	int initialDelayMs;
+	int periodMs;
+	TimerListener *listener;
+};
+
+
+static bool CompareScheduledTimerCalls( 
+		const std::pair< double, AttachedTimerListener > & lhs, const std::pair< double, AttachedTimerListener > & rhs )
+{
+	return lhs.first < rhs.first;
+}
+
+
+SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;
+
+extern "C" /*static*/ void InterruptSignalHandler( int );
+/*static*/ void InterruptSignalHandler( int )
+{
+	multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
+#ifndef WINCE
+    signal( SIGINT, SIG_DFL );
+#endif
+}
+
+
+class SocketReceiveMultiplexer::Implementation{
+    NetworkInitializer networkInitializer_;
+
+	std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
+	std::vector< AttachedTimerListener > timerListeners_;
+
+	volatile bool break_;
+	HANDLE breakEvent_;
+
+	double GetCurrentTimeMs() const
+	{
+#ifndef WINCE
+		return timeGetTime(); // FIXME: bad choice if you want to run for more than 40 days
+#else
+        return 0;
+#endif
+    }
+
+public:
+    Implementation()
+	{
+		breakEvent_ = CreateEvent( NULL, FALSE, FALSE, NULL );
+	}
+
+    ~Implementation()
+	{
+		CloseHandle( breakEvent_ );
+	}
+
+    void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+	{
+		assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
+		// we don't check that the same socket has been added multiple times, even though this is an error
+		socketListeners_.push_back( std::make_pair( listener, socket ) );
+	}
+
+    void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+	{
+		std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = 
+				std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
+		assert( i != socketListeners_.end() );
+
+		socketListeners_.erase( i );
+	}
+
+    void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+	{
+		timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
+	}
+
+	void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+	{
+		timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
+	}
+
+    void DetachPeriodicTimerListener( TimerListener *listener )
+	{
+		std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+		while( i != timerListeners_.end() ){
+			if( i->listener == listener )
+				break;
+			++i;
+		}
+
+		assert( i != timerListeners_.end() );
+
+		timerListeners_.erase( i );
+	}
+
+    void Run()
+	{
+		break_ = false;
+
+		// prepare the window events which we use to wake up on incoming data
+		// we use this instead of select() primarily to support the AsyncBreak() 
+		// mechanism.
+
+		std::vector<HANDLE> events( socketListeners_.size() + 1, 0 );
+		int j=0;
+		for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+				i != socketListeners_.end(); ++i, ++j ){
+
+			HANDLE event = CreateEvent( NULL, FALSE, FALSE, NULL );
+			WSAEventSelect( i->second->impl_->Socket(), event, FD_READ ); // note that this makes the socket non-blocking which is why we can safely call RecieveFrom() on all sockets below
+			events[j] = event;
+		}
+
+
+		events[ socketListeners_.size() ] = breakEvent_; // last event in the collection is the break event
+
+		
+		// configure the timer queue
+		double currentTimeMs = GetCurrentTimeMs();
+
+		// expiry time ms, listener
+		std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
+		for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
+				i != timerListeners_.end(); ++i )
+			timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
+		std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+
+		const int MAX_BUFFER_SIZE = 4098;
+		char *data = new char[ MAX_BUFFER_SIZE ];
+		IpEndpointName remoteEndpoint;
+
+		while( !break_ ){
+
+			double currentTimeMs = GetCurrentTimeMs();
+
+            DWORD waitTime = INFINITE;
+            if( !timerQueue_.empty() ){
+
+                waitTime = (DWORD)( timerQueue_.front().first >= currentTimeMs
+                            ? timerQueue_.front().first - currentTimeMs
+                            : 0 );
+            }
+
+			DWORD waitResult = WaitForMultipleObjects( (DWORD)socketListeners_.size() + 1, &events[0], FALSE, waitTime );
+			if( break_ )
+				break;
+
+			if( waitResult != WAIT_TIMEOUT ){
+				for( int i = waitResult - WAIT_OBJECT_0; i < (int)socketListeners_.size(); ++i ){
+					std::size_t size = socketListeners_[i].second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
+					if( size > 0 ){
+						socketListeners_[i].first->ProcessPacket( data, (int)size, remoteEndpoint );
+						if( break_ )
+							break;
+					}
+				}
+			}
+
+			// execute any expired timers
+			currentTimeMs = GetCurrentTimeMs();
+			bool resort = false;
+			for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
+					i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
+
+				i->second.listener->TimerExpired();
+				if( break_ )
+					break;
+
+				i->first += i->second.periodMs;
+				resort = true;
+			}
+			if( resort )
+				std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
+		}
+
+		delete [] data;
+
+		// free events
+		j = 0;
+		for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
+				i != socketListeners_.end(); ++i, ++j ){
+
+			WSAEventSelect( i->second->impl_->Socket(), events[j], 0 ); // remove association between socket and event
+			CloseHandle( events[j] );
+			unsigned long enableNonblocking = 0;
+			ioctlsocket( i->second->impl_->Socket(), FIONBIO, &enableNonblocking );  // make the socket blocking again
+		}
+	}
+
+    void Break()
+	{
+		break_ = true;
+	}
+
+    void AsynchronousBreak()
+	{
+		break_ = true;
+		SetEvent( breakEvent_ );
+	}
+};
+
+
+
+SocketReceiveMultiplexer::SocketReceiveMultiplexer()
+{
+	impl_ = new Implementation();
+}
+
+SocketReceiveMultiplexer::~SocketReceiveMultiplexer()
+{	
+	delete impl_;
+}
+
+void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+	impl_->AttachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )
+{
+	impl_->DetachSocketListener( socket, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
+{
+	impl_->AttachPeriodicTimerListener( periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
+{
+	impl_->AttachPeriodicTimerListener( initialDelayMilliseconds, periodMilliseconds, listener );
+}
+
+void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )
+{
+	impl_->DetachPeriodicTimerListener( listener );
+}
+
+void SocketReceiveMultiplexer::Run()
+{
+	impl_->Run();
+}
+
+void SocketReceiveMultiplexer::RunUntilSigInt()
+{
+	assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
+	multiplexerInstanceToAbortWithSigInt_ = this;
+#ifndef WINCE
+    signal( SIGINT, InterruptSignalHandler );
+#endif
+	impl_->Run();
+#ifndef WINCE
+	signal( SIGINT, SIG_DFL );
+#endif
+	multiplexerInstanceToAbortWithSigInt_ = 0;
+}
+
+void SocketReceiveMultiplexer::Break()
+{
+	impl_->Break();
+}
+
+void SocketReceiveMultiplexer::AsynchronousBreak()
+{
+	impl_->AsynchronousBreak();
+}
+
diff --git a/src/osc/oscPack/osc/MessageMappingOscPacketListener.h b/src/osc/oscPack/osc/MessageMappingOscPacketListener.h
new file mode 100644
index 0000000..fc7f75a
--- /dev/null
+++ b/src/osc/oscPack/osc/MessageMappingOscPacketListener.h
@@ -0,0 +1,80 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H
+#define INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H
+
+#include <cstring>
+#include <map>
+
+#include "OscPacketListener.h"
+
+
+
+namespace osc{
+
+template< class T >
+class MessageMappingOscPacketListener : public OscPacketListener{
+public:
+    typedef void (T::*function_type)(const osc::ReceivedMessage&, const IpEndpointName&);
+
+protected:
+    void RegisterMessageFunction( const char *addressPattern, function_type f )
+    {
+        functions_.insert( std::make_pair( addressPattern, f ) );
+    }
+
+    virtual void ProcessMessage( const osc::ReceivedMessage& m,
+		const IpEndpointName& remoteEndpoint )
+    {
+        typename function_map_type::iterator i = functions_.find( m.AddressPattern() );
+        if( i != functions_.end() )
+            (dynamic_cast<T*>(this)->*(i->second))( m, remoteEndpoint );
+    }
+    
+private:
+    struct cstr_compare{
+        bool operator()( const char *lhs, const char *rhs ) const
+            { return std::strcmp( lhs, rhs ) < 0; }
+    };
+
+    typedef std::map<const char*, function_type, cstr_compare> function_map_type;
+    function_map_type functions_;
+};
+
+} // namespace osc
+
+#endif /* INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H */
\ No newline at end of file
diff --git a/src/osc/oscPack/osc/OscException.h b/src/osc/oscPack/osc/OscException.h
new file mode 100644
index 0000000..5742762
--- /dev/null
+++ b/src/osc/oscPack/osc/OscException.h
@@ -0,0 +1,62 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_OSCEXCEPTION_H
+#define INCLUDED_OSCPACK_OSCEXCEPTION_H
+
+#include <exception>
+
+namespace osc{
+
+class Exception : public std::exception {
+    const char *what_;
+    
+public:
+    Exception() throw() {}
+    Exception( const Exception& src ) throw()
+        : std::exception( src )
+        , what_( src.what_ ) {}
+    Exception( const char *w ) throw()
+        : what_( w ) {}
+    Exception& operator=( const Exception& src ) throw()
+        { what_ = src.what_; return *this; }
+    virtual ~Exception() throw() {}
+    virtual const char* what() const throw() { return what_; }
+};
+
+} // namespace osc
+
+#endif /* INCLUDED_OSCPACK_OSCEXCEPTION_H */
diff --git a/src/osc/oscPack/osc/OscHostEndianness.h b/src/osc/oscPack/osc/OscHostEndianness.h
new file mode 100644
index 0000000..3bcc376
--- /dev/null
+++ b/src/osc/oscPack/osc/OscHostEndianness.h
@@ -0,0 +1,127 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_OSCHOSTENDIANNESS_H
+#define INCLUDED_OSCPACK_OSCHOSTENDIANNESS_H
+
+/*
+    Make sure either OSC_HOST_LITTLE_ENDIAN or OSC_HOST_BIG_ENDIAN is defined
+
+    We try to use preprocessor symbols to deduce the host endianness.
+
+    Alternatively you can define one of the above symbols from the command line.
+    Usually you do this with the -D flag to the compiler. e.g.:
+
+    $ g++ -DOSC_HOST_LITTLE_ENDIAN ...
+*/
+
+#if defined(OSC_HOST_LITTLE_ENDIAN) || defined(OSC_HOST_BIG_ENDIAN)
+
+// endianness defined on the command line. nothing to do here.
+
+#elif defined(__WIN32__) || defined(WIN32) || defined(WINCE)
+
+// assume that __WIN32__ is only defined on little endian systems
+
+#define OSC_HOST_LITTLE_ENDIAN 1
+#undef OSC_HOST_BIG_ENDIAN
+
+#elif defined(__APPLE__)
+
+#if defined(__LITTLE_ENDIAN__)
+
+#define OSC_HOST_LITTLE_ENDIAN 1
+#undef OSC_HOST_BIG_ENDIAN
+
+#elif defined(__BIG_ENDIAN__)
+
+#define OSC_HOST_BIG_ENDIAN 1
+#undef OSC_HOST_LITTLE_ENDIAN
+
+#endif
+
+#elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__)
+
+// should cover gcc and clang
+
+#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+
+#define OSC_HOST_LITTLE_ENDIAN 1
+#undef OSC_HOST_BIG_ENDIAN
+
+#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+
+#define OSC_HOST_BIG_ENDIAN 1
+#undef OSC_HOST_LITTLE_ENDIAN
+
+#endif
+
+#else
+
+// gcc defines __LITTLE_ENDIAN__ and __BIG_ENDIAN__
+// for others used here see http://sourceforge.net/p/predef/wiki/Endianness/
+#if (defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) \
+    || (defined(__ARMEL__) && !defined(__ARMEB__)) \
+    || (defined(__AARCH64EL__) && !defined(__AARCH64EB__)) \
+    || (defined(_MIPSEL) && !defined(_MIPSEB)) \
+    || (defined(__MIPSEL) && !defined(__MIPSEB)) \
+    || (defined(__MIPSEL__) && !defined(__MIPSEB__))
+
+#define OSC_HOST_LITTLE_ENDIAN 1
+#undef OSC_HOST_BIG_ENDIAN
+
+#elif (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) \
+    || (defined(__ARMEB__) && !defined(__ARMEL__)) \
+    || (defined(__AARCH64EB__) && !defined(__AARCH64EL__)) \
+    || (defined(_MIPSEB) && !defined(_MIPSEL)) \
+    || (defined(__MIPSEB) && !defined(__MIPSEL)) \
+    || (defined(__MIPSEB__) && !defined(__MIPSEL__))
+
+#define OSC_HOST_BIG_ENDIAN 1
+#undef OSC_HOST_LITTLE_ENDIAN
+
+#endif
+
+#endif
+
+#if !defined(OSC_HOST_LITTLE_ENDIAN) && !defined(OSC_HOST_BIG_ENDIAN)
+
+#error please edit OSCHostEndianness.h or define one of {OSC_HOST_LITTLE_ENDIAN, OSC_HOST_BIG_ENDIAN} to configure endianness
+
+#endif
+
+#endif /* INCLUDED_OSCPACK_OSCHOSTENDIANNESS_H */
+
diff --git a/src/osc/oscPack/osc/OscOutboundPacketStream.cpp b/src/osc/oscPack/osc/OscOutboundPacketStream.cpp
new file mode 100644
index 0000000..e54cbd3
--- /dev/null
+++ b/src/osc/oscPack/osc/OscOutboundPacketStream.cpp
@@ -0,0 +1,683 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#include "OscOutboundPacketStream.h"
+
+#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32)
+#include <malloc.h> // for alloca
+#else
+//#include <alloca.h> // alloca on Linux (also OSX)
+#include <stdlib.h> // alloca on OSX and FreeBSD (and Linux?)
+#endif
+
+#include <cassert>
+#include <cstring> // memcpy, memmove, strcpy, strlen
+#include <cstddef> // ptrdiff_t
+
+#include "OscHostEndianness.h"
+
+#if defined(__BORLANDC__) // workaround for BCB4 release build intrinsics bug
+namespace std {
+using ::__strcpy__;  // avoid error: E2316 '__strcpy__' is not a member of 'std'.
+}
+#endif
+
+namespace osc{
+
+static void FromInt32( char *p, int32 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::int32 i;
+        char c[4];
+    } u;
+
+    u.i = x;
+
+    p[3] = u.c[0];
+    p[2] = u.c[1];
+    p[1] = u.c[2];
+    p[0] = u.c[3];
+#else
+    *reinterpret_cast<int32*>(p) = x;
+#endif
+}
+
+
+static void FromUInt32( char *p, uint32 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::uint32 i;
+        char c[4];
+    } u;
+
+    u.i = x;
+
+    p[3] = u.c[0];
+    p[2] = u.c[1];
+    p[1] = u.c[2];
+    p[0] = u.c[3];
+#else
+    *reinterpret_cast<uint32*>(p) = x;
+#endif
+}
+
+
+static void FromInt64( char *p, int64 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::int64 i;
+        char c[8];
+    } u;
+
+    u.i = x;
+
+    p[7] = u.c[0];
+    p[6] = u.c[1];
+    p[5] = u.c[2];
+    p[4] = u.c[3];
+    p[3] = u.c[4];
+    p[2] = u.c[5];
+    p[1] = u.c[6];
+    p[0] = u.c[7];
+#else
+    *reinterpret_cast<int64*>(p) = x;
+#endif
+}
+
+
+static void FromUInt64( char *p, uint64 x )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::uint64 i;
+        char c[8];
+    } u;
+
+    u.i = x;
+
+    p[7] = u.c[0];
+    p[6] = u.c[1];
+    p[5] = u.c[2];
+    p[4] = u.c[3];
+    p[3] = u.c[4];
+    p[2] = u.c[5];
+    p[1] = u.c[6];
+    p[0] = u.c[7];
+#else
+    *reinterpret_cast<uint64*>(p) = x;
+#endif
+}
+
+
+// round up to the next highest multiple of 4. unless x is already a multiple of 4
+static inline std::size_t RoundUp4( std::size_t x ) 
+{
+    return (x + 3) & ~((std::size_t)0x03);
+}
+
+
+OutboundPacketStream::OutboundPacketStream( char *buffer, std::size_t capacity )
+    : data_( buffer )
+    , end_( data_ + capacity )
+    , typeTagsCurrent_( end_ )
+    , messageCursor_( data_ )
+    , argumentCurrent_( data_ )
+    , elementSizePtr_( 0 )
+    , messageIsInProgress_( false )
+{
+    // sanity check integer types declared in OscTypes.h 
+    // you'll need to fix OscTypes.h if any of these asserts fail
+    assert( sizeof(osc::int32) == 4 );
+    assert( sizeof(osc::uint32) == 4 );
+    assert( sizeof(osc::int64) == 8 );
+    assert( sizeof(osc::uint64) == 8 );
+}
+
+
+OutboundPacketStream::~OutboundPacketStream()
+{
+
+}
+
+
+char *OutboundPacketStream::BeginElement( char *beginPtr )
+{
+    if( elementSizePtr_ == 0 ){
+
+        elementSizePtr_ = reinterpret_cast<uint32*>(data_);
+
+        return beginPtr;
+
+    }else{
+        // store an offset to the old element size ptr in the element size slot
+        // we store an offset rather than the actual pointer to be 64 bit clean.
+        *reinterpret_cast<uint32*>(beginPtr) =
+                (uint32)(reinterpret_cast<char*>(elementSizePtr_) - data_);
+
+        elementSizePtr_ = reinterpret_cast<uint32*>(beginPtr);
+
+        return beginPtr + 4;
+    }
+}
+
+
+void OutboundPacketStream::EndElement( char *endPtr )
+{
+    assert( elementSizePtr_ != 0 );
+
+    if( elementSizePtr_ == reinterpret_cast<uint32*>(data_) ){
+
+        elementSizePtr_ = 0;
+
+    }else{
+        // while building an element, an offset to the containing element's
+        // size slot is stored in the elements size slot (or a ptr to data_
+        // if there is no containing element). We retrieve that here
+        uint32 *previousElementSizePtr =
+                reinterpret_cast<uint32*>(data_ + *elementSizePtr_);
+
+        // then we store the element size in the slot. note that the element
+        // size does not include the size slot, hence the - 4 below.
+
+        std::ptrdiff_t d = endPtr - reinterpret_cast<char*>(elementSizePtr_);
+        // assert( d >= 4 && d <= 0x7FFFFFFF ); // assume packets smaller than 2Gb
+
+        uint32 elementSize = static_cast<uint32>(d - 4);
+        FromUInt32( reinterpret_cast<char*>(elementSizePtr_), elementSize );
+
+        // finally, we reset the element size ptr to the containing element
+        elementSizePtr_ = previousElementSizePtr;
+    }
+}
+
+
+bool OutboundPacketStream::ElementSizeSlotRequired() const
+{
+    return (elementSizePtr_ != 0);
+}
+
+
+void OutboundPacketStream::CheckForAvailableBundleSpace()
+{
+    std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0) + 16;
+
+    if( required > Capacity() )
+        throw OutOfBufferMemoryException();
+}
+
+
+void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern )
+{
+    // plus 4 for at least four bytes of type tag
+    std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0)
+            + RoundUp4(std::strlen(addressPattern) + 1) + 4;
+
+    if( required > Capacity() )
+        throw OutOfBufferMemoryException();
+}
+
+
+void OutboundPacketStream::CheckForAvailableArgumentSpace( std::size_t argumentLength )
+{
+    // plus three for extra type tag, comma and null terminator
+    std::size_t required = (argumentCurrent_ - data_) + argumentLength
+            + RoundUp4( (end_ - typeTagsCurrent_) + 3 );
+
+    if( required > Capacity() )
+        throw OutOfBufferMemoryException();
+}
+
+
+void OutboundPacketStream::Clear()
+{
+    typeTagsCurrent_ = end_;
+    messageCursor_ = data_;
+    argumentCurrent_ = data_;
+    elementSizePtr_ = 0;
+    messageIsInProgress_ = false;
+}
+
+
+std::size_t OutboundPacketStream::Capacity() const
+{
+    return end_ - data_;
+}
+
+
+std::size_t OutboundPacketStream::Size() const
+{
+    std::size_t result = argumentCurrent_ - data_;
+    if( IsMessageInProgress() ){
+        // account for the length of the type tag string. the total type tag
+        // includes an initial comma, plus at least one terminating \0
+        result += RoundUp4( (end_ - typeTagsCurrent_) + 2 );
+    }
+
+    return result;
+}
+
+
+const char *OutboundPacketStream::Data() const
+{
+    return data_;
+}
+
+
+bool OutboundPacketStream::IsReady() const
+{
+    return (!IsMessageInProgress() && !IsBundleInProgress());
+}
+
+
+bool OutboundPacketStream::IsMessageInProgress() const
+{
+    return messageIsInProgress_;
+}
+
+
+bool OutboundPacketStream::IsBundleInProgress() const
+{
+    return (elementSizePtr_ != 0);
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs )
+{
+    if( IsMessageInProgress() )
+        throw MessageInProgressException();
+
+    CheckForAvailableBundleSpace();
+
+    messageCursor_ = BeginElement( messageCursor_ );
+
+    std::memcpy( messageCursor_, "#bundle\0", 8 );
+    FromUInt64( messageCursor_ + 8, rhs.timeTag );
+
+    messageCursor_ += 16;
+    argumentCurrent_ = messageCursor_;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator& rhs )
+{
+    (void) rhs;
+
+    if( !IsBundleInProgress() )
+        throw BundleNotInProgressException();
+    if( IsMessageInProgress() )
+        throw MessageInProgressException();
+
+    EndElement( messageCursor_ );
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs )
+{
+    if( IsMessageInProgress() )
+        throw MessageInProgressException();
+
+    CheckForAvailableMessageSpace( rhs.addressPattern );
+
+    messageCursor_ = BeginElement( messageCursor_ );
+
+    std::strcpy( messageCursor_, rhs.addressPattern );
+    std::size_t rhsLength = std::strlen(rhs.addressPattern);
+    messageCursor_ += rhsLength + 1;
+
+    // zero pad to 4-byte boundary
+    std::size_t i = rhsLength + 1;
+    while( i & 0x3 ){
+        *messageCursor_++ = '\0';
+        ++i;
+    }
+
+    argumentCurrent_ = messageCursor_;
+    typeTagsCurrent_ = end_;
+
+    messageIsInProgress_ = true;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& rhs )
+{
+    (void) rhs;
+
+    if( !IsMessageInProgress() )
+        throw MessageNotInProgressException();
+
+    std::size_t typeTagsCount = end_ - typeTagsCurrent_;
+
+    if( typeTagsCount ){
+
+        char *tempTypeTags = (char*)alloca(typeTagsCount);
+        std::memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount );
+
+        // slot size includes comma and null terminator
+        std::size_t typeTagSlotSize = RoundUp4( typeTagsCount + 2 );
+
+        std::size_t argumentsSize = argumentCurrent_ - messageCursor_;
+
+        std::memmove( messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize );
+
+        messageCursor_[0] = ',';
+        // copy type tags in reverse (really forward) order
+        for( std::size_t i=0; i < typeTagsCount; ++i )
+            messageCursor_[i+1] = tempTypeTags[ (typeTagsCount-1) - i ];
+
+        char *p = messageCursor_ + 1 + typeTagsCount;
+        for( std::size_t i=0; i < (typeTagSlotSize - (typeTagsCount + 1)); ++i )
+            *p++ = '\0';
+
+        typeTagsCurrent_ = end_;
+
+        // advance messageCursor_ for next message
+        messageCursor_ += typeTagSlotSize + argumentsSize;
+
+    }else{
+        // send an empty type tags string
+        std::memcpy( messageCursor_, ",\0\0\0", 4 );
+
+        // advance messageCursor_ for next message
+        messageCursor_ += 4;
+    }
+
+    argumentCurrent_ = messageCursor_;
+
+    EndElement( messageCursor_ );
+
+    messageIsInProgress_ = false;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs )
+{
+    CheckForAvailableArgumentSpace(0);
+
+    *(--typeTagsCurrent_) = (char)((rhs) ? TRUE_TYPE_TAG : FALSE_TYPE_TAG);
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs )
+{
+    (void) rhs;
+    CheckForAvailableArgumentSpace(0);
+
+    *(--typeTagsCurrent_) = NIL_TYPE_TAG;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs )
+{
+    (void) rhs;
+    CheckForAvailableArgumentSpace(0);
+
+    *(--typeTagsCurrent_) = INFINITUM_TYPE_TAG;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs )
+{
+    CheckForAvailableArgumentSpace(4);
+
+    *(--typeTagsCurrent_) = INT32_TYPE_TAG;
+    FromInt32( argumentCurrent_, rhs );
+    argumentCurrent_ += 4;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( float rhs )
+{
+    CheckForAvailableArgumentSpace(4);
+
+    *(--typeTagsCurrent_) = FLOAT_TYPE_TAG;
+
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        float f;
+        char c[4];
+    } u;
+
+    u.f = rhs;
+
+    argumentCurrent_[3] = u.c[0];
+    argumentCurrent_[2] = u.c[1];
+    argumentCurrent_[1] = u.c[2];
+    argumentCurrent_[0] = u.c[3];
+#else
+    *reinterpret_cast<float*>(argumentCurrent_) = rhs;
+#endif
+
+    argumentCurrent_ += 4;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )
+{
+    CheckForAvailableArgumentSpace(4);
+
+    *(--typeTagsCurrent_) = CHAR_TYPE_TAG;
+    FromInt32( argumentCurrent_, rhs );
+    argumentCurrent_ += 4;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )
+{
+    CheckForAvailableArgumentSpace(4);
+
+    *(--typeTagsCurrent_) = RGBA_COLOR_TYPE_TAG;
+    FromUInt32( argumentCurrent_, rhs );
+    argumentCurrent_ += 4;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )
+{
+    CheckForAvailableArgumentSpace(4);
+
+    *(--typeTagsCurrent_) = MIDI_MESSAGE_TYPE_TAG;
+    FromUInt32( argumentCurrent_, rhs );
+    argumentCurrent_ += 4;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )
+{
+    CheckForAvailableArgumentSpace(8);
+
+    *(--typeTagsCurrent_) = INT64_TYPE_TAG;
+    FromInt64( argumentCurrent_, rhs );
+    argumentCurrent_ += 8;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )
+{
+    CheckForAvailableArgumentSpace(8);
+
+    *(--typeTagsCurrent_) = TIME_TAG_TYPE_TAG;
+    FromUInt64( argumentCurrent_, rhs );
+    argumentCurrent_ += 8;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )
+{
+    CheckForAvailableArgumentSpace(8);
+
+    *(--typeTagsCurrent_) = DOUBLE_TYPE_TAG;
+
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        double f;
+        char c[8];
+    } u;
+
+    u.f = rhs;
+
+    argumentCurrent_[7] = u.c[0];
+    argumentCurrent_[6] = u.c[1];
+    argumentCurrent_[5] = u.c[2];
+    argumentCurrent_[4] = u.c[3];
+    argumentCurrent_[3] = u.c[4];
+    argumentCurrent_[2] = u.c[5];
+    argumentCurrent_[1] = u.c[6];
+    argumentCurrent_[0] = u.c[7];
+#else
+    *reinterpret_cast<double*>(argumentCurrent_) = rhs;
+#endif
+
+    argumentCurrent_ += 8;
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )
+{
+    CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) );
+
+    *(--typeTagsCurrent_) = STRING_TYPE_TAG;
+    std::strcpy( argumentCurrent_, rhs );
+    std::size_t rhsLength = std::strlen(rhs);
+    argumentCurrent_ += rhsLength + 1;
+
+    // zero pad to 4-byte boundary
+    std::size_t i = rhsLength + 1;
+    while( i & 0x3 ){
+        *argumentCurrent_++ = '\0';
+        ++i;
+    }
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs )
+{
+    CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) );
+
+    *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG;
+    std::strcpy( argumentCurrent_, rhs );
+    std::size_t rhsLength = std::strlen(rhs);
+    argumentCurrent_ += rhsLength + 1;
+
+    // zero pad to 4-byte boundary
+    std::size_t i = rhsLength + 1;
+    while( i & 0x3 ){
+        *argumentCurrent_++ = '\0';
+        ++i;
+    }
+
+    return *this;
+}
+
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )
+{
+    CheckForAvailableArgumentSpace( 4 + RoundUp4(rhs.size) );
+
+    *(--typeTagsCurrent_) = BLOB_TYPE_TAG;
+    FromUInt32( argumentCurrent_, rhs.size );
+    argumentCurrent_ += 4;
+    
+    std::memcpy( argumentCurrent_, rhs.data, rhs.size );
+    argumentCurrent_ += rhs.size;
+
+    // zero pad to 4-byte boundary
+    unsigned long i = rhs.size;
+    while( i & 0x3 ){
+        *argumentCurrent_++ = '\0';
+        ++i;
+    }
+
+    return *this;
+}
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rhs )
+{
+    (void) rhs;
+    CheckForAvailableArgumentSpace(0);
+
+    *(--typeTagsCurrent_) = ARRAY_BEGIN_TYPE_TAG;
+
+    return *this;
+}
+
+OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayTerminator& rhs )
+{
+    (void) rhs;
+    CheckForAvailableArgumentSpace(0);
+
+    *(--typeTagsCurrent_) = ARRAY_END_TYPE_TAG;
+
+    return *this;
+}
+
+} // namespace osc
+
+
diff --git a/src/osc/oscPack/osc/OscOutboundPacketStream.h b/src/osc/oscPack/osc/OscOutboundPacketStream.h
new file mode 100644
index 0000000..26f3e58
--- /dev/null
+++ b/src/osc/oscPack/osc/OscOutboundPacketStream.h
@@ -0,0 +1,154 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H
+#define INCLUDED_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H
+
+#include <cstring> // size_t
+
+#include "OscTypes.h"
+#include "OscException.h"
+
+
+namespace osc{
+
+class OutOfBufferMemoryException : public Exception{
+public:
+    OutOfBufferMemoryException( const char *w="out of buffer memory" )
+        : Exception( w ) {}
+};
+
+class BundleNotInProgressException : public Exception{
+public:
+    BundleNotInProgressException(
+            const char *w="call to EndBundle when bundle is not in progress" )
+        : Exception( w ) {}
+};
+
+class MessageInProgressException : public Exception{
+public:
+    MessageInProgressException(
+            const char *w="opening or closing bundle or message while message is in progress" )
+        : Exception( w ) {}
+};
+
+class MessageNotInProgressException : public Exception{
+public:
+    MessageNotInProgressException(
+            const char *w="call to EndMessage when message is not in progress" )
+        : Exception( w ) {}
+};
+
+
+class OutboundPacketStream{
+public:
+	OutboundPacketStream( char *buffer, std::size_t capacity );
+	~OutboundPacketStream();
+
+    void Clear();
+
+    std::size_t Capacity() const;
+
+    // invariant: size() is valid even while building a message.
+    std::size_t Size() const;
+
+    const char *Data() const;
+
+    // indicates that all messages have been closed with a matching EndMessage
+    // and all bundles have been closed with a matching EndBundle
+    bool IsReady() const;
+
+    bool IsMessageInProgress() const;
+    bool IsBundleInProgress() const;
+
+    OutboundPacketStream& operator<<( const BundleInitiator& rhs );
+    OutboundPacketStream& operator<<( const BundleTerminator& rhs );
+    
+    OutboundPacketStream& operator<<( const BeginMessage& rhs );
+    OutboundPacketStream& operator<<( const MessageTerminator& rhs );
+
+    OutboundPacketStream& operator<<( bool rhs );
+    OutboundPacketStream& operator<<( const NilType& rhs );
+    OutboundPacketStream& operator<<( const InfinitumType& rhs );
+    OutboundPacketStream& operator<<( int32 rhs );
+
+#if !(defined(__x86_64__) || defined(_M_X64))
+    OutboundPacketStream& operator<<( int rhs )
+            { *this << (int32)rhs; return *this; }
+#endif
+
+    OutboundPacketStream& operator<<( float rhs );
+    OutboundPacketStream& operator<<( char rhs );
+    OutboundPacketStream& operator<<( const RgbaColor& rhs );
+    OutboundPacketStream& operator<<( const MidiMessage& rhs );
+    OutboundPacketStream& operator<<( int64 rhs );
+    OutboundPacketStream& operator<<( const TimeTag& rhs );
+    OutboundPacketStream& operator<<( double rhs );
+    OutboundPacketStream& operator<<( const char* rhs );
+    OutboundPacketStream& operator<<( const Symbol& rhs );
+    OutboundPacketStream& operator<<( const Blob& rhs );
+
+    OutboundPacketStream& operator<<( const ArrayInitiator& rhs );
+    OutboundPacketStream& operator<<( const ArrayTerminator& rhs );
+
+private:
+
+    char *BeginElement( char *beginPtr );
+    void EndElement( char *endPtr );
+
+    bool ElementSizeSlotRequired() const;
+    void CheckForAvailableBundleSpace();
+    void CheckForAvailableMessageSpace( const char *addressPattern );
+    void CheckForAvailableArgumentSpace( std::size_t argumentLength );
+
+    char *data_;
+    char *end_;
+
+    char *typeTagsCurrent_; // stored in reverse order
+    char *messageCursor_;
+    char *argumentCurrent_;
+
+    // elementSizePtr_ has two special values: 0 indicates that a bundle
+    // isn't open, and elementSizePtr_==data_ indicates that a bundle is
+    // open but that it doesn't have a size slot (ie the outermost bundle)
+    uint32 *elementSizePtr_;
+
+    bool messageIsInProgress_;
+};
+
+} // namespace osc
+
+#endif /* INCLUDED_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H */
diff --git a/src/osc/oscPack/osc/OscPacketListener.h b/src/osc/oscPack/osc/OscPacketListener.h
new file mode 100644
index 0000000..c77e924
--- /dev/null
+++ b/src/osc/oscPack/osc/OscPacketListener.h
@@ -0,0 +1,79 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_OSCPACKETLISTENER_H
+#define INCLUDED_OSCPACK_OSCPACKETLISTENER_H
+
+#include "OscReceivedElements.h"
+#include "../ip/PacketListener.h"
+
+
+namespace osc{
+
+class OscPacketListener : public PacketListener{ 
+protected:
+    virtual void ProcessBundle( const osc::ReceivedBundle& b, 
+				const IpEndpointName& remoteEndpoint )
+    {
+        // ignore bundle time tag for now
+
+        for( ReceivedBundle::const_iterator i = b.ElementsBegin(); 
+				i != b.ElementsEnd(); ++i ){
+            if( i->IsBundle() )
+                ProcessBundle( ReceivedBundle(*i), remoteEndpoint );
+            else
+                ProcessMessage( ReceivedMessage(*i), remoteEndpoint );
+        }
+    }
+
+    virtual void ProcessMessage( const osc::ReceivedMessage& m, 
+				const IpEndpointName& remoteEndpoint ) = 0;
+    
+public:
+	virtual void ProcessPacket( const char *data, int size, 
+			const IpEndpointName& remoteEndpoint )
+    {
+        osc::ReceivedPacket p( data, size );
+        if( p.IsBundle() )
+            ProcessBundle( ReceivedBundle(p), remoteEndpoint );
+        else
+            ProcessMessage( ReceivedMessage(p), remoteEndpoint );
+    }
+};
+
+} // namespace osc
+
+#endif /* INCLUDED_OSCPACK_OSCPACKETLISTENER_H */
diff --git a/src/osc/oscPack/osc/OscPrintReceivedElements.cpp b/src/osc/oscPack/osc/OscPrintReceivedElements.cpp
new file mode 100644
index 0000000..72e0bc5
--- /dev/null
+++ b/src/osc/oscPack/osc/OscPrintReceivedElements.cpp
@@ -0,0 +1,261 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#include "OscPrintReceivedElements.h"
+
+#include <cstring>
+#include <ctime>
+#include <iostream>
+#include <iomanip>
+
+#if defined(__BORLANDC__) // workaround for BCB4 release build intrinsics bug
+namespace std {
+using ::__strcpy__;  // avoid error: E2316 '__strcpy__' is not a member of 'std'.
+}
+#endif
+
+namespace osc{
+
+
+std::ostream& operator<<( std::ostream & os,
+        const ReceivedMessageArgument& arg )
+{
+    switch( arg.TypeTag() ){
+        case TRUE_TYPE_TAG:
+            os << "bool:true";
+            break;
+                
+        case FALSE_TYPE_TAG:
+            os << "bool:false";
+            break;
+
+        case NIL_TYPE_TAG:
+            os << "(Nil)";
+            break;
+
+        case INFINITUM_TYPE_TAG:
+            os << "(Infinitum)";
+            break;
+
+        case INT32_TYPE_TAG:
+            os << "int32:" << arg.AsInt32Unchecked();
+            break;
+
+        case FLOAT_TYPE_TAG:
+            os << "float32:" << arg.AsFloatUnchecked();
+            break;
+
+        case CHAR_TYPE_TAG:
+            {
+                char s[2] = {0};
+                s[0] = arg.AsCharUnchecked();
+                os << "char:'" << s << "'";
+            }
+            break;
+
+        case RGBA_COLOR_TYPE_TAG:
+            {
+                uint32 color = arg.AsRgbaColorUnchecked();
+                
+                os << "RGBA:0x"
+                        << std::hex << std::setfill('0')
+                        << std::setw(2) << (int)((color>>24) & 0xFF)
+                        << std::setw(2) << (int)((color>>16) & 0xFF)
+                        << std::setw(2) << (int)((color>>8) & 0xFF)
+                        << std::setw(2) << (int)(color & 0xFF)
+                        << std::setfill(' ');
+                os.unsetf(std::ios::basefield);
+            }
+            break;
+
+        case MIDI_MESSAGE_TYPE_TAG:
+            {
+                uint32 m = arg.AsMidiMessageUnchecked();
+                os << "midi (port, status, data1, data2):<<"
+                        << std::hex << std::setfill('0')
+                        << "0x" << std::setw(2) << (int)((m>>24) & 0xFF)
+                        << " 0x" << std::setw(2) << (int)((m>>16) & 0xFF)
+                        << " 0x" << std::setw(2) << (int)((m>>8) & 0xFF)
+                        << " 0x" << std::setw(2) << (int)(m & 0xFF)
+                        << std::setfill(' ') << ">>";
+                os.unsetf(std::ios::basefield);
+            }
+            break;
+				
+        case INT64_TYPE_TAG:
+            os << "int64:" << arg.AsInt64Unchecked();
+            break;
+
+        case TIME_TAG_TYPE_TAG:
+            {
+                os << "OSC-timetag:" << arg.AsTimeTagUnchecked() << " ";
+
+                std::time_t t =
+                        (unsigned long)( arg.AsTimeTagUnchecked() >> 32 );
+
+                const char *timeString = std::ctime( &t );
+                size_t len = std::strlen( timeString );
+
+                // -1 to omit trailing newline from string returned by ctime()
+                if( len > 1 )
+                    os.write( timeString, len - 1 );
+            }
+            break;
+                
+        case DOUBLE_TYPE_TAG:
+            os << "double:" << arg.AsDoubleUnchecked();
+            break;
+
+        case STRING_TYPE_TAG:
+            os << "OSC-string:`" << arg.AsStringUnchecked() << "'";
+            break;
+                
+        case SYMBOL_TYPE_TAG: 
+            os << "OSC-string (symbol):`" << arg.AsSymbolUnchecked() << "'";
+            break;
+
+        case BLOB_TYPE_TAG:
+            {
+                const void *data;
+                osc_bundle_element_size_t size;
+                arg.AsBlobUnchecked( data, size );
+                os << "OSC-blob:<<" << std::hex << std::setfill('0');
+                unsigned char *p = (unsigned char*)data;
+                for( osc_bundle_element_size_t i = 0; i < size; ++i ){
+                    os << "0x" << std::setw(2) << int(p[i]);
+                    if( i != size-1 )
+                        os << ' ';
+                }
+                os.unsetf(std::ios::basefield);
+                os << ">>" << std::setfill(' ');
+            }
+            break;
+
+        case ARRAY_BEGIN_TYPE_TAG:
+            os << "[";
+            break;
+
+        case ARRAY_END_TYPE_TAG:
+            os << "]";
+            break;
+
+        default:
+            os << "unknown";
+    }
+
+    return os;
+}
+
+
+std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m )
+{
+    os << "[";
+    if( m.AddressPatternIsUInt32() )
+        os << m.AddressPatternAsUInt32();
+    else
+        os << m.AddressPattern();
+    
+    bool first = true;
+    for( ReceivedMessage::const_iterator i = m.ArgumentsBegin();
+            i != m.ArgumentsEnd(); ++i ){
+        if( first ){
+            os << " ";
+            first = false;
+        }else{
+            os << ", ";
+        }
+
+        os << *i;
+    }
+
+    os << "]";
+
+    return os;
+}
+
+
+std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b )
+{
+    static int indent = 0;
+
+    for( int j=0; j < indent; ++j )
+        os << "  ";
+    os << "{ ( ";
+    if( b.TimeTag() == 1 )
+        os << "immediate";
+    else
+        os << b.TimeTag();
+    os << " )\n";
+
+    ++indent;
+    
+    for( ReceivedBundle::const_iterator i = b.ElementsBegin();
+            i != b.ElementsEnd(); ++i ){
+        if( i->IsBundle() ){
+            ReceivedBundle b(*i);
+            os << b << "\n";
+        }else{
+            ReceivedMessage m(*i);
+            for( int j=0; j < indent; ++j )
+                os << "  ";
+            os << m << "\n";
+        }
+    }
+
+    --indent;
+
+    for( int j=0; j < indent; ++j )
+        os << "  ";
+    os << "}";
+
+    return os;
+}
+
+
+std::ostream& operator<<( std::ostream & os, const ReceivedPacket& p )
+{
+    if( p.IsBundle() ){
+        ReceivedBundle b(p);
+        os << b << "\n";
+    }else{
+        ReceivedMessage m(p);
+        os << m << "\n";
+    }
+
+    return os;
+}
+
+} // namespace osc
diff --git a/src/osc/oscPack/osc/OscPrintReceivedElements.h b/src/osc/oscPack/osc/OscPrintReceivedElements.h
new file mode 100644
index 0000000..7561c01
--- /dev/null
+++ b/src/osc/oscPack/osc/OscPrintReceivedElements.h
@@ -0,0 +1,54 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H
+#define INCLUDED_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H
+
+#include <iosfwd>
+
+#include "OscReceivedElements.h"
+
+
+namespace osc{
+
+std::ostream& operator<<( std::ostream & os, const ReceivedPacket& p );
+std::ostream& operator<<( std::ostream & os, const ReceivedMessageArgument& arg );
+std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m );
+std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b );
+
+} // namespace osc
+
+#endif /* INCLUDED_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H */
diff --git a/src/osc/oscPack/osc/OscReceivedElements.cpp b/src/osc/oscPack/osc/OscReceivedElements.cpp
new file mode 100644
index 0000000..dd19a44
--- /dev/null
+++ b/src/osc/oscPack/osc/OscReceivedElements.cpp
@@ -0,0 +1,801 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#include "OscReceivedElements.h"
+
+#include "OscHostEndianness.h"
+
+#include <cstddef> // ptrdiff_t
+
+namespace osc{
+
+
+// return the first 4 byte boundary after the end of a str4
+// be careful about calling this version if you don't know whether
+// the string is terminated correctly.
+static inline const char* FindStr4End( const char *p )
+{
+	if( p[0] == '\0' )    // special case for SuperCollider integer address pattern
+		return p + 4;
+
+    p += 3;
+
+    while( *p )
+        p += 4;
+
+    return p + 1;
+}
+
+
+// return the first 4 byte boundary after the end of a str4
+// returns 0 if p == end or if the string is unterminated
+static inline const char* FindStr4End( const char *p, const char *end )
+{
+    if(p >= end) {
+        return 0;
+    }
+
+    if( p[0] == '\0' ) {   // special case for SuperCollider integer address pattern
+        return p + 4;
+    }
+
+    p += 3;
+    end -= 1;
+
+    while( p < end && *p ) {
+        p += 4;
+    }
+
+    if( *p ) {
+        return 0;
+    }
+    else {
+        return p + 1;
+    }
+}
+
+
+// round up to the next highest multiple of 4. unless x is already a multiple of 4
+static inline uint32 RoundUp4( uint32 x ) 
+{
+    return (x + 3) & ~((uint32)0x03);
+}
+
+
+static inline int32 ToInt32( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::int32 i;
+        char c[4];
+    } u;
+
+    u.c[0] = p[3];
+    u.c[1] = p[2];
+    u.c[2] = p[1];
+    u.c[3] = p[0];
+
+    return u.i;
+#else
+	return *(int32*)p;
+#endif
+}
+
+
+static inline uint32 ToUInt32( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::uint32 i;
+        char c[4];
+    } u;
+
+    u.c[0] = p[3];
+    u.c[1] = p[2];
+    u.c[2] = p[1];
+    u.c[3] = p[0];
+
+    return u.i;
+#else
+	return *(uint32*)p;
+#endif
+}
+
+
+static inline int64 ToInt64( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::int64 i;
+        char c[8];
+    } u;
+
+    u.c[0] = p[7];
+    u.c[1] = p[6];
+    u.c[2] = p[5];
+    u.c[3] = p[4];
+    u.c[4] = p[3];
+    u.c[5] = p[2];
+    u.c[6] = p[1];
+    u.c[7] = p[0];
+
+    return u.i;
+#else
+	return *(int64*)p;
+#endif
+}
+
+
+static inline uint64 ToUInt64( const char *p )
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::uint64 i;
+        char c[8];
+    } u;
+
+    u.c[0] = p[7];
+    u.c[1] = p[6];
+    u.c[2] = p[5];
+    u.c[3] = p[4];
+    u.c[4] = p[3];
+    u.c[5] = p[2];
+    u.c[6] = p[1];
+    u.c[7] = p[0];
+
+    return u.i;
+#else
+	return *(uint64*)p;
+#endif
+}
+
+//------------------------------------------------------------------------------
+
+bool ReceivedPacket::IsBundle() const
+{
+    return (Size() > 0 && Contents()[0] == '#');
+}
+
+//------------------------------------------------------------------------------
+
+bool ReceivedBundleElement::IsBundle() const
+{
+    return (Size() > 0 && Contents()[0] == '#');
+}
+
+
+osc_bundle_element_size_t ReceivedBundleElement::Size() const
+{
+    return ToInt32( sizePtr_ );
+}
+
+//------------------------------------------------------------------------------
+
+bool ReceivedMessageArgument::AsBool() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == TRUE_TYPE_TAG )
+		return true;
+	else if( *typeTagPtr_ == FALSE_TYPE_TAG )
+		return false;
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+bool ReceivedMessageArgument::AsBoolUnchecked() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == TRUE_TYPE_TAG )
+		return true;
+    else
+	    return false;
+}
+
+
+int32 ReceivedMessageArgument::AsInt32() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == INT32_TYPE_TAG )
+		return AsInt32Unchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+int32 ReceivedMessageArgument::AsInt32Unchecked() const
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        osc::int32 i;
+        char c[4];
+    } u;
+
+    u.c[0] = argumentPtr_[3];
+    u.c[1] = argumentPtr_[2];
+    u.c[2] = argumentPtr_[1];
+    u.c[3] = argumentPtr_[0];
+
+    return u.i;
+#else
+	return *(int32*)argument_;
+#endif
+}
+
+
+float ReceivedMessageArgument::AsFloat() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == FLOAT_TYPE_TAG )
+		return AsFloatUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+float ReceivedMessageArgument::AsFloatUnchecked() const
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        float f;
+        char c[4];
+    } u;
+
+    u.c[0] = argumentPtr_[3];
+    u.c[1] = argumentPtr_[2];
+    u.c[2] = argumentPtr_[1];
+    u.c[3] = argumentPtr_[0];
+
+    return u.f;
+#else
+	return *(float*)argument_;
+#endif
+}
+
+
+char ReceivedMessageArgument::AsChar() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == CHAR_TYPE_TAG )
+		return AsCharUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+char ReceivedMessageArgument::AsCharUnchecked() const
+{
+    return (char)ToInt32( argumentPtr_ );
+}
+
+
+uint32 ReceivedMessageArgument::AsRgbaColor() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == RGBA_COLOR_TYPE_TAG )
+		return AsRgbaColorUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const
+{
+	return ToUInt32( argumentPtr_ );
+}
+
+
+uint32 ReceivedMessageArgument::AsMidiMessage() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG )
+		return AsMidiMessageUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const
+{
+	return ToUInt32( argumentPtr_ );
+}
+
+
+int64 ReceivedMessageArgument::AsInt64() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == INT64_TYPE_TAG )
+		return AsInt64Unchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+int64 ReceivedMessageArgument::AsInt64Unchecked() const
+{
+    return ToInt64( argumentPtr_ );
+}
+
+
+uint64 ReceivedMessageArgument::AsTimeTag() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == TIME_TAG_TYPE_TAG )
+		return AsTimeTagUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const
+{
+    return ToUInt64( argumentPtr_ );
+}
+
+
+double ReceivedMessageArgument::AsDouble() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == DOUBLE_TYPE_TAG )
+		return AsDoubleUnchecked();
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+double ReceivedMessageArgument::AsDoubleUnchecked() const
+{
+#ifdef OSC_HOST_LITTLE_ENDIAN
+    union{
+        double d;
+        char c[8];
+    } u;
+
+    u.c[0] = argumentPtr_[7];
+    u.c[1] = argumentPtr_[6];
+    u.c[2] = argumentPtr_[5];
+    u.c[3] = argumentPtr_[4];
+    u.c[4] = argumentPtr_[3];
+    u.c[5] = argumentPtr_[2];
+    u.c[6] = argumentPtr_[1];
+    u.c[7] = argumentPtr_[0];
+
+    return u.d;
+#else
+	return *(double*)argument_;
+#endif
+}
+
+
+const char* ReceivedMessageArgument::AsString() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == STRING_TYPE_TAG )
+		return argumentPtr_;
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+const char* ReceivedMessageArgument::AsSymbol() const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == SYMBOL_TYPE_TAG )
+		return argumentPtr_;
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+void ReceivedMessageArgument::AsBlob( const void*& data, osc_bundle_element_size_t& size ) const
+{
+    if( !typeTagPtr_ )
+        throw MissingArgumentException();
+	else if( *typeTagPtr_ == BLOB_TYPE_TAG )
+		AsBlobUnchecked( data, size );
+	else
+		throw WrongArgumentTypeException();
+}
+
+
+void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const
+{
+    // read blob size as an unsigned int then validate
+    osc_bundle_element_size_t sizeResult = (osc_bundle_element_size_t)ToUInt32( argumentPtr_ );
+    if( !IsValidElementSizeValue(sizeResult) )
+        throw MalformedMessageException("invalid blob size");
+
+    size = sizeResult;
+	data = (void*)(argumentPtr_+ osc::OSC_SIZEOF_INT32);
+}
+
+std::size_t ReceivedMessageArgument::ComputeArrayItemCount() const
+{
+    // it is only valid to call ComputeArrayItemCount when the argument is the array start marker
+    if( !IsArrayBegin() )
+        throw WrongArgumentTypeException();
+
+    std::size_t result = 0;
+    unsigned int level = 0;
+    const char *typeTag = typeTagPtr_ + 1;
+
+    // iterate through all type tags. note that ReceivedMessage::Init
+    // has already checked that the message is well formed.
+    while( *typeTag ) {
+        switch( *typeTag++ ) {
+            case ARRAY_BEGIN_TYPE_TAG:
+                level += 1;
+                break;
+
+            case ARRAY_END_TYPE_TAG:
+                if(level == 0)
+                    return result;
+                level -= 1;
+                break;
+
+            default:
+                if( level == 0 ) // only count items at level 0
+                    ++result;
+        }
+    }
+
+    return result;
+}
+
+//------------------------------------------------------------------------------
+
+void ReceivedMessageArgumentIterator::Advance()
+{
+    if( !value_.typeTagPtr_ )
+        return;
+        
+    switch( *value_.typeTagPtr_++ ){
+        case '\0':
+            // don't advance past end
+            --value_.typeTagPtr_;
+            break;
+            
+        case TRUE_TYPE_TAG:
+        case FALSE_TYPE_TAG:
+        case NIL_TYPE_TAG:
+        case INFINITUM_TYPE_TAG:
+        
+            // zero length
+            break;
+
+        case INT32_TYPE_TAG:
+        case FLOAT_TYPE_TAG: 					
+        case CHAR_TYPE_TAG:
+        case RGBA_COLOR_TYPE_TAG:
+        case MIDI_MESSAGE_TYPE_TAG:
+
+            value_.argumentPtr_ += 4;
+            break;
+
+        case INT64_TYPE_TAG:
+        case TIME_TAG_TYPE_TAG:
+        case DOUBLE_TYPE_TAG:
+				
+            value_.argumentPtr_ += 8;
+            break;
+
+        case STRING_TYPE_TAG: 
+        case SYMBOL_TYPE_TAG:
+
+            // we use the unsafe function FindStr4End(char*) here because all of
+            // the arguments have already been validated in
+            // ReceivedMessage::Init() below.
+            
+            value_.argumentPtr_ = FindStr4End( value_.argumentPtr_ );
+            break;
+
+        case BLOB_TYPE_TAG:
+            {
+                // treat blob size as an unsigned int for the purposes of this calculation
+                uint32 blobSize = ToUInt32( value_.argumentPtr_ );
+                value_.argumentPtr_ = value_.argumentPtr_ + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize );
+            }
+            break;
+
+        case ARRAY_BEGIN_TYPE_TAG:
+        case ARRAY_END_TYPE_TAG: 
+
+            //    [ Indicates the beginning of an array. The tags following are for
+            //        data in the Array until a close brace tag is reached.
+            //    ] Indicates the end of an array.
+
+            // zero length, don't advance argument ptr
+            break;
+
+        default:    // unknown type tag
+            // don't advance
+            --value_.typeTagPtr_;
+            break;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet )
+    : addressPattern_( packet.Contents() )
+{
+    Init( packet.Contents(), packet.Size() );
+}
+
+
+ReceivedMessage::ReceivedMessage( const ReceivedBundleElement& bundleElement )
+    : addressPattern_( bundleElement.Contents() )
+{
+    Init( bundleElement.Contents(), bundleElement.Size() );
+}
+
+
+bool ReceivedMessage::AddressPatternIsUInt32() const
+{
+	return (addressPattern_[0] == '\0');
+}
+
+
+uint32 ReceivedMessage::AddressPatternAsUInt32() const
+{
+    return ToUInt32( addressPattern_ );
+}
+
+
+void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size )
+{
+    if( !IsValidElementSizeValue(size) )
+        throw MalformedMessageException( "invalid message size" );
+
+    if( size == 0 )
+        throw MalformedMessageException( "zero length messages not permitted" );
+
+    if( !IsMultipleOf4(size) )
+        throw MalformedMessageException( "message size must be multiple of four" );
+
+    const char *end = message + size;
+
+    typeTagsBegin_ = FindStr4End( addressPattern_, end );
+    if( typeTagsBegin_ == 0 ){
+        // address pattern was not terminated before end
+        throw MalformedMessageException( "unterminated address pattern" );
+    }
+
+    if( typeTagsBegin_ == end ){
+        // message consists of only the address pattern - no arguments or type tags.
+        typeTagsBegin_ = 0;
+        typeTagsEnd_ = 0;
+        arguments_ = 0;
+            
+    }else{
+        if( *typeTagsBegin_ != ',' )
+            throw MalformedMessageException( "type tags not present" );
+
+        if( *(typeTagsBegin_ + 1) == '\0' ){
+            // zero length type tags
+            typeTagsBegin_ = 0;
+            typeTagsEnd_ = 0;
+            arguments_ = 0;
+
+        }else{
+            // check that all arguments are present and well formed
+                
+            arguments_ = FindStr4End( typeTagsBegin_, end );
+            if( arguments_ == 0 ){
+                throw MalformedMessageException( "type tags were not terminated before end of message" );
+            }
+
+            ++typeTagsBegin_; // advance past initial ','
+            
+            const char *typeTag = typeTagsBegin_;
+            const char *argument = arguments_;
+            unsigned int arrayLevel = 0;
+                        
+            do{
+                switch( *typeTag ){
+                    case TRUE_TYPE_TAG:
+                    case FALSE_TYPE_TAG:
+                    case NIL_TYPE_TAG:
+                    case INFINITUM_TYPE_TAG:
+                        // zero length
+                        break;
+
+                    //    [ Indicates the beginning of an array. The tags following are for
+                    //        data in the Array until a close brace tag is reached.
+                    //    ] Indicates the end of an array.
+                    case ARRAY_BEGIN_TYPE_TAG:
+                        ++arrayLevel;
+                        // (zero length argument data)
+                        break;
+
+                    case ARRAY_END_TYPE_TAG:
+                        --arrayLevel;
+                        // (zero length argument data)
+                        break;
+
+                    case INT32_TYPE_TAG:
+                    case FLOAT_TYPE_TAG:
+                    case CHAR_TYPE_TAG:
+                    case RGBA_COLOR_TYPE_TAG:
+                    case MIDI_MESSAGE_TYPE_TAG:
+
+                        if( argument == end )
+                            throw MalformedMessageException( "arguments exceed message size" );
+                        argument += 4;
+                        if( argument > end )
+                            throw MalformedMessageException( "arguments exceed message size" );
+                        break;
+
+                    case INT64_TYPE_TAG:
+                    case TIME_TAG_TYPE_TAG:
+                    case DOUBLE_TYPE_TAG:
+
+                        if( argument == end )
+                            throw MalformedMessageException( "arguments exceed message size" );
+                        argument += 8;
+                        if( argument > end )
+                            throw MalformedMessageException( "arguments exceed message size" );
+                        break;
+
+                    case STRING_TYPE_TAG: 
+                    case SYMBOL_TYPE_TAG:
+                    
+                        if( argument == end )
+                            throw MalformedMessageException( "arguments exceed message size" );
+                        argument = FindStr4End( argument, end );
+                        if( argument == 0 )
+                            throw MalformedMessageException( "unterminated string argument" );
+                        break;
+
+                    case BLOB_TYPE_TAG:
+                        {
+                            if( argument + osc::OSC_SIZEOF_INT32 > end )
+                                MalformedMessageException( "arguments exceed message size" );
+                                
+                            // treat blob size as an unsigned int for the purposes of this calculation
+                            uint32 blobSize = ToUInt32( argument );
+                            argument = argument + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize );
+                            if( argument > end )
+                                MalformedMessageException( "arguments exceed message size" );
+                        }
+                        break;
+                        
+                    default:
+                        throw MalformedMessageException( "unknown type tag" );
+                }
+
+            }while( *++typeTag != '\0' );
+            typeTagsEnd_ = typeTag;
+
+            if( arrayLevel !=  0 )
+                throw MalformedMessageException( "array was not terminated before end of message (expected ']' end of array tag)" );
+        }
+
+        // These invariants should be guaranteed by the above code.
+        // we depend on them in the implementation of ArgumentCount()
+#ifndef NDEBUG
+        std::ptrdiff_t argumentCount = typeTagsEnd_ - typeTagsBegin_;
+        assert( argumentCount >= 0 );
+        assert( argumentCount <= OSC_INT32_MAX );
+#endif
+    }
+}
+
+//------------------------------------------------------------------------------
+
+ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet )
+    : elementCount_( 0 )
+{
+    Init( packet.Contents(), packet.Size() );
+}
+
+
+ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement )
+    : elementCount_( 0 )
+{
+    Init( bundleElement.Contents(), bundleElement.Size() );
+}
+
+
+void ReceivedBundle::Init( const char *bundle, osc_bundle_element_size_t size )
+{
+
+    if( !IsValidElementSizeValue(size) )
+        throw MalformedBundleException( "invalid bundle size" );
+
+    if( size < 16 )
+        throw MalformedBundleException( "packet too short for bundle" );
+
+    if( !IsMultipleOf4(size) )
+        throw MalformedBundleException( "bundle size must be multiple of four" );
+
+    if( bundle[0] != '#'
+        || bundle[1] != 'b'
+        || bundle[2] != 'u'
+        || bundle[3] != 'n'
+        || bundle[4] != 'd'
+        || bundle[5] != 'l'
+        || bundle[6] != 'e'
+        || bundle[7] != '\0' )
+            throw MalformedBundleException( "bad bundle address pattern" );    
+
+    end_ = bundle + size;
+
+    timeTag_ = bundle + 8;
+
+    const char *p = timeTag_ + 8;
+        
+    while( p < end_ ){
+        if( p + osc::OSC_SIZEOF_INT32 > end_ )
+            throw MalformedBundleException( "packet too short for elementSize" );
+
+        // treat element size as an unsigned int for the purposes of this calculation
+        uint32 elementSize = ToUInt32( p );
+        if( (elementSize & ((uint32)0x03)) != 0 )
+            throw MalformedBundleException( "bundle element size must be multiple of four" );
+
+        p += osc::OSC_SIZEOF_INT32 + elementSize;
+        if( p > end_ )
+            throw MalformedBundleException( "packet too short for bundle element" );
+
+        ++elementCount_;
+    }
+
+    if( p != end_ )
+        throw MalformedBundleException( "bundle contents " );
+}
+
+
+uint64 ReceivedBundle::TimeTag() const
+{
+    return ToUInt64( timeTag_ );
+}
+
+
+} // namespace osc
+
diff --git a/src/osc/oscPack/osc/OscReceivedElements.h b/src/osc/oscPack/osc/OscReceivedElements.h
new file mode 100644
index 0000000..729938e
--- /dev/null
+++ b/src/osc/oscPack/osc/OscReceivedElements.h
@@ -0,0 +1,548 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H
+#define INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H
+
+#include <cassert>
+#include <cstddef>
+#include <cstring> // size_t
+
+#include "OscTypes.h"
+#include "OscException.h"
+
+
+namespace osc{
+
+
+class MalformedPacketException : public Exception{
+public:
+    MalformedPacketException( const char *w="malformed packet" )
+        : Exception( w ) {}
+};
+
+class MalformedMessageException : public Exception{
+public:
+    MalformedMessageException( const char *w="malformed message" )
+        : Exception( w ) {}
+};
+
+class MalformedBundleException : public Exception{
+public:
+    MalformedBundleException( const char *w="malformed bundle" )
+        : Exception( w ) {}
+};
+
+class WrongArgumentTypeException : public Exception{
+public:
+    WrongArgumentTypeException( const char *w="wrong argument type" )
+        : Exception( w ) {}
+};
+
+class MissingArgumentException : public Exception{
+public:
+    MissingArgumentException( const char *w="missing argument" )
+        : Exception( w ) {}
+};
+
+class ExcessArgumentException : public Exception{
+public:
+    ExcessArgumentException( const char *w="too many arguments" )
+        : Exception( w ) {}
+};
+
+
+class ReceivedPacket{
+public:
+    // Although the OSC spec is not entirely clear on this, we only support
+    // packets up to 0x7FFFFFFC bytes long (the maximum 4-byte aligned value
+    // representable by an int32). An exception will be raised if you pass a 
+    // larger value to the ReceivedPacket() constructor.
+
+    ReceivedPacket( const char *contents, osc_bundle_element_size_t size )
+        : contents_( contents )
+        , size_( ValidateSize(size) ) {}
+
+    ReceivedPacket( const char *contents, std::size_t size )
+        : contents_( contents )
+        , size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {}
+
+#if !(defined(__x86_64__) || defined(_M_X64))
+    ReceivedPacket( const char *contents, int size )
+        : contents_( contents )
+        , size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {}
+#endif
+
+    bool IsMessage() const { return !IsBundle(); }
+    bool IsBundle() const;
+
+    osc_bundle_element_size_t Size() const { return size_; }
+    const char *Contents() const { return contents_; }
+
+private:
+    const char *contents_;
+    osc_bundle_element_size_t size_;
+
+    static osc_bundle_element_size_t ValidateSize( osc_bundle_element_size_t size )
+    {
+        // sanity check integer types declared in OscTypes.h 
+        // you'll need to fix OscTypes.h if any of these asserts fail
+        assert( sizeof(osc::int32) == 4 );
+        assert( sizeof(osc::uint32) == 4 );
+        assert( sizeof(osc::int64) == 8 );
+        assert( sizeof(osc::uint64) == 8 );
+
+        if( !IsValidElementSizeValue(size) )
+            throw MalformedPacketException( "invalid packet size" );
+
+        if( size == 0 )
+            throw MalformedPacketException( "zero length elements not permitted" );
+
+        if( !IsMultipleOf4(size) )
+            throw MalformedPacketException( "element size must be multiple of four" );
+
+        return size;
+    }
+};
+
+
+class ReceivedBundleElement{
+public:
+    ReceivedBundleElement( const char *sizePtr )
+        : sizePtr_( sizePtr ) {}
+
+    friend class ReceivedBundleElementIterator;
+
+    bool IsMessage() const { return !IsBundle(); }
+    bool IsBundle() const;
+
+    osc_bundle_element_size_t Size() const;
+    const char *Contents() const { return sizePtr_ + osc::OSC_SIZEOF_INT32; }
+
+private:
+    const char *sizePtr_;
+};
+
+
+class ReceivedBundleElementIterator{
+public:
+	ReceivedBundleElementIterator( const char *sizePtr )
+        : value_( sizePtr ) {}
+
+	ReceivedBundleElementIterator operator++()
+	{
+        Advance();
+        return *this;
+	}
+
+    ReceivedBundleElementIterator operator++(int)
+    {
+        ReceivedBundleElementIterator old( *this );
+        Advance();
+        return old;
+    }
+
+	const ReceivedBundleElement& operator*() const { return value_; }
+
+    const ReceivedBundleElement* operator->() const { return &value_; }
+
+	friend bool operator==(const ReceivedBundleElementIterator& lhs,
+            const ReceivedBundleElementIterator& rhs );
+
+private:
+	ReceivedBundleElement value_;
+
+	void Advance() { value_.sizePtr_ = value_.Contents() + value_.Size(); }
+
+    bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const
+    {
+        return value_.sizePtr_ == rhs.value_.sizePtr_;
+    }
+};
+
+inline bool operator==(const ReceivedBundleElementIterator& lhs,
+        const ReceivedBundleElementIterator& rhs )
+{	
+	return lhs.IsEqualTo( rhs );
+}
+
+inline bool operator!=(const ReceivedBundleElementIterator& lhs,
+        const ReceivedBundleElementIterator& rhs )
+{
+	return !( lhs == rhs );
+}
+
+
+class ReceivedMessageArgument{
+public:
+	ReceivedMessageArgument( const char *typeTagPtr, const char *argumentPtr )
+		: typeTagPtr_( typeTagPtr )
+		, argumentPtr_( argumentPtr ) {}
+
+    friend class ReceivedMessageArgumentIterator;
+    
+	char TypeTag() const { return *typeTagPtr_; }
+
+    // the unchecked methods below don't check whether the argument actually
+    // is of the specified type. they should only be used if you've already
+    // checked the type tag or the associated IsType() method.
+
+    bool IsBool() const
+        { return *typeTagPtr_ == TRUE_TYPE_TAG || *typeTagPtr_ == FALSE_TYPE_TAG; }
+    bool AsBool() const;
+    bool AsBoolUnchecked() const;
+
+    bool IsNil() const { return *typeTagPtr_ == NIL_TYPE_TAG; }
+    bool IsInfinitum() const { return *typeTagPtr_ == INFINITUM_TYPE_TAG; }
+
+    bool IsInt32() const { return *typeTagPtr_ == INT32_TYPE_TAG; }
+    int32 AsInt32() const;
+    int32 AsInt32Unchecked() const;
+
+    bool IsFloat() const { return *typeTagPtr_ == FLOAT_TYPE_TAG; }
+    float AsFloat() const;
+    float AsFloatUnchecked() const;
+
+    bool IsChar() const { return *typeTagPtr_ == CHAR_TYPE_TAG; }
+    char AsChar() const;
+    char AsCharUnchecked() const;
+
+    bool IsRgbaColor() const { return *typeTagPtr_ == RGBA_COLOR_TYPE_TAG; }
+    uint32 AsRgbaColor() const;
+    uint32 AsRgbaColorUnchecked() const;
+
+    bool IsMidiMessage() const { return *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG; }
+    uint32 AsMidiMessage() const;
+    uint32 AsMidiMessageUnchecked() const;
+
+    bool IsInt64() const { return *typeTagPtr_ == INT64_TYPE_TAG; }
+    int64 AsInt64() const;
+    int64 AsInt64Unchecked() const;
+
+    bool IsTimeTag() const { return *typeTagPtr_ == TIME_TAG_TYPE_TAG; }
+    uint64 AsTimeTag() const;
+    uint64 AsTimeTagUnchecked() const;
+
+    bool IsDouble() const { return *typeTagPtr_ == DOUBLE_TYPE_TAG; }
+    double AsDouble() const;
+    double AsDoubleUnchecked() const;
+
+    bool IsString() const { return *typeTagPtr_ == STRING_TYPE_TAG; }
+    const char* AsString() const;
+    const char* AsStringUnchecked() const { return argumentPtr_; }
+
+    bool IsSymbol() const { return *typeTagPtr_ == SYMBOL_TYPE_TAG; }
+    const char* AsSymbol() const;
+    const char* AsSymbolUnchecked() const { return argumentPtr_; }
+
+    bool IsBlob() const { return *typeTagPtr_ == BLOB_TYPE_TAG; }
+    void AsBlob( const void*& data, osc_bundle_element_size_t& size ) const;
+    void AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const;
+    
+    bool IsArrayBegin() const { return *typeTagPtr_ == ARRAY_BEGIN_TYPE_TAG; }
+    bool IsArrayEnd() const { return *typeTagPtr_ == ARRAY_END_TYPE_TAG; }
+    // Calculate the number of top-level items in the array. Nested arrays count as one item.
+    // Only valid at array start. Will throw an exception if IsArrayStart() == false.
+    std::size_t ComputeArrayItemCount() const;
+
+private:
+	const char *typeTagPtr_;
+	const char *argumentPtr_;
+};
+
+
+class ReceivedMessageArgumentIterator{
+public:
+	ReceivedMessageArgumentIterator( const char *typeTags, const char *arguments )
+        : value_( typeTags, arguments ) {}
+
+	ReceivedMessageArgumentIterator operator++()
+	{
+        Advance();
+        return *this;
+	}
+
+    ReceivedMessageArgumentIterator operator++(int)
+    {
+        ReceivedMessageArgumentIterator old( *this );
+        Advance();
+        return old;
+    }
+
+	const ReceivedMessageArgument& operator*() const { return value_; }
+
+    const ReceivedMessageArgument* operator->() const { return &value_; }
+
+	friend bool operator==(const ReceivedMessageArgumentIterator& lhs,
+            const ReceivedMessageArgumentIterator& rhs );
+
+private:
+	ReceivedMessageArgument value_;
+
+	void Advance();
+
+    bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const
+    {
+        return value_.typeTagPtr_ == rhs.value_.typeTagPtr_;
+    }
+};
+
+inline bool operator==(const ReceivedMessageArgumentIterator& lhs,
+        const ReceivedMessageArgumentIterator& rhs )
+{	
+	return lhs.IsEqualTo( rhs );
+}
+
+inline bool operator!=(const ReceivedMessageArgumentIterator& lhs,
+        const ReceivedMessageArgumentIterator& rhs )
+{	
+	return !( lhs == rhs );
+}
+
+
+class ReceivedMessageArgumentStream{
+    friend class ReceivedMessage;
+    ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin,
+            const ReceivedMessageArgumentIterator& end )
+        : p_( begin )
+        , end_( end ) {}
+
+    ReceivedMessageArgumentIterator p_, end_;
+    
+public:
+
+    // end of stream
+    bool Eos() const { return p_ == end_; }
+
+    ReceivedMessageArgumentStream& operator>>( bool& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsBool();
+        return *this;
+    }
+
+    // not sure if it would be useful to stream Nil and Infinitum
+    // for now it's not possible
+    // same goes for array boundaries
+
+    ReceivedMessageArgumentStream& operator>>( int32& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsInt32();
+        return *this;
+    }     
+
+    ReceivedMessageArgumentStream& operator>>( float& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsFloat();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( char& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsChar();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs.value = (*p_++).AsRgbaColor();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs.value = (*p_++).AsMidiMessage();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( int64& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsInt64();
+        return *this;
+    }
+    
+    ReceivedMessageArgumentStream& operator>>( TimeTag& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs.value = (*p_++).AsTimeTag();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( double& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsDouble();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( Blob& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        (*p_++).AsBlob( rhs.data, rhs.size );
+        return *this;
+    }
+    
+    ReceivedMessageArgumentStream& operator>>( const char*& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs = (*p_++).AsString();
+        return *this;
+    }
+    
+    ReceivedMessageArgumentStream& operator>>( Symbol& rhs )
+    {
+        if( Eos() )
+            throw MissingArgumentException();
+
+        rhs.value = (*p_++).AsSymbol();
+        return *this;
+    }
+
+    ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs )
+    {
+        (void) rhs; // suppress unused parameter warning
+
+        if( !Eos() )
+            throw ExcessArgumentException();
+
+        return *this;
+    }
+};
+
+
+class ReceivedMessage{
+    void Init( const char *bundle, osc_bundle_element_size_t size );
+public:
+    explicit ReceivedMessage( const ReceivedPacket& packet );
+    explicit ReceivedMessage( const ReceivedBundleElement& bundleElement );
+
+	const char *AddressPattern() const { return addressPattern_; }
+
+	// Support for non-standard SuperCollider integer address patterns:
+	bool AddressPatternIsUInt32() const;
+	uint32 AddressPatternAsUInt32() const;
+
+	uint32 ArgumentCount() const { return static_cast<uint32>(typeTagsEnd_ - typeTagsBegin_); }
+
+    const char *TypeTags() const { return typeTagsBegin_; }
+
+
+    typedef ReceivedMessageArgumentIterator const_iterator;
+    
+	ReceivedMessageArgumentIterator ArgumentsBegin() const
+    {
+        return ReceivedMessageArgumentIterator( typeTagsBegin_, arguments_ );
+    }
+     
+	ReceivedMessageArgumentIterator ArgumentsEnd() const
+    {
+        return ReceivedMessageArgumentIterator( typeTagsEnd_, 0 );
+    }
+
+    ReceivedMessageArgumentStream ArgumentStream() const
+    {
+        return ReceivedMessageArgumentStream( ArgumentsBegin(), ArgumentsEnd() );
+    }
+
+private:
+	const char *addressPattern_;
+	const char *typeTagsBegin_;
+	const char *typeTagsEnd_;
+    const char *arguments_;
+};
+
+
+class ReceivedBundle{
+    void Init( const char *message, osc_bundle_element_size_t size );
+public:
+    explicit ReceivedBundle( const ReceivedPacket& packet );
+    explicit ReceivedBundle( const ReceivedBundleElement& bundleElement );
+
+    uint64 TimeTag() const;
+
+    uint32 ElementCount() const { return elementCount_; }
+
+    typedef ReceivedBundleElementIterator const_iterator;
+    
+	ReceivedBundleElementIterator ElementsBegin() const
+    {
+        return ReceivedBundleElementIterator( timeTag_ + 8 );
+    }
+     
+	ReceivedBundleElementIterator ElementsEnd() const
+    {
+        return ReceivedBundleElementIterator( end_ );
+    }
+
+private:
+    const char *timeTag_;
+    const char *end_;
+    uint32 elementCount_;
+};
+
+
+} // namespace osc
+
+
+#endif /* INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H */
diff --git a/src/osc/oscPack/osc/OscTypes.cpp b/src/osc/oscPack/osc/OscTypes.cpp
new file mode 100644
index 0000000..51616d5
--- /dev/null
+++ b/src/osc/oscPack/osc/OscTypes.cpp
@@ -0,0 +1,52 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#include "OscTypes.h"
+
+namespace osc{
+
+BundleInitiator BeginBundleImmediate(1);
+BundleTerminator EndBundle;
+MessageTerminator EndMessage;
+NilType OscNil;
+#ifndef _OBJC_OBJC_H_
+NilType Nil; // Objective-C defines Nil. so our Nil is deprecated. use OscNil instead
+#endif
+InfinitumType Infinitum;
+ArrayInitiator BeginArray;
+ArrayTerminator EndArray;
+
+} // namespace osc
diff --git a/src/osc/oscPack/osc/OscTypes.h b/src/osc/oscPack/osc/OscTypes.h
new file mode 100644
index 0000000..005524f
--- /dev/null
+++ b/src/osc/oscPack/osc/OscTypes.h
@@ -0,0 +1,240 @@
+/*
+	oscpack -- Open Sound Control (OSC) packet manipulation library
+    http://www.rossbencina.com/code/oscpack
+
+    Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
+
+	Permission is hereby granted, free of charge, to any person obtaining
+	a copy of this software and associated documentation files
+	(the "Software"), to deal in the Software without restriction,
+	including without limitation the rights to use, copy, modify, merge,
+	publish, distribute, sublicense, and/or sell copies of the Software,
+	and to permit persons to whom the Software is furnished to do so,
+	subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be
+	included in all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+	The text above constitutes the entire oscpack license; however, 
+	the oscpack developer(s) also make the following non-binding requests:
+
+	Any person wishing to distribute modifications to the Software is
+	requested to send the modifications to the original developer so that
+	they can be incorporated into the canonical version. It is also 
+	requested that these non-binding requests be included whenever the
+	above license is reproduced.
+*/
+#ifndef INCLUDED_OSCPACK_OSCTYPES_H
+#define INCLUDED_OSCPACK_OSCTYPES_H
+
+
+namespace osc{
+
+// basic types
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+
+typedef __int64 int64;
+typedef unsigned __int64 uint64;
+
+#elif defined(__x86_64__) || defined(_M_X64)
+
+typedef long int64;
+typedef unsigned long uint64;
+
+#else
+
+typedef long long int64;
+typedef unsigned long long uint64;
+
+#endif
+
+
+
+#if defined(__x86_64__) || defined(_M_X64)
+
+typedef signed int int32;
+typedef unsigned int uint32;
+
+#else
+
+typedef signed long int32;
+typedef unsigned long uint32;
+
+#endif
+
+
+enum ValueTypeSizes{
+    OSC_SIZEOF_INT32 = 4,
+    OSC_SIZEOF_UINT32 = 4,
+    OSC_SIZEOF_INT64 = 8,
+    OSC_SIZEOF_UINT64 = 8,
+};
+
+
+// osc_bundle_element_size_t is used for the size of bundle elements and blobs
+// the OSC spec specifies these as int32 (signed) but we ensure that they 
+// are always positive since negative field sizes make no sense.
+
+typedef int32 osc_bundle_element_size_t;
+
+enum {
+    OSC_INT32_MAX = 0x7FFFFFFF,
+
+    // Element sizes are specified to be int32, and are always rounded up to nearest 
+    // multiple of 4. Therefore their values can't be greater than 0x7FFFFFFC.
+    OSC_BUNDLE_ELEMENT_SIZE_MAX = 0x7FFFFFFC
+};
+
+
+inline bool IsValidElementSizeValue( osc_bundle_element_size_t x )
+{
+    // sizes may not be negative or exceed OSC_BUNDLE_ELEMENT_SIZE_MAX
+    return x >= 0 && x <= OSC_BUNDLE_ELEMENT_SIZE_MAX; 
+}
+
+
+inline bool IsMultipleOf4( osc_bundle_element_size_t x )
+{
+    return (x & ((osc_bundle_element_size_t)0x03)) == 0;
+}
+
+
+enum TypeTagValues {
+    TRUE_TYPE_TAG = 'T',
+    FALSE_TYPE_TAG = 'F',
+    NIL_TYPE_TAG = 'N',
+    INFINITUM_TYPE_TAG = 'I',
+    INT32_TYPE_TAG = 'i',
+    FLOAT_TYPE_TAG = 'f',
+    CHAR_TYPE_TAG = 'c',
+    RGBA_COLOR_TYPE_TAG = 'r',
+    MIDI_MESSAGE_TYPE_TAG = 'm',
+    INT64_TYPE_TAG = 'h',
+    TIME_TAG_TYPE_TAG = 't',
+    DOUBLE_TYPE_TAG = 'd',
+    STRING_TYPE_TAG = 's',
+    SYMBOL_TYPE_TAG = 'S',
+    BLOB_TYPE_TAG = 'b',
+    ARRAY_BEGIN_TYPE_TAG = '[',
+    ARRAY_END_TYPE_TAG = ']'
+};
+
+
+
+// i/o manipulators used for streaming interfaces
+
+struct BundleInitiator{
+    explicit BundleInitiator( uint64 timeTag_ ) : timeTag( timeTag_ ) {}
+    uint64 timeTag;
+};
+
+extern BundleInitiator BeginBundleImmediate;
+
+inline BundleInitiator BeginBundle( uint64 timeTag=1 )
+{
+    return BundleInitiator(timeTag);
+}
+
+
+struct BundleTerminator{
+};
+
+extern BundleTerminator EndBundle;
+
+struct BeginMessage{
+    explicit BeginMessage( const char *addressPattern_ ) : addressPattern( addressPattern_ ) {}
+    const char *addressPattern;
+};
+
+struct MessageTerminator{
+};
+
+extern MessageTerminator EndMessage;
+
+
+// osc specific types. they are defined as structs so they can be used
+// as separately identifiable types with the streaming operators.
+
+struct NilType{
+};
+
+extern NilType OscNil;
+
+#ifndef _OBJC_OBJC_H_
+extern NilType Nil; // Objective-C defines Nil. so our Nil is deprecated. use OscNil instead
+#endif
+
+struct InfinitumType{
+};
+
+extern InfinitumType Infinitum;
+
+struct RgbaColor{
+    RgbaColor() {}
+    explicit RgbaColor( uint32 value_ ) : value( value_ ) {}
+    uint32 value;
+
+    operator uint32() const { return value; }
+};
+
+
+struct MidiMessage{
+    MidiMessage() {}
+    explicit MidiMessage( uint32 value_ ) : value( value_ ) {}
+    uint32 value;
+
+    operator uint32() const { return value; }
+};
+
+
+struct TimeTag{
+    TimeTag() {}
+    explicit TimeTag( uint64 value_ ) : value( value_ ) {}
+    uint64 value;
+
+    operator uint64() const { return value; }
+};
+
+
+struct Symbol{
+    Symbol() {}
+    explicit Symbol( const char* value_ ) : value( value_ ) {}
+    const char* value;
+
+    operator const char *() const { return value; }
+};
+
+
+struct Blob{
+    Blob() {}
+    explicit Blob( const void* data_, osc_bundle_element_size_t size_ )
+            : data( data_ ), size( size_ ) {}
+    const void* data;
+    osc_bundle_element_size_t size;
+};
+
+struct ArrayInitiator{
+};
+
+extern ArrayInitiator BeginArray;
+
+struct ArrayTerminator{
+};
+
+extern ArrayTerminator EndArray;
+
+} // namespace osc
+
+
+#endif /* INCLUDED_OSCPACK_OSCTYPES_H */
diff --git a/src/tags b/src/tags
new file mode 100644
index 0000000..1d02e6b
--- /dev/null
+++ b/src/tags
@@ -0,0 +1,2475 @@
+!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;" to lines/
+!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/
+!_TAG_PROGRAM_AUTHOR	Darren Hiebert	/dhiebert@users.sourceforge.net/
+!_TAG_PROGRAM_NAME	Exuberant Ctags	//
+!_TAG_PROGRAM_URL	http://ctags.sourceforge.net	/official site/
+!_TAG_PROGRAM_VERSION	5.9~svn20110310	//
+ACCESSIBILITY	modules/Attribute.hpp	/^        enum ACCESSIBILITY {HIDDEN, OUTPUT, LOCAL, GLOBAL};$/;"	g	class:Attribute
+ACTION_ATTRIBUTE	modules/Attribute.hpp	/^                   ACTION_ATTRIBUTE, $/;"	e	enum:Attribute::TYPE
+ACTION_FLOAT_ATTRIBUTE	modules/Attribute.hpp	/^                   ACTION_FLOAT_ATTRIBUTE,$/;"	e	enum:Attribute::TYPE
+ACTION_INT_ATTRIBUTE	modules/Attribute.hpp	/^                   ACTION_INT_ATTRIBUTE,$/;"	e	enum:Attribute::TYPE
+ACTION_STRING_ATTRIBUTE	modules/Attribute.hpp	/^                   ACTION_STRING_ATTRIBUTE,$/;"	e	enum:Attribute::TYPE
+ADDRESS_AND_PORT_STRING_LENGTH	osc/oscPack/ip/IpEndpointName.h	/^	enum { ADDRESS_AND_PORT_STRING_LENGTH=23};$/;"	e	enum:IpEndpointName::__anon4
+ADDRESS_STRING_LENGTH	osc/oscPack/ip/IpEndpointName.h	/^	enum { ADDRESS_STRING_LENGTH=17 };$/;"	e	enum:IpEndpointName::__anon3
+AI_CONFIG_PP_SBP_REMOVE	modules/ModelModule.cpp	23;"	d	file:
+ANY_ADDRESS	osc/oscPack/ip/IpEndpointName.h	/^    static const unsigned long ANY_ADDRESS = 0xFFFFFFFF;$/;"	m	class:IpEndpointName
+ANY_PORT	osc/oscPack/ip/IpEndpointName.h	/^    static const int ANY_PORT = -1;$/;"	m	class:IpEndpointName
+ARRAY_BEGIN_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    ARRAY_BEGIN_TYPE_TAG = '[',$/;"	e	enum:osc::TypeTagValues
+ARRAY_END_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    ARRAY_END_TYPE_TAG = ']'$/;"	e	enum:osc::TypeTagValues
+ActionCallback	modules/Attribute.hpp	/^        typedef void (ActionCallback) (Module*);$/;"	t	class:Attribute
+AddressAndPortAsString	osc/oscPack/ip/IpEndpointName.cpp	/^void IpEndpointName::AddressAndPortAsString( char *s ) const$/;"	f	class:IpEndpointName
+AddressAndPortAsString	osc/oscPack/ip/IpEndpointName.h	/^	void AddressAndPortAsString( char *s ) const;$/;"	p	class:IpEndpointName
+AddressAsString	osc/oscPack/ip/IpEndpointName.cpp	/^void IpEndpointName::AddressAsString( char *s ) const$/;"	f	class:IpEndpointName
+AddressAsString	osc/oscPack/ip/IpEndpointName.h	/^	void AddressAsString( char *s ) const;$/;"	p	class:IpEndpointName
+AddressPattern	osc/oscPack/osc/OscReceivedElements.h	/^	const char *AddressPattern() const { return addressPattern_; }$/;"	f	class:osc::ReceivedMessage
+AddressPatternAsUInt32	osc/oscPack/osc/OscReceivedElements.cpp	/^uint32 ReceivedMessage::AddressPatternAsUInt32() const$/;"	f	class:osc::ReceivedMessage
+AddressPatternAsUInt32	osc/oscPack/osc/OscReceivedElements.h	/^	uint32 AddressPatternAsUInt32() const;$/;"	p	class:osc::ReceivedMessage
+AddressPatternIsUInt32	osc/oscPack/osc/OscReceivedElements.cpp	/^bool ReceivedMessage::AddressPatternIsUInt32() const$/;"	f	class:osc::ReceivedMessage
+AddressPatternIsUInt32	osc/oscPack/osc/OscReceivedElements.h	/^	bool AddressPatternIsUInt32() const;$/;"	p	class:osc::ReceivedMessage
+Advance	osc/oscPack/osc/OscReceivedElements.cpp	/^void ReceivedMessageArgumentIterator::Advance()$/;"	f	class:osc::ReceivedMessageArgumentIterator
+Advance	osc/oscPack/osc/OscReceivedElements.h	/^	void Advance() { value_.sizePtr_ = value_.Contents() + value_.Size(); }$/;"	f	class:osc::ReceivedBundleElementIterator
+Advance	osc/oscPack/osc/OscReceivedElements.h	/^	void Advance();$/;"	p	class:osc::ReceivedMessageArgumentIterator
+ArgumentCount	osc/oscPack/osc/OscReceivedElements.h	/^	uint32 ArgumentCount() const { return static_cast<uint32>(typeTagsEnd_ - typeTagsBegin_); }$/;"	f	class:osc::ReceivedMessage
+ArgumentStream	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream ArgumentStream() const$/;"	f	class:osc::ReceivedMessage
+ArgumentsBegin	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedMessageArgumentIterator ArgumentsBegin() const$/;"	f	class:osc::ReceivedMessage
+ArgumentsEnd	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedMessageArgumentIterator ArgumentsEnd() const$/;"	f	class:osc::ReceivedMessage
+ArrayInitiator	osc/oscPack/osc/OscTypes.h	/^struct ArrayInitiator{$/;"	s	namespace:osc
+ArrayTerminator	osc/oscPack/osc/OscTypes.h	/^struct ArrayTerminator{$/;"	s	namespace:osc
+ArucoTracker	modules/DepthCamModule.hpp	/^class ArucoTracker : public Tracker {$/;"	c
+AsBlob	osc/oscPack/osc/OscReceivedElements.cpp	/^void ReceivedMessageArgument::AsBlob( const void*& data, osc_bundle_element_size_t& size ) const$/;"	f	class:osc::ReceivedMessageArgument
+AsBlob	osc/oscPack/osc/OscReceivedElements.h	/^    void AsBlob( const void*& data, osc_bundle_element_size_t& size ) const;$/;"	p	class:osc::ReceivedMessageArgument
+AsBlobUnchecked	osc/oscPack/osc/OscReceivedElements.cpp	/^void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const$/;"	f	class:osc::ReceivedMessageArgument
+AsBlobUnchecked	osc/oscPack/osc/OscReceivedElements.h	/^    void AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const;$/;"	p	class:osc::ReceivedMessageArgument
+AsBool	osc/oscPack/osc/OscReceivedElements.cpp	/^bool ReceivedMessageArgument::AsBool() const$/;"	f	class:osc::ReceivedMessageArgument
+AsBool	osc/oscPack/osc/OscReceivedElements.h	/^    bool AsBool() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsBoolUnchecked	osc/oscPack/osc/OscReceivedElements.cpp	/^bool ReceivedMessageArgument::AsBoolUnchecked() const$/;"	f	class:osc::ReceivedMessageArgument
+AsBoolUnchecked	osc/oscPack/osc/OscReceivedElements.h	/^    bool AsBoolUnchecked() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsChar	osc/oscPack/osc/OscReceivedElements.cpp	/^char ReceivedMessageArgument::AsChar() const$/;"	f	class:osc::ReceivedMessageArgument
+AsChar	osc/oscPack/osc/OscReceivedElements.h	/^    char AsChar() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsCharUnchecked	osc/oscPack/osc/OscReceivedElements.cpp	/^char ReceivedMessageArgument::AsCharUnchecked() const$/;"	f	class:osc::ReceivedMessageArgument
+AsCharUnchecked	osc/oscPack/osc/OscReceivedElements.h	/^    char AsCharUnchecked() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsDouble	osc/oscPack/osc/OscReceivedElements.cpp	/^double ReceivedMessageArgument::AsDouble() const$/;"	f	class:osc::ReceivedMessageArgument
+AsDouble	osc/oscPack/osc/OscReceivedElements.h	/^    double AsDouble() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsDoubleUnchecked	osc/oscPack/osc/OscReceivedElements.cpp	/^double ReceivedMessageArgument::AsDoubleUnchecked() const$/;"	f	class:osc::ReceivedMessageArgument
+AsDoubleUnchecked	osc/oscPack/osc/OscReceivedElements.h	/^    double AsDoubleUnchecked() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsFloat	osc/oscPack/osc/OscReceivedElements.cpp	/^float ReceivedMessageArgument::AsFloat() const$/;"	f	class:osc::ReceivedMessageArgument
+AsFloat	osc/oscPack/osc/OscReceivedElements.h	/^    float AsFloat() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsFloatUnchecked	osc/oscPack/osc/OscReceivedElements.cpp	/^float ReceivedMessageArgument::AsFloatUnchecked() const$/;"	f	class:osc::ReceivedMessageArgument
+AsFloatUnchecked	osc/oscPack/osc/OscReceivedElements.h	/^    float AsFloatUnchecked() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsInt32	osc/oscPack/osc/OscReceivedElements.cpp	/^int32 ReceivedMessageArgument::AsInt32() const$/;"	f	class:osc::ReceivedMessageArgument
+AsInt32	osc/oscPack/osc/OscReceivedElements.h	/^    int32 AsInt32() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsInt32Unchecked	osc/oscPack/osc/OscReceivedElements.cpp	/^int32 ReceivedMessageArgument::AsInt32Unchecked() const$/;"	f	class:osc::ReceivedMessageArgument
+AsInt32Unchecked	osc/oscPack/osc/OscReceivedElements.h	/^    int32 AsInt32Unchecked() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsInt64	osc/oscPack/osc/OscReceivedElements.cpp	/^int64 ReceivedMessageArgument::AsInt64() const$/;"	f	class:osc::ReceivedMessageArgument
+AsInt64	osc/oscPack/osc/OscReceivedElements.h	/^    int64 AsInt64() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsInt64Unchecked	osc/oscPack/osc/OscReceivedElements.cpp	/^int64 ReceivedMessageArgument::AsInt64Unchecked() const$/;"	f	class:osc::ReceivedMessageArgument
+AsInt64Unchecked	osc/oscPack/osc/OscReceivedElements.h	/^    int64 AsInt64Unchecked() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsMidiMessage	osc/oscPack/osc/OscReceivedElements.cpp	/^uint32 ReceivedMessageArgument::AsMidiMessage() const$/;"	f	class:osc::ReceivedMessageArgument
+AsMidiMessage	osc/oscPack/osc/OscReceivedElements.h	/^    uint32 AsMidiMessage() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsMidiMessageUnchecked	osc/oscPack/osc/OscReceivedElements.cpp	/^uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const$/;"	f	class:osc::ReceivedMessageArgument
+AsMidiMessageUnchecked	osc/oscPack/osc/OscReceivedElements.h	/^    uint32 AsMidiMessageUnchecked() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsRgbaColor	osc/oscPack/osc/OscReceivedElements.cpp	/^uint32 ReceivedMessageArgument::AsRgbaColor() const$/;"	f	class:osc::ReceivedMessageArgument
+AsRgbaColor	osc/oscPack/osc/OscReceivedElements.h	/^    uint32 AsRgbaColor() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsRgbaColorUnchecked	osc/oscPack/osc/OscReceivedElements.cpp	/^uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const$/;"	f	class:osc::ReceivedMessageArgument
+AsRgbaColorUnchecked	osc/oscPack/osc/OscReceivedElements.h	/^    uint32 AsRgbaColorUnchecked() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsString	osc/oscPack/osc/OscReceivedElements.cpp	/^const char* ReceivedMessageArgument::AsString() const$/;"	f	class:osc::ReceivedMessageArgument
+AsString	osc/oscPack/osc/OscReceivedElements.h	/^    const char* AsString() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsStringUnchecked	osc/oscPack/osc/OscReceivedElements.h	/^    const char* AsStringUnchecked() const { return argumentPtr_; }$/;"	f	class:osc::ReceivedMessageArgument
+AsSymbol	osc/oscPack/osc/OscReceivedElements.cpp	/^const char* ReceivedMessageArgument::AsSymbol() const$/;"	f	class:osc::ReceivedMessageArgument
+AsSymbol	osc/oscPack/osc/OscReceivedElements.h	/^    const char* AsSymbol() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsSymbolUnchecked	osc/oscPack/osc/OscReceivedElements.h	/^    const char* AsSymbolUnchecked() const { return argumentPtr_; }$/;"	f	class:osc::ReceivedMessageArgument
+AsTimeTag	osc/oscPack/osc/OscReceivedElements.cpp	/^uint64 ReceivedMessageArgument::AsTimeTag() const$/;"	f	class:osc::ReceivedMessageArgument
+AsTimeTag	osc/oscPack/osc/OscReceivedElements.h	/^    uint64 AsTimeTag() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsTimeTagUnchecked	osc/oscPack/osc/OscReceivedElements.cpp	/^uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const$/;"	f	class:osc::ReceivedMessageArgument
+AsTimeTagUnchecked	osc/oscPack/osc/OscReceivedElements.h	/^    uint64 AsTimeTagUnchecked() const;$/;"	p	class:osc::ReceivedMessageArgument
+AsynchronousBreak	osc/oscPack/ip/UdpSocket.h	/^    void AsynchronousBreak() { mux_.AsynchronousBreak(); }$/;"	f	class:UdpListeningReceiveSocket
+AsynchronousBreak	osc/oscPack/ip/UdpSocket.h	/^    void AsynchronousBreak(); \/\/ call this from another thread or signal handler to exit the Run() state$/;"	p	class:SocketReceiveMultiplexer
+AsynchronousBreak	osc/oscPack/ip/posix/UdpSocket.cpp	/^    void AsynchronousBreak()$/;"	f	class:SocketReceiveMultiplexer::Implementation
+AsynchronousBreak	osc/oscPack/ip/posix/UdpSocket.cpp	/^void SocketReceiveMultiplexer::AsynchronousBreak()$/;"	f	class:SocketReceiveMultiplexer
+AsynchronousBreak	osc/oscPack/ip/win32/UdpSocket.cpp	/^    void AsynchronousBreak()$/;"	f	class:SocketReceiveMultiplexer::Implementation
+AsynchronousBreak	osc/oscPack/ip/win32/UdpSocket.cpp	/^void SocketReceiveMultiplexer::AsynchronousBreak()$/;"	f	class:SocketReceiveMultiplexer
+AttachPeriodicTimerListener	osc/oscPack/ip/UdpSocket.h	/^	void AttachPeriodicTimerListener($/;"	p	class:SocketReceiveMultiplexer
+AttachPeriodicTimerListener	osc/oscPack/ip/UdpSocket.h	/^    void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener );$/;"	p	class:SocketReceiveMultiplexer
+AttachPeriodicTimerListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^	void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer::Implementation
+AttachPeriodicTimerListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^    void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer::Implementation
+AttachPeriodicTimerListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer
+AttachPeriodicTimerListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer
+AttachPeriodicTimerListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^	void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer::Implementation
+AttachPeriodicTimerListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^    void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer::Implementation
+AttachPeriodicTimerListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer
+AttachPeriodicTimerListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer
+AttachSocketListener	osc/oscPack/ip/UdpSocket.h	/^    void AttachSocketListener( UdpSocket *socket, PacketListener *listener );$/;"	p	class:SocketReceiveMultiplexer
+AttachSocketListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^    void AttachSocketListener( UdpSocket *socket, PacketListener *listener )$/;"	f	class:SocketReceiveMultiplexer::Implementation
+AttachSocketListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )$/;"	f	class:SocketReceiveMultiplexer
+AttachSocketListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^    void AttachSocketListener( UdpSocket *socket, PacketListener *listener )$/;"	f	class:SocketReceiveMultiplexer::Implementation
+AttachSocketListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )$/;"	f	class:SocketReceiveMultiplexer
+AttachedTimerListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^	AttachedTimerListener( int id, int p, TimerListener *tl )$/;"	f	struct:AttachedTimerListener
+AttachedTimerListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^struct AttachedTimerListener{$/;"	s	file:
+AttachedTimerListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^	AttachedTimerListener( int id, int p, TimerListener *tl )$/;"	f	struct:AttachedTimerListener
+AttachedTimerListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^struct AttachedTimerListener{$/;"	s	file:
+Attribute	modules/Attribute.hpp	/^        Attribute(const std::string& name, const TYPE& type, $/;"	f	class:Attribute
+Attribute	modules/Attribute.hpp	/^class Attribute {$/;"	c
+AttributeWidget	gui/AttributeWidget.cpp	/^AttributeWidget::AttributeWidget(int x, int y, $/;"	f	class:AttributeWidget
+AttributeWidget	gui/AttributeWidget.hpp	/^        AttributeWidget(int x, int y, int w, int h, Attribute* attribute);$/;"	p	class:AttributeWidget
+AttributeWidget	gui/AttributeWidget.hpp	/^class AttributeWidget : public Fl_Group {$/;"	c
+AttributeWidget_h	gui/AttributeWidget.hpp	24;"	d
+Attribute_h	modules/Attribute.hpp	25;"	d
+BACKGROUND	Reveal.hpp	/^            CAMFILTER, CAMCONTOURTHRESH, CAMMARKERS, MARKTEX, BACKGROUND,$/;"	e	enum:Reveal::REVIL_UNIFORM
+BBOXLOCALSIZE	Reveal.hpp	/^            BBOXMIN, BBOXSIZE, BBOXROT, BBOXLOCALSIZE, $/;"	e	enum:Reveal::REVIL_UNIFORM
+BBOXMIN	Reveal.hpp	/^            BBOXMIN, BBOXSIZE, BBOXROT, BBOXLOCALSIZE, $/;"	e	enum:Reveal::REVIL_UNIFORM
+BBOXROT	Reveal.hpp	/^            BBOXMIN, BBOXSIZE, BBOXROT, BBOXLOCALSIZE, $/;"	e	enum:Reveal::REVIL_UNIFORM
+BBOXSIZE	Reveal.hpp	/^            BBOXMIN, BBOXSIZE, BBOXROT, BBOXLOCALSIZE, $/;"	e	enum:Reveal::REVIL_UNIFORM
+BLOB_ATTRIBUTE	modules/Attribute.hpp	/^                   BLOB_ATTRIBUTE};$/;"	e	enum:Attribute::TYPE
+BLOB_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    BLOB_TYPE_TAG = 'b',$/;"	e	enum:osc::TypeTagValues
+BOOL_ATTRIBUTE	modules/Attribute.hpp	/^                   BOOL_ATTRIBUTE, $/;"	e	enum:Attribute::TYPE
+BeginArray	osc/oscPack/osc/OscTypes.cpp	/^ArrayInitiator BeginArray;$/;"	m	namespace:osc	file:
+BeginBundle	osc/oscPack/osc/OscTypes.h	/^inline BundleInitiator BeginBundle( uint64 timeTag=1 )$/;"	f	namespace:osc
+BeginElement	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^char *OutboundPacketStream::BeginElement( char *beginPtr )$/;"	f	class:osc::OutboundPacketStream
+BeginElement	osc/oscPack/osc/OscOutboundPacketStream.h	/^    char *BeginElement( char *beginPtr );$/;"	p	class:osc::OutboundPacketStream
+BeginMessage	osc/oscPack/osc/OscTypes.h	/^    explicit BeginMessage( const char *addressPattern_ ) : addressPattern( addressPattern_ ) {}$/;"	f	struct:osc::BeginMessage
+BeginMessage	osc/oscPack/osc/OscTypes.h	/^struct BeginMessage{$/;"	s	namespace:osc
+Bind	osc/oscPack/ip/UdpSocket.h	/^	void Bind( const IpEndpointName& localEndpoint );$/;"	p	class:UdpSocket
+Bind	osc/oscPack/ip/posix/UdpSocket.cpp	/^	void Bind( const IpEndpointName& localEndpoint )$/;"	f	class:UdpSocket::Implementation
+Bind	osc/oscPack/ip/posix/UdpSocket.cpp	/^void UdpSocket::Bind( const IpEndpointName& localEndpoint )$/;"	f	class:UdpSocket
+Bind	osc/oscPack/ip/win32/UdpSocket.cpp	/^	void Bind( const IpEndpointName& localEndpoint )$/;"	f	class:UdpSocket::Implementation
+Bind	osc/oscPack/ip/win32/UdpSocket.cpp	/^void UdpSocket::Bind( const IpEndpointName& localEndpoint )$/;"	f	class:UdpSocket
+Blob	osc/oscPack/osc/OscTypes.h	/^    Blob() {}$/;"	f	struct:osc::Blob
+Blob	osc/oscPack/osc/OscTypes.h	/^    explicit Blob( const void* data_, osc_bundle_element_size_t size_ )$/;"	f	struct:osc::Blob
+Blob	osc/oscPack/osc/OscTypes.h	/^struct Blob{$/;"	s	namespace:osc
+BlobCallback	modules/Attribute.hpp	/^        typedef void (BlobCallback) (Module*, const std::string&, void*);$/;"	t	class:Attribute
+BoolCallback	modules/Attribute.hpp	/^        typedef void (BoolCallback) (Module*,const std::vector<bool>&);$/;"	t	class:Attribute
+BoxGeometry	geoms/BoxGeometry.cpp	/^BoxGeometry::BoxGeometry(): Geometry() {$/;"	f	class:BoxGeometry
+BoxGeometry	geoms/BoxGeometry.hpp	/^        BoxGeometry();$/;"	p	class:BoxGeometry
+BoxGeometry	geoms/BoxGeometry.hpp	/^class BoxGeometry : public Geometry {$/;"	c
+BoxGeometry_h	geoms/BoxGeometry.hpp	25;"	d
+Break	osc/oscPack/ip/UdpSocket.h	/^    void Break() { mux_.Break(); }$/;"	f	class:UdpListeningReceiveSocket
+Break	osc/oscPack/ip/UdpSocket.h	/^    void Break();    \/\/ call this from a listener to exit once the listener returns$/;"	p	class:SocketReceiveMultiplexer
+Break	osc/oscPack/ip/posix/UdpSocket.cpp	/^    void Break()$/;"	f	class:SocketReceiveMultiplexer::Implementation
+Break	osc/oscPack/ip/posix/UdpSocket.cpp	/^void SocketReceiveMultiplexer::Break()$/;"	f	class:SocketReceiveMultiplexer
+Break	osc/oscPack/ip/win32/UdpSocket.cpp	/^    void Break()$/;"	f	class:SocketReceiveMultiplexer::Implementation
+Break	osc/oscPack/ip/win32/UdpSocket.cpp	/^void SocketReceiveMultiplexer::Break()$/;"	f	class:SocketReceiveMultiplexer
+BundleInitiator	osc/oscPack/osc/OscTypes.h	/^    explicit BundleInitiator( uint64 timeTag_ ) : timeTag( timeTag_ ) {}$/;"	f	struct:osc::BundleInitiator
+BundleInitiator	osc/oscPack/osc/OscTypes.h	/^struct BundleInitiator{$/;"	s	namespace:osc
+BundleNotInProgressException	osc/oscPack/osc/OscOutboundPacketStream.h	/^    BundleNotInProgressException($/;"	f	class:osc::BundleNotInProgressException
+BundleNotInProgressException	osc/oscPack/osc/OscOutboundPacketStream.h	/^class BundleNotInProgressException : public Exception{$/;"	c	namespace:osc
+BundleTerminator	osc/oscPack/osc/OscTypes.h	/^struct BundleTerminator{$/;"	s	namespace:osc
+CALIBPROG	Reveal.hpp	/^            PREVIEWPROG, SLICEPROG, SELECTPROG, RENDERPROG, CALIBPROG$/;"	e	enum:Reveal::REVIL_PROGRAM
+CAMCONTOURTHRESH	Reveal.hpp	/^            CAMFILTER, CAMCONTOURTHRESH, CAMMARKERS, MARKTEX, BACKGROUND,$/;"	e	enum:Reveal::REVIL_UNIFORM
+CAMFILTER	Reveal.hpp	/^            CAMFILTER, CAMCONTOURTHRESH, CAMMARKERS, MARKTEX, BACKGROUND,$/;"	e	enum:Reveal::REVIL_UNIFORM
+CAMMARKERS	Reveal.hpp	/^            CAMFILTER, CAMCONTOURTHRESH, CAMMARKERS, MARKTEX, BACKGROUND,$/;"	e	enum:Reveal::REVIL_UNIFORM
+CAMTEX1	Reveal.hpp	/^            CAMTEX1, CAMTEX2, CAMXRESO, CAMYRESO, CAMXZFACTOR, CAMYZFACTOR, $/;"	e	enum:Reveal::REVIL_UNIFORM
+CAMTEX2	Reveal.hpp	/^            CAMTEX1, CAMTEX2, CAMXRESO, CAMYRESO, CAMXZFACTOR, CAMYZFACTOR, $/;"	e	enum:Reveal::REVIL_UNIFORM
+CAMXRESO	Reveal.hpp	/^            CAMTEX1, CAMTEX2, CAMXRESO, CAMYRESO, CAMXZFACTOR, CAMYZFACTOR, $/;"	e	enum:Reveal::REVIL_UNIFORM
+CAMXZFACTOR	Reveal.hpp	/^            CAMTEX1, CAMTEX2, CAMXRESO, CAMYRESO, CAMXZFACTOR, CAMYZFACTOR, $/;"	e	enum:Reveal::REVIL_UNIFORM
+CAMYRESO	Reveal.hpp	/^            CAMTEX1, CAMTEX2, CAMXRESO, CAMYRESO, CAMXZFACTOR, CAMYZFACTOR, $/;"	e	enum:Reveal::REVIL_UNIFORM
+CAMYZFACTOR	Reveal.hpp	/^            CAMTEX1, CAMTEX2, CAMXRESO, CAMYRESO, CAMXZFACTOR, CAMYZFACTOR, $/;"	e	enum:Reveal::REVIL_UNIFORM
+CHAR_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    CHAR_TYPE_TAG = 'c',$/;"	e	enum:osc::TypeTagValues
+COORDSTEX	Reveal.hpp	/^            OUTPUTTEX, SLICETEX, SELECTTEX, INSIDETEX, SURFACETEX, COORDSTEX,$/;"	e	enum:Reveal::REVIL_UNIFORM
+CamGeometry	geoms/CamGeometry.cpp	/^CamGeometry::CamGeometry(const int& width, const int& height): Geometry() {$/;"	f	class:CamGeometry
+CamGeometry	geoms/CamGeometry.hpp	/^        CamGeometry(const int& width, const int& height);$/;"	p	class:CamGeometry
+CamGeometry	geoms/CamGeometry.hpp	/^class CamGeometry : public Geometry {$/;"	c
+CamGeometry_h	geoms/CamGeometry.hpp	25;"	d
+Capacity	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^std::size_t OutboundPacketStream::Capacity() const$/;"	f	class:osc::OutboundPacketStream
+Capacity	osc/oscPack/osc/OscOutboundPacketStream.h	/^    std::size_t Capacity() const;$/;"	p	class:osc::OutboundPacketStream
+CheckForAvailableArgumentSpace	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^void OutboundPacketStream::CheckForAvailableArgumentSpace( std::size_t argumentLength )$/;"	f	class:osc::OutboundPacketStream
+CheckForAvailableArgumentSpace	osc/oscPack/osc/OscOutboundPacketStream.h	/^    void CheckForAvailableArgumentSpace( std::size_t argumentLength );$/;"	p	class:osc::OutboundPacketStream
+CheckForAvailableBundleSpace	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^void OutboundPacketStream::CheckForAvailableBundleSpace()$/;"	f	class:osc::OutboundPacketStream
+CheckForAvailableBundleSpace	osc/oscPack/osc/OscOutboundPacketStream.h	/^    void CheckForAvailableBundleSpace();$/;"	p	class:osc::OutboundPacketStream
+CheckForAvailableMessageSpace	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern )$/;"	f	class:osc::OutboundPacketStream
+CheckForAvailableMessageSpace	osc/oscPack/osc/OscOutboundPacketStream.h	/^    void CheckForAvailableMessageSpace( const char *addressPattern );$/;"	p	class:osc::OutboundPacketStream
+Clear	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^void OutboundPacketStream::Clear()$/;"	f	class:osc::OutboundPacketStream
+Clear	osc/oscPack/osc/OscOutboundPacketStream.h	/^    void Clear();$/;"	p	class:osc::OutboundPacketStream
+CompareScheduledTimerCalls	osc/oscPack/ip/posix/UdpSocket.cpp	/^static bool CompareScheduledTimerCalls( $/;"	f	file:
+CompareScheduledTimerCalls	osc/oscPack/ip/win32/UdpSocket.cpp	/^static bool CompareScheduledTimerCalls( $/;"	f	file:
+ComputeArrayItemCount	osc/oscPack/osc/OscReceivedElements.cpp	/^std::size_t ReceivedMessageArgument::ComputeArrayItemCount() const$/;"	f	class:osc::ReceivedMessageArgument
+ComputeArrayItemCount	osc/oscPack/osc/OscReceivedElements.h	/^    std::size_t ComputeArrayItemCount() const;$/;"	p	class:osc::ReceivedMessageArgument
+ConeGeometry	geoms/ConeGeometry.cpp	/^ConeGeometry::ConeGeometry(): Geometry() {$/;"	f	class:ConeGeometry
+ConeGeometry	geoms/ConeGeometry.hpp	/^        ConeGeometry();$/;"	p	class:ConeGeometry
+ConeGeometry	geoms/ConeGeometry.hpp	/^class ConeGeometry : public Geometry {$/;"	c
+ConeGeometry_h	geoms/ConeGeometry.hpp	25;"	d
+Connect	osc/oscPack/ip/UdpSocket.h	/^	void Connect( const IpEndpointName& remoteEndpoint );	$/;"	p	class:UdpSocket
+Connect	osc/oscPack/ip/posix/UdpSocket.cpp	/^	void Connect( const IpEndpointName& remoteEndpoint )$/;"	f	class:UdpSocket::Implementation
+Connect	osc/oscPack/ip/posix/UdpSocket.cpp	/^void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )$/;"	f	class:UdpSocket
+Connect	osc/oscPack/ip/win32/UdpSocket.cpp	/^	void Connect( const IpEndpointName& remoteEndpoint )$/;"	f	class:UdpSocket::Implementation
+Connect	osc/oscPack/ip/win32/UdpSocket.cpp	/^void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )$/;"	f	class:UdpSocket
+Contents	osc/oscPack/osc/OscReceivedElements.h	/^    const char *Contents() const { return contents_; }$/;"	f	class:osc::ReceivedPacket
+Contents	osc/oscPack/osc/OscReceivedElements.h	/^    const char *Contents() const { return sizePtr_ + osc::OSC_SIZEOF_INT32; }$/;"	f	class:osc::ReceivedBundleElement
+ContextGeometry	geoms/Geometry.hpp	/^struct ContextGeometry {$/;"	s
+ContextHandler	modules/ContextHandler.hpp	/^class ContextHandler {$/;"	c
+ContextHandler_h	modules/ContextHandler.hpp	25;"	d
+CutWindow	modules/RevealedCutModule.cpp	/^CutWindow::CutWindow(CutWindowsManager* man, $/;"	f	class:CutWindow
+CutWindow	modules/RevealedCutModule.hpp	/^        CutWindow(CutWindowsManager* man, Display* disp, const Window& win);$/;"	p	class:CutWindow
+CutWindow	modules/RevealedCutModule.hpp	/^class CutWindow {$/;"	c
+CutWindowsManager	modules/RevealedCutModule.cpp	/^CutWindowsManager::CutWindowsManager() {$/;"	f	class:CutWindowsManager
+CutWindowsManager	modules/RevealedCutModule.hpp	/^        CutWindowsManager();$/;"	p	class:CutWindowsManager
+CutWindowsManager	modules/RevealedCutModule.hpp	/^class CutWindowsManager {$/;"	c
+DEPTHID	Reveal.hpp	/^            DEPTHTYPE, DEPTHID, OUTPUTCURS, $/;"	e	enum:Reveal::REVIL_UNIFORM
+DEPTHTYPE	Reveal.hpp	/^            DEPTHTYPE, DEPTHID, OUTPUTCURS, $/;"	e	enum:Reveal::REVIL_UNIFORM
+DOUBLE_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    DOUBLE_TYPE_TAG = 'd',$/;"	e	enum:osc::TypeTagValues
+Data	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^const char *OutboundPacketStream::Data() const$/;"	f	class:osc::OutboundPacketStream
+Data	osc/oscPack/osc/OscOutboundPacketStream.h	/^    const char *Data() const;$/;"	p	class:osc::OutboundPacketStream
+DepthCamModule	modules/DepthCamModule.cpp	/^DepthCamModule::DepthCamModule():   GroupModule(),$/;"	f	class:DepthCamModule
+DepthCamModule	modules/DepthCamModule.hpp	/^        DepthCamModule();$/;"	p	class:DepthCamModule
+DepthCamModule	modules/DepthCamModule.hpp	/^class DepthCamModule : public GroupModule, public DepthModule {$/;"	c
+DepthCamModule_h	modules/DepthCamModule.hpp	25;"	d
+DepthGroupModule	modules/DepthGroupModule.cpp	/^DepthGroupModule::DepthGroupModule(): GroupModule(), DepthModule() {$/;"	f	class:DepthGroupModule
+DepthGroupModule	modules/DepthGroupModule.hpp	/^        DepthGroupModule();$/;"	p	class:DepthGroupModule
+DepthGroupModule	modules/DepthGroupModule.hpp	/^class DepthGroupModule : public GroupModule, public DepthModule {$/;"	c
+DepthGroupModule_h	modules/DepthGroupModule.hpp	25;"	d
+DepthMeshModule	modules/DepthMeshModule.cpp	/^DepthMeshModule::DepthMeshModule(): DepthModule() {$/;"	f	class:DepthMeshModule
+DepthMeshModule	modules/DepthMeshModule.hpp	/^        DepthMeshModule();$/;"	p	class:DepthMeshModule
+DepthMeshModule	modules/DepthMeshModule.hpp	/^class DepthMeshModule : public DepthModule {$/;"	c
+DepthMeshModule_h	modules/DepthMeshModule.hpp	25;"	d
+DepthModule	modules/DepthModule.cpp	/^DepthModule::DepthModule(): GeomModule(), m_space(NULL) {}$/;"	f	class:DepthModule
+DepthModule	modules/DepthModule.hpp	/^        DepthModule();$/;"	p	class:DepthModule
+DepthModule	modules/DepthModule.hpp	/^class DepthModule : public virtual GeomModule {$/;"	c
+DepthModule_h	modules/DepthModule.hpp	25;"	d
+DepthShapeModule	modules/DepthShapeModule.cpp	/^DepthShapeModule::DepthShapeModule(): ShapeModule(), DepthModule() {$/;"	f	class:DepthShapeModule
+DepthShapeModule	modules/DepthShapeModule.hpp	/^        DepthShapeModule();$/;"	p	class:DepthShapeModule
+DepthShapeModule	modules/DepthShapeModule.hpp	/^class DepthShapeModule : public ShapeModule, public DepthModule {$/;"	c
+DepthShapeModule_h	modules/DepthShapeModule.hpp	25;"	d
+DetachPeriodicTimerListener	osc/oscPack/ip/UdpSocket.h	/^    void DetachPeriodicTimerListener( TimerListener *listener );  $/;"	p	class:SocketReceiveMultiplexer
+DetachPeriodicTimerListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^    void DetachPeriodicTimerListener( TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer::Implementation
+DetachPeriodicTimerListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer
+DetachPeriodicTimerListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^    void DetachPeriodicTimerListener( TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer::Implementation
+DetachPeriodicTimerListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )$/;"	f	class:SocketReceiveMultiplexer
+DetachSocketListener	osc/oscPack/ip/UdpSocket.h	/^    void DetachSocketListener( UdpSocket *socket, PacketListener *listener );$/;"	p	class:SocketReceiveMultiplexer
+DetachSocketListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^    void DetachSocketListener( UdpSocket *socket, PacketListener *listener )$/;"	f	class:SocketReceiveMultiplexer::Implementation
+DetachSocketListener	osc/oscPack/ip/posix/UdpSocket.cpp	/^void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )$/;"	f	class:SocketReceiveMultiplexer
+DetachSocketListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^    void DetachSocketListener( UdpSocket *socket, PacketListener *listener )$/;"	f	class:SocketReceiveMultiplexer::Implementation
+DetachSocketListener	osc/oscPack/ip/win32/UdpSocket.cpp	/^void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )$/;"	f	class:SocketReceiveMultiplexer
+EPSILON	modules/RevealedModelModule.cpp	29;"	d	file:
+ElementCount	osc/oscPack/osc/OscReceivedElements.h	/^    uint32 ElementCount() const { return elementCount_; }$/;"	f	class:osc::ReceivedBundle
+ElementSizeSlotRequired	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^bool OutboundPacketStream::ElementSizeSlotRequired() const$/;"	f	class:osc::OutboundPacketStream
+ElementSizeSlotRequired	osc/oscPack/osc/OscOutboundPacketStream.h	/^    bool ElementSizeSlotRequired() const;$/;"	p	class:osc::OutboundPacketStream
+ElementsBegin	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedBundleElementIterator ElementsBegin() const$/;"	f	class:osc::ReceivedBundle
+ElementsEnd	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedBundleElementIterator ElementsEnd() const$/;"	f	class:osc::ReceivedBundle
+EndArray	osc/oscPack/osc/OscTypes.cpp	/^ArrayTerminator EndArray;$/;"	m	namespace:osc	file:
+EndBundle	osc/oscPack/osc/OscTypes.cpp	/^BundleTerminator EndBundle;$/;"	m	namespace:osc	file:
+EndElement	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^void OutboundPacketStream::EndElement( char *endPtr )$/;"	f	class:osc::OutboundPacketStream
+EndElement	osc/oscPack/osc/OscOutboundPacketStream.h	/^    void EndElement( char *endPtr );$/;"	p	class:osc::OutboundPacketStream
+EndMessage	osc/oscPack/osc/OscTypes.cpp	/^MessageTerminator EndMessage;$/;"	m	namespace:osc	file:
+Eos	osc/oscPack/osc/OscReceivedElements.h	/^    bool Eos() const { return p_ == end_; }$/;"	f	class:osc::ReceivedMessageArgumentStream
+Exception	osc/oscPack/osc/OscException.h	/^    Exception( const Exception& src ) throw()$/;"	f	class:osc::Exception
+Exception	osc/oscPack/osc/OscException.h	/^    Exception( const char *w ) throw()$/;"	f	class:osc::Exception
+Exception	osc/oscPack/osc/OscException.h	/^    Exception() throw() {}$/;"	f	class:osc::Exception
+Exception	osc/oscPack/osc/OscException.h	/^class Exception : public std::exception {$/;"	c	namespace:osc
+ExcessArgumentException	osc/oscPack/osc/OscReceivedElements.h	/^    ExcessArgumentException( const char *w="too many arguments" )$/;"	f	class:osc::ExcessArgumentException
+ExcessArgumentException	osc/oscPack/osc/OscReceivedElements.h	/^class ExcessArgumentException : public Exception{$/;"	c	namespace:osc
+FALSE_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    FALSE_TYPE_TAG = 'F',$/;"	e	enum:osc::TypeTagValues
+FILE_OPEN_ATTRIBUTE	modules/Attribute.hpp	/^                   FILE_OPEN_ATTRIBUTE, $/;"	e	enum:Attribute::TYPE
+FILE_SAVE_ATTRIBUTE	modules/Attribute.hpp	/^                   FILE_SAVE_ATTRIBUTE, $/;"	e	enum:Attribute::TYPE
+FLOAT_ATTRIBUTE	modules/Attribute.hpp	/^        enum TYPE {FLOAT_ATTRIBUTE, $/;"	e	enum:Attribute::TYPE
+FLOAT_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    FLOAT_TYPE_TAG = 'f',$/;"	e	enum:osc::TypeTagValues
+FOLDER_OPEN_ATTRIBUTE	modules/Attribute.hpp	/^                   FOLDER_OPEN_ATTRIBUTE, $/;"	e	enum:Attribute::TYPE
+FileCallback	modules/Attribute.hpp	/^        typedef void (FileCallback) (Module*, const std::string&);$/;"	t	class:Attribute
+FindStr4End	osc/oscPack/osc/OscReceivedElements.cpp	/^static inline const char* FindStr4End( const char *p )$/;"	f	namespace:osc
+FindStr4End	osc/oscPack/osc/OscReceivedElements.cpp	/^static inline const char* FindStr4End( const char *p, const char *end )$/;"	f	namespace:osc
+FloatCallback	modules/Attribute.hpp	/^        typedef void (FloatCallback) (Module*, const std::vector<float>&);$/;"	t	class:Attribute
+FromInt32	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^static void FromInt32( char *p, int32 x )$/;"	f	namespace:osc
+FromInt64	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^static void FromInt64( char *p, int64 x )$/;"	f	namespace:osc
+FromUInt32	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^static void FromUInt32( char *p, uint32 x )$/;"	f	namespace:osc
+FromUInt64	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^static void FromUInt64( char *p, uint64 x )$/;"	f	namespace:osc
+GEOM_BOX	Reveal.hpp	/^            GEOM_BOX, GEOM_QUAD, GEOM_SPHERE, GEOM_TUBE, GEOM_CONE,$/;"	e	enum:Reveal::GEOM_ID
+GEOM_CAM1280	Reveal.hpp	/^            GEOM_CAM1280, GEOM_CAM640, GEOM_CAM320,$/;"	e	enum:Reveal::GEOM_ID
+GEOM_CAM320	Reveal.hpp	/^            GEOM_CAM1280, GEOM_CAM640, GEOM_CAM320,$/;"	e	enum:Reveal::GEOM_ID
+GEOM_CAM640	Reveal.hpp	/^            GEOM_CAM1280, GEOM_CAM640, GEOM_CAM320,$/;"	e	enum:Reveal::GEOM_ID
+GEOM_CONE	Reveal.hpp	/^            GEOM_BOX, GEOM_QUAD, GEOM_SPHERE, GEOM_TUBE, GEOM_CONE,$/;"	e	enum:Reveal::GEOM_ID
+GEOM_CUSTOM	Reveal.hpp	/^            GEOM_PATH, GEOM_CUSTOM$/;"	e	enum:Reveal::GEOM_ID
+GEOM_ID	Reveal.hpp	/^        enum GEOM_ID { $/;"	g	class:Reveal
+GEOM_PATH	Reveal.hpp	/^            GEOM_PATH, GEOM_CUSTOM$/;"	e	enum:Reveal::GEOM_ID
+GEOM_QUAD	Reveal.hpp	/^            GEOM_BOX, GEOM_QUAD, GEOM_SPHERE, GEOM_TUBE, GEOM_CONE,$/;"	e	enum:Reveal::GEOM_ID
+GEOM_SPHERE	Reveal.hpp	/^            GEOM_BOX, GEOM_QUAD, GEOM_SPHERE, GEOM_TUBE, GEOM_CONE,$/;"	e	enum:Reveal::GEOM_ID
+GEOM_TUBE	Reveal.hpp	/^            GEOM_BOX, GEOM_QUAD, GEOM_SPHERE, GEOM_TUBE, GEOM_CONE,$/;"	e	enum:Reveal::GEOM_ID
+GLM_ENABLE_EXPERIMENTAL	modules/Module.hpp	29;"	d
+GLOBAL	modules/Attribute.hpp	/^        enum ACCESSIBILITY {HIDDEN, OUTPUT, LOCAL, GLOBAL};$/;"	e	enum:Attribute::ACCESSIBILITY
+GRADIENTTYPE	Reveal.hpp	/^            INSIDE, SURFACE, GRADIENTTYPE, SURFACETHICKNESS,$/;"	e	enum:Reveal::REVIL_UNIFORM
+GeomModule	modules/GeomModule.cpp	/^GeomModule::GeomModule(): Module(), $/;"	f	class:GeomModule
+GeomModule	modules/GeomModule.hpp	/^        GeomModule();$/;"	p	class:GeomModule
+GeomModule	modules/GeomModule.hpp	/^class GeomModule : public virtual Module {$/;"	c
+GeomModule_h	modules/GeomModule.hpp	25;"	d
+Geometry	geoms/Geometry.cpp	/^Geometry::Geometry():m_hasTexCoords(false), m_points(false) {}$/;"	f	class:Geometry
+Geometry	geoms/Geometry.hpp	/^        Geometry();$/;"	p	class:Geometry
+Geometry	geoms/Geometry.hpp	/^class Geometry {$/;"	c
+Geometry_h	geoms/Geometry.hpp	25;"	d
+GetCurrentTimeMs	osc/oscPack/ip/posix/UdpSocket.cpp	/^	double GetCurrentTimeMs() const$/;"	f	class:SocketReceiveMultiplexer::Implementation	file:
+GetCurrentTimeMs	osc/oscPack/ip/win32/UdpSocket.cpp	/^	double GetCurrentTimeMs() const$/;"	f	class:SocketReceiveMultiplexer::Implementation	file:
+GetHostByName	osc/oscPack/ip/IpEndpointName.cpp	/^unsigned long IpEndpointName::GetHostByName( const char *s )$/;"	f	class:IpEndpointName
+GetHostByName	osc/oscPack/ip/IpEndpointName.h	/^    static unsigned long GetHostByName( const char *s );$/;"	p	class:IpEndpointName
+GetHostByName	osc/oscPack/ip/NetworkingUtils.h	/^unsigned long GetHostByName( const char *name );$/;"	p
+GetHostByName	osc/oscPack/ip/posix/NetworkingUtils.cpp	/^unsigned long GetHostByName( const char *name )$/;"	f
+GetHostByName	osc/oscPack/ip/win32/NetworkingUtils.cpp	/^unsigned long GetHostByName( const char *name )$/;"	f
+GroupModule	modules/GroupModule.cpp	/^GroupModule::GroupModule():Module() {$/;"	f	class:GroupModule
+GroupModule	modules/GroupModule.hpp	/^        GroupModule();$/;"	p	class:GroupModule
+GroupModule	modules/GroupModule.hpp	/^class GroupModule: public virtual Module {$/;"	c
+GroupModule_h	modules/GroupModule.hpp	25;"	d
+GuiListener	gui/GuiListener.cpp	/^GuiListener::GuiListener(AttributeWidget* wid):Listener(), $/;"	f	class:GuiListener
+GuiListener	gui/GuiListener.hpp	/^        GuiListener(AttributeWidget*);$/;"	p	class:GuiListener
+GuiListener	gui/GuiListener.hpp	/^class GuiListener: public Listener {$/;"	c
+GuiListener_h	gui/GuiListener.hpp	25;"	d
+HIDDEN	modules/Attribute.hpp	/^        enum ACCESSIBILITY {HIDDEN, OUTPUT, LOCAL, GLOBAL};$/;"	e	enum:Attribute::ACCESSIBILITY
+INCLUDED_OSCPACK_IPENDPOINTNAME_H	osc/oscPack/ip/IpEndpointName.h	38;"	d
+INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H	osc/oscPack/osc/MessageMappingOscPacketListener.h	38;"	d
+INCLUDED_OSCPACK_NETWORKINGUTILS_H	osc/oscPack/ip/NetworkingUtils.h	38;"	d
+INCLUDED_OSCPACK_OSCEXCEPTION_H	osc/oscPack/osc/OscException.h	38;"	d
+INCLUDED_OSCPACK_OSCHOSTENDIANNESS_H	osc/oscPack/osc/OscHostEndianness.h	38;"	d
+INCLUDED_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H	osc/oscPack/osc/OscOutboundPacketStream.h	38;"	d
+INCLUDED_OSCPACK_OSCPACKETLISTENER_H	osc/oscPack/osc/OscPacketListener.h	38;"	d
+INCLUDED_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H	osc/oscPack/osc/OscPrintReceivedElements.h	38;"	d
+INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H	osc/oscPack/osc/OscReceivedElements.h	38;"	d
+INCLUDED_OSCPACK_OSCTYPES_H	osc/oscPack/osc/OscTypes.h	38;"	d
+INCLUDED_OSCPACK_PACKETLISTENER_H	osc/oscPack/ip/PacketListener.h	38;"	d
+INCLUDED_OSCPACK_TIMERLISTENER_H	osc/oscPack/ip/TimerListener.h	38;"	d
+INCLUDED_OSCPACK_UDPSOCKET_H	osc/oscPack/ip/UdpSocket.h	38;"	d
+INFINITUM_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    INFINITUM_TYPE_TAG = 'I',$/;"	e	enum:osc::TypeTagValues
+INSIDE	Reveal.hpp	/^            INSIDE, SURFACE, GRADIENTTYPE, SURFACETHICKNESS,$/;"	e	enum:Reveal::REVIL_UNIFORM
+INSIDETEX	Reveal.hpp	/^            OUTPUTTEX, SLICETEX, SELECTTEX, INSIDETEX, SURFACETEX, COORDSTEX,$/;"	e	enum:Reveal::REVIL_UNIFORM
+INT32_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    INT32_TYPE_TAG = 'i',$/;"	e	enum:osc::TypeTagValues
+INT64_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    INT64_TYPE_TAG = 'h',$/;"	e	enum:osc::TypeTagValues
+INT_ATTRIBUTE	modules/Attribute.hpp	/^                   INT_ATTRIBUTE, $/;"	e	enum:Attribute::TYPE
+IP_MTU_SIZE	osc/OscManager.hpp	37;"	d
+ImageTracker	modules/DepthCamModule.cpp	/^ImageTracker::ImageTracker():Tracker() {$/;"	f	class:ImageTracker
+ImageTracker	modules/DepthCamModule.hpp	/^        ImageTracker();$/;"	p	class:ImageTracker
+ImageTracker	modules/DepthCamModule.hpp	/^class ImageTracker : public Tracker {$/;"	c
+Implementation	osc/oscPack/ip/posix/UdpSocket.cpp	/^	Implementation()$/;"	f	class:UdpSocket::Implementation
+Implementation	osc/oscPack/ip/posix/UdpSocket.cpp	/^    Implementation()$/;"	f	class:SocketReceiveMultiplexer::Implementation
+Implementation	osc/oscPack/ip/posix/UdpSocket.cpp	/^class SocketReceiveMultiplexer::Implementation{$/;"	c	class:SocketReceiveMultiplexer	file:
+Implementation	osc/oscPack/ip/posix/UdpSocket.cpp	/^class UdpSocket::Implementation{$/;"	c	class:UdpSocket	file:
+Implementation	osc/oscPack/ip/win32/UdpSocket.cpp	/^	Implementation()$/;"	f	class:UdpSocket::Implementation
+Implementation	osc/oscPack/ip/win32/UdpSocket.cpp	/^    Implementation()$/;"	f	class:SocketReceiveMultiplexer::Implementation
+Implementation	osc/oscPack/ip/win32/UdpSocket.cpp	/^class SocketReceiveMultiplexer::Implementation{$/;"	c	class:SocketReceiveMultiplexer	file:
+Implementation	osc/oscPack/ip/win32/UdpSocket.cpp	/^class UdpSocket::Implementation{$/;"	c	class:UdpSocket	file:
+Infinitum	osc/oscPack/osc/OscTypes.cpp	/^InfinitumType Infinitum;$/;"	m	namespace:osc	file:
+InfinitumType	osc/oscPack/osc/OscTypes.h	/^struct InfinitumType{$/;"	s	namespace:osc
+Init	osc/oscPack/osc/OscReceivedElements.cpp	/^void ReceivedBundle::Init( const char *bundle, osc_bundle_element_size_t size )$/;"	f	class:osc::ReceivedBundle
+Init	osc/oscPack/osc/OscReceivedElements.cpp	/^void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size )$/;"	f	class:osc::ReceivedMessage
+Init	osc/oscPack/osc/OscReceivedElements.h	/^    void Init( const char *bundle, osc_bundle_element_size_t size );$/;"	p	class:osc::ReceivedMessage
+Init	osc/oscPack/osc/OscReceivedElements.h	/^    void Init( const char *message, osc_bundle_element_size_t size );$/;"	p	class:osc::ReceivedBundle
+IntCallback	modules/Attribute.hpp	/^        typedef void (IntCallback) (Module*, const std::vector<int>&);$/;"	t	class:Attribute
+InterruptSignalHandler	osc/oscPack/ip/posix/UdpSocket.cpp	/^\/*static*\/ void InterruptSignalHandler( int )$/;"	f
+InterruptSignalHandler	osc/oscPack/ip/posix/UdpSocket.cpp	/^extern "C" \/*static*\/ void InterruptSignalHandler( int );$/;"	p	file:
+InterruptSignalHandler	osc/oscPack/ip/win32/UdpSocket.cpp	/^\/*static*\/ void InterruptSignalHandler( int )$/;"	f
+InterruptSignalHandler	osc/oscPack/ip/win32/UdpSocket.cpp	/^extern "C" \/*static*\/ void InterruptSignalHandler( int );$/;"	p	file:
+IpEndpointName	osc/oscPack/ip/IpEndpointName.h	/^    IpEndpointName( const char *addressName, int port_=ANY_PORT )$/;"	f	class:IpEndpointName
+IpEndpointName	osc/oscPack/ip/IpEndpointName.h	/^    IpEndpointName( int addressA, int addressB, int addressC, int addressD, int port_=ANY_PORT )$/;"	f	class:IpEndpointName
+IpEndpointName	osc/oscPack/ip/IpEndpointName.h	/^    IpEndpointName( int port_ ) $/;"	f	class:IpEndpointName
+IpEndpointName	osc/oscPack/ip/IpEndpointName.h	/^    IpEndpointName( unsigned long ipAddress_, int port_ ) $/;"	f	class:IpEndpointName
+IpEndpointName	osc/oscPack/ip/IpEndpointName.h	/^    IpEndpointName()$/;"	f	class:IpEndpointName
+IpEndpointName	osc/oscPack/ip/IpEndpointName.h	/^class IpEndpointName{$/;"	c
+IpEndpointNameFromSockaddr	osc/oscPack/ip/posix/UdpSocket.cpp	/^static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )$/;"	f	file:
+IpEndpointNameFromSockaddr	osc/oscPack/ip/win32/UdpSocket.cpp	/^static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )$/;"	f	file:
+IsArrayBegin	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsArrayBegin() const { return *typeTagPtr_ == ARRAY_BEGIN_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsArrayEnd	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsArrayEnd() const { return *typeTagPtr_ == ARRAY_END_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsBlob	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsBlob() const { return *typeTagPtr_ == BLOB_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsBool	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsBool() const$/;"	f	class:osc::ReceivedMessageArgument
+IsBound	osc/oscPack/ip/UdpSocket.h	/^	bool IsBound() const;$/;"	p	class:UdpSocket
+IsBound	osc/oscPack/ip/posix/UdpSocket.cpp	/^	bool IsBound() const { return isBound_; }$/;"	f	class:UdpSocket::Implementation
+IsBound	osc/oscPack/ip/posix/UdpSocket.cpp	/^bool UdpSocket::IsBound() const$/;"	f	class:UdpSocket
+IsBound	osc/oscPack/ip/win32/UdpSocket.cpp	/^	bool IsBound() const { return isBound_; }$/;"	f	class:UdpSocket::Implementation
+IsBound	osc/oscPack/ip/win32/UdpSocket.cpp	/^bool UdpSocket::IsBound() const$/;"	f	class:UdpSocket
+IsBundle	osc/oscPack/osc/OscReceivedElements.cpp	/^bool ReceivedBundleElement::IsBundle() const$/;"	f	class:osc::ReceivedBundleElement
+IsBundle	osc/oscPack/osc/OscReceivedElements.cpp	/^bool ReceivedPacket::IsBundle() const$/;"	f	class:osc::ReceivedPacket
+IsBundle	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsBundle() const;$/;"	p	class:osc::ReceivedBundleElement
+IsBundle	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsBundle() const;$/;"	p	class:osc::ReceivedPacket
+IsBundleInProgress	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^bool OutboundPacketStream::IsBundleInProgress() const$/;"	f	class:osc::OutboundPacketStream
+IsBundleInProgress	osc/oscPack/osc/OscOutboundPacketStream.h	/^    bool IsBundleInProgress() const;$/;"	p	class:osc::OutboundPacketStream
+IsChar	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsChar() const { return *typeTagPtr_ == CHAR_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsDouble	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsDouble() const { return *typeTagPtr_ == DOUBLE_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsEqualTo	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const$/;"	f	class:osc::ReceivedBundleElementIterator
+IsEqualTo	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const$/;"	f	class:osc::ReceivedMessageArgumentIterator
+IsFloat	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsFloat() const { return *typeTagPtr_ == FLOAT_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsInfinitum	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsInfinitum() const { return *typeTagPtr_ == INFINITUM_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsInt32	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsInt32() const { return *typeTagPtr_ == INT32_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsInt64	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsInt64() const { return *typeTagPtr_ == INT64_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsMessage	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsMessage() const { return !IsBundle(); }$/;"	f	class:osc::ReceivedBundleElement
+IsMessage	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsMessage() const { return !IsBundle(); }$/;"	f	class:osc::ReceivedPacket
+IsMessageInProgress	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^bool OutboundPacketStream::IsMessageInProgress() const$/;"	f	class:osc::OutboundPacketStream
+IsMessageInProgress	osc/oscPack/osc/OscOutboundPacketStream.h	/^    bool IsMessageInProgress() const;$/;"	p	class:osc::OutboundPacketStream
+IsMidiMessage	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsMidiMessage() const { return *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsMulticastAddress	osc/oscPack/ip/IpEndpointName.h	/^    bool IsMulticastAddress() const { return ((address >> 24) & 0xFF) >= 224 && ((address >> 24) & 0xFF) <= 239; }$/;"	f	class:IpEndpointName
+IsMultipleOf4	osc/oscPack/osc/OscTypes.h	/^inline bool IsMultipleOf4( osc_bundle_element_size_t x )$/;"	f	namespace:osc
+IsNil	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsNil() const { return *typeTagPtr_ == NIL_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsReady	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^bool OutboundPacketStream::IsReady() const$/;"	f	class:osc::OutboundPacketStream
+IsReady	osc/oscPack/osc/OscOutboundPacketStream.h	/^    bool IsReady() const;$/;"	p	class:osc::OutboundPacketStream
+IsRgbaColor	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsRgbaColor() const { return *typeTagPtr_ == RGBA_COLOR_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsString	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsString() const { return *typeTagPtr_ == STRING_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsSymbol	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsSymbol() const { return *typeTagPtr_ == SYMBOL_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsTimeTag	osc/oscPack/osc/OscReceivedElements.h	/^    bool IsTimeTag() const { return *typeTagPtr_ == TIME_TAG_TYPE_TAG; }$/;"	f	class:osc::ReceivedMessageArgument
+IsValidElementSizeValue	osc/oscPack/osc/OscTypes.h	/^inline bool IsValidElementSizeValue( osc_bundle_element_size_t x )$/;"	f	namespace:osc
+LOCAL	modules/Attribute.hpp	/^        enum ACCESSIBILITY {HIDDEN, OUTPUT, LOCAL, GLOBAL};$/;"	e	enum:Attribute::ACCESSIBILITY
+Listener	modules/Listener.cpp	/^Listener::Listener(){}$/;"	f	class:Listener
+Listener	modules/Listener.hpp	/^        Listener();$/;"	p	class:Listener
+Listener	modules/Listener.hpp	/^class Listener {$/;"	c
+ListenerWidget	gui/ListenerWidget.cpp	/^ListenerWidget::ListenerWidget(int x, int y, $/;"	f	class:ListenerWidget
+ListenerWidget	gui/ListenerWidget.hpp	/^        ListenerWidget(int x, int y, int w, int h, Listener* listener);$/;"	p	class:ListenerWidget
+ListenerWidget	gui/ListenerWidget.hpp	/^class ListenerWidget : public Fl_Group {$/;"	c
+ListenerWidget_h	gui/ListenerWidget.hpp	24;"	d
+Listener_h	modules/Listener.hpp	25;"	d
+LocalEndpointFor	osc/oscPack/ip/UdpSocket.h	/^	IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const;$/;"	p	class:UdpSocket
+LocalEndpointFor	osc/oscPack/ip/posix/UdpSocket.cpp	/^	IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const$/;"	f	class:UdpSocket::Implementation
+LocalEndpointFor	osc/oscPack/ip/posix/UdpSocket.cpp	/^IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const$/;"	f	class:UdpSocket
+LocalEndpointFor	osc/oscPack/ip/win32/UdpSocket.cpp	/^	IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const$/;"	f	class:UdpSocket::Implementation
+LocalEndpointFor	osc/oscPack/ip/win32/UdpSocket.cpp	/^IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const$/;"	f	class:UdpSocket
+MARKTEX	Reveal.hpp	/^            CAMFILTER, CAMCONTOURTHRESH, CAMMARKERS, MARKTEX, BACKGROUND,$/;"	e	enum:Reveal::REVIL_UNIFORM
+MIDI_MESSAGE_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    MIDI_MESSAGE_TYPE_TAG = 'm',$/;"	e	enum:osc::TypeTagValues
+MIRRORED	Reveal.hpp	/^            VIEWMAT, VIEWPROJMAT, MODELMAT, MIRRORED, $/;"	e	enum:Reveal::REVIL_UNIFORM
+MODELMAT	Reveal.hpp	/^            VIEWMAT, VIEWPROJMAT, MODELMAT, MIRRORED, $/;"	e	enum:Reveal::REVIL_UNIFORM
+MainWindow	gui/MainWindow.cpp	/^MainWindow::MainWindow(): Fl_Double_Window(600, 327, "Revil - Configuration"),$/;"	f	class:MainWindow
+MainWindow	gui/MainWindow.hpp	/^        MainWindow();$/;"	p	class:MainWindow
+MainWindow	gui/MainWindow.hpp	/^class MainWindow: public Fl_Double_Window {$/;"	c
+MainWindow_h	gui/MainWindow.hpp	25;"	d
+MalformedBundleException	osc/oscPack/osc/OscReceivedElements.h	/^    MalformedBundleException( const char *w="malformed bundle" )$/;"	f	class:osc::MalformedBundleException
+MalformedBundleException	osc/oscPack/osc/OscReceivedElements.h	/^class MalformedBundleException : public Exception{$/;"	c	namespace:osc
+MalformedMessageException	osc/oscPack/osc/OscReceivedElements.h	/^    MalformedMessageException( const char *w="malformed message" )$/;"	f	class:osc::MalformedMessageException
+MalformedMessageException	osc/oscPack/osc/OscReceivedElements.h	/^class MalformedMessageException : public Exception{$/;"	c	namespace:osc
+MalformedPacketException	osc/oscPack/osc/OscReceivedElements.h	/^    MalformedPacketException( const char *w="malformed packet" )$/;"	f	class:osc::MalformedPacketException
+MalformedPacketException	osc/oscPack/osc/OscReceivedElements.h	/^class MalformedPacketException : public Exception{$/;"	c	namespace:osc
+MessageInProgressException	osc/oscPack/osc/OscOutboundPacketStream.h	/^    MessageInProgressException($/;"	f	class:osc::MessageInProgressException
+MessageInProgressException	osc/oscPack/osc/OscOutboundPacketStream.h	/^class MessageInProgressException : public Exception{$/;"	c	namespace:osc
+MessageMappingOscPacketListener	osc/oscPack/osc/MessageMappingOscPacketListener.h	/^class MessageMappingOscPacketListener : public OscPacketListener{$/;"	c	namespace:osc
+MessageNotInProgressException	osc/oscPack/osc/OscOutboundPacketStream.h	/^    MessageNotInProgressException($/;"	f	class:osc::MessageNotInProgressException
+MessageNotInProgressException	osc/oscPack/osc/OscOutboundPacketStream.h	/^class MessageNotInProgressException : public Exception{$/;"	c	namespace:osc
+MessageTerminator	osc/oscPack/osc/OscTypes.h	/^struct MessageTerminator{$/;"	s	namespace:osc
+MidiMessage	osc/oscPack/osc/OscTypes.h	/^    MidiMessage() {}$/;"	f	struct:osc::MidiMessage
+MidiMessage	osc/oscPack/osc/OscTypes.h	/^    explicit MidiMessage( uint32 value_ ) : value( value_ ) {}$/;"	f	struct:osc::MidiMessage
+MidiMessage	osc/oscPack/osc/OscTypes.h	/^struct MidiMessage{$/;"	s	namespace:osc
+MissingArgumentException	osc/oscPack/osc/OscReceivedElements.h	/^    MissingArgumentException( const char *w="missing argument" )$/;"	f	class:osc::MissingArgumentException
+MissingArgumentException	osc/oscPack/osc/OscReceivedElements.h	/^class MissingArgumentException : public Exception{$/;"	c	namespace:osc
+ModelModule	modules/ModelModule.cpp	/^ModelModule::ModelModule(): GeomModule() {$/;"	f	class:ModelModule
+ModelModule	modules/ModelModule.hpp	/^        ModelModule();$/;"	p	class:ModelModule
+ModelModule	modules/ModelModule.hpp	/^class ModelModule : public virtual GeomModule {$/;"	c
+ModelModule_h	modules/ModelModule.hpp	25;"	d
+ModelVertex	modules/ModelModule.hpp	/^        struct ModelVertex {$/;"	s	class:ModelModule
+Module	modules/Module.cpp	/^Module::Module() {$/;"	f	class:Module
+Module	modules/Module.hpp	/^        Module();$/;"	p	class:Module
+Module	modules/Module.hpp	/^class Module {$/;"	c
+ModuleListObserver	Reveal.hpp	/^class ModuleListObserver {$/;"	c
+ModuleWidget	gui/ModuleWidget.cpp	/^ModuleWidget::ModuleWidget(int x, int y, $/;"	f	class:ModuleWidget
+ModuleWidget	gui/ModuleWidget.hpp	/^        ModuleWidget(int x, int y, int w, int h, Module* module);$/;"	p	class:ModuleWidget
+ModuleWidget	gui/ModuleWidget.hpp	/^class ModuleWidget : public Fl_Toggle_Button {$/;"	c
+ModuleWidget_h	gui/ModuleWidget.hpp	24;"	d
+Module_h	modules/Module.hpp	25;"	d
+NIL_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    NIL_TYPE_TAG = 'N',$/;"	e	enum:osc::TypeTagValues
+NetworkInitializer	osc/oscPack/ip/NetworkingUtils.h	/^    NetworkInitializer();$/;"	p	class:NetworkInitializer
+NetworkInitializer	osc/oscPack/ip/NetworkingUtils.h	/^class NetworkInitializer{$/;"	c
+NetworkInitializer	osc/oscPack/ip/posix/NetworkingUtils.cpp	/^NetworkInitializer::NetworkInitializer() {}$/;"	f	class:NetworkInitializer
+NetworkInitializer	osc/oscPack/ip/win32/NetworkingUtils.cpp	/^NetworkInitializer::NetworkInitializer()$/;"	f	class:NetworkInitializer
+Nil	osc/oscPack/osc/OscTypes.cpp	/^NilType Nil; \/\/ Objective-C defines Nil. so our Nil is deprecated. use OscNil instead$/;"	m	namespace:osc	file:
+NilType	osc/oscPack/osc/OscTypes.h	/^struct NilType{$/;"	s	namespace:osc
+OSC_BUNDLE_ELEMENT_SIZE_MAX	osc/oscPack/osc/OscTypes.h	/^    OSC_BUNDLE_ELEMENT_SIZE_MAX = 0x7FFFFFFC$/;"	e	enum:osc::__anon5
+OSC_HOST_BIG_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	104;"	d
+OSC_HOST_BIG_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	113;"	d
+OSC_HOST_BIG_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	60;"	d
+OSC_HOST_BIG_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	67;"	d
+OSC_HOST_BIG_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	71;"	d
+OSC_HOST_BIG_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	83;"	d
+OSC_HOST_BIG_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	87;"	d
+OSC_HOST_LITTLE_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	103;"	d
+OSC_HOST_LITTLE_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	114;"	d
+OSC_HOST_LITTLE_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	59;"	d
+OSC_HOST_LITTLE_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	66;"	d
+OSC_HOST_LITTLE_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	72;"	d
+OSC_HOST_LITTLE_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	82;"	d
+OSC_HOST_LITTLE_ENDIAN	osc/oscPack/osc/OscHostEndianness.h	88;"	d
+OSC_INT32_MAX	osc/oscPack/osc/OscTypes.h	/^    OSC_INT32_MAX = 0x7FFFFFFF,$/;"	e	enum:osc::__anon5
+OSC_SIZEOF_INT32	osc/oscPack/osc/OscTypes.h	/^    OSC_SIZEOF_INT32 = 4,$/;"	e	enum:osc::ValueTypeSizes
+OSC_SIZEOF_INT64	osc/oscPack/osc/OscTypes.h	/^    OSC_SIZEOF_INT64 = 8,$/;"	e	enum:osc::ValueTypeSizes
+OSC_SIZEOF_UINT32	osc/oscPack/osc/OscTypes.h	/^    OSC_SIZEOF_UINT32 = 4,$/;"	e	enum:osc::ValueTypeSizes
+OSC_SIZEOF_UINT64	osc/oscPack/osc/OscTypes.h	/^    OSC_SIZEOF_UINT64 = 8,$/;"	e	enum:osc::ValueTypeSizes
+OUTBLOBSIZE	Reveal.hpp	/^            OUTSHAPESIZE, OUTBLOBSIZE, OUTDEPTHSIZE, OUTNBDEPTH,$/;"	e	enum:Reveal::REVIL_UNIFORM
+OUTDEPTHSIZE	Reveal.hpp	/^            OUTSHAPESIZE, OUTBLOBSIZE, OUTDEPTHSIZE, OUTNBDEPTH,$/;"	e	enum:Reveal::REVIL_UNIFORM
+OUTNBDEPTH	Reveal.hpp	/^            OUTSHAPESIZE, OUTBLOBSIZE, OUTDEPTHSIZE, OUTNBDEPTH,$/;"	e	enum:Reveal::REVIL_UNIFORM
+OUTPUT	modules/Attribute.hpp	/^        enum ACCESSIBILITY {HIDDEN, OUTPUT, LOCAL, GLOBAL};$/;"	e	enum:Attribute::ACCESSIBILITY
+OUTPUTCURS	Reveal.hpp	/^            DEPTHTYPE, DEPTHID, OUTPUTCURS, $/;"	e	enum:Reveal::REVIL_UNIFORM
+OUTPUTTEX	Reveal.hpp	/^            OUTPUTTEX, SLICETEX, SELECTTEX, INSIDETEX, SURFACETEX, COORDSTEX,$/;"	e	enum:Reveal::REVIL_UNIFORM
+OUTSHAPESIZE	Reveal.hpp	/^            OUTSHAPESIZE, OUTBLOBSIZE, OUTDEPTHSIZE, OUTNBDEPTH,$/;"	e	enum:Reveal::REVIL_UNIFORM
+OscListener	osc/OscListener.cpp	/^OscListener::OscListener():Listener() {$/;"	f	class:OscListener
+OscListener	osc/OscListener.cpp	/^OscListener::OscListener(const std::string& adPort):Listener() {$/;"	f	class:OscListener
+OscListener	osc/OscListener.hpp	/^        OscListener();$/;"	p	class:OscListener
+OscListener	osc/OscListener.hpp	/^        OscListener(const std::string& adPort);$/;"	p	class:OscListener
+OscListener	osc/OscListener.hpp	/^class OscListener: public Listener {$/;"	c
+OscListener_h	osc/OscListener.hpp	25;"	d
+OscManager	osc/OscManager.cpp	/^OscManager::OscManager(): osc::OscPacketListener() {}$/;"	f	class:OscManager
+OscManager	osc/OscManager.hpp	/^        OscManager();$/;"	p	class:OscManager
+OscManager	osc/OscManager.hpp	/^class OscManager :  public osc::OscPacketListener {$/;"	c
+OscManager_h	osc/OscManager.hpp	25;"	d
+OscMessage	osc/OscManager.hpp	/^struct OscMessage {$/;"	s
+OscNil	osc/oscPack/osc/OscTypes.cpp	/^NilType OscNil;$/;"	m	namespace:osc	file:
+OscPacketListener	osc/oscPack/osc/OscPacketListener.h	/^class OscPacketListener : public PacketListener{ $/;"	c	namespace:osc
+OscStream	osc/OscManager.hpp	/^struct OscStream {$/;"	s
+OutOfBufferMemoryException	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutOfBufferMemoryException( const char *w="out of buffer memory" )$/;"	f	class:osc::OutOfBufferMemoryException
+OutOfBufferMemoryException	osc/oscPack/osc/OscOutboundPacketStream.h	/^class OutOfBufferMemoryException : public Exception{$/;"	c	namespace:osc
+OutboundPacketStream	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream::OutboundPacketStream( char *buffer, std::size_t capacity )$/;"	f	class:osc::OutboundPacketStream
+OutboundPacketStream	osc/oscPack/osc/OscOutboundPacketStream.h	/^	OutboundPacketStream( char *buffer, std::size_t capacity );$/;"	p	class:osc::OutboundPacketStream
+OutboundPacketStream	osc/oscPack/osc/OscOutboundPacketStream.h	/^class OutboundPacketStream{$/;"	c	namespace:osc
+PATBRIGHT	Reveal.hpp	/^            PATW, PATPOSX, PATPOSY, PATNBX, PATNBY, PATBRIGHT, PATTERNTEX$/;"	e	enum:Reveal::REVIL_UNIFORM
+PATNBX	Reveal.hpp	/^            PATW, PATPOSX, PATPOSY, PATNBX, PATNBY, PATBRIGHT, PATTERNTEX$/;"	e	enum:Reveal::REVIL_UNIFORM
+PATNBY	Reveal.hpp	/^            PATW, PATPOSX, PATPOSY, PATNBX, PATNBY, PATBRIGHT, PATTERNTEX$/;"	e	enum:Reveal::REVIL_UNIFORM
+PATPOSX	Reveal.hpp	/^            PATW, PATPOSX, PATPOSY, PATNBX, PATNBY, PATBRIGHT, PATTERNTEX$/;"	e	enum:Reveal::REVIL_UNIFORM
+PATPOSY	Reveal.hpp	/^            PATW, PATPOSX, PATPOSY, PATNBX, PATNBY, PATBRIGHT, PATTERNTEX$/;"	e	enum:Reveal::REVIL_UNIFORM
+PATTERNTEX	Reveal.hpp	/^            PATW, PATPOSX, PATPOSY, PATNBX, PATNBY, PATBRIGHT, PATTERNTEX$/;"	e	enum:Reveal::REVIL_UNIFORM
+PATW	Reveal.hpp	/^            PATW, PATPOSX, PATPOSY, PATNBX, PATNBY, PATBRIGHT, PATTERNTEX$/;"	e	enum:Reveal::REVIL_UNIFORM
+PREVIEWPROG	Reveal.hpp	/^            PREVIEWPROG, SLICEPROG, SELECTPROG, RENDERPROG, CALIBPROG$/;"	e	enum:Reveal::REVIL_PROGRAM
+PacketListener	osc/oscPack/ip/PacketListener.h	/^class PacketListener{$/;"	c
+PathPoint	modules/RevealedPathModule.hpp	/^        PathPoint(){}$/;"	f	class:PathPoint
+PathPoint	modules/RevealedPathModule.hpp	/^        PathPoint(glm::vec4 pnt):m_point(pnt){}$/;"	f	class:PathPoint
+PathPoint	modules/RevealedPathModule.hpp	/^class PathPoint {$/;"	c
+PathPointModule	modules/RevealedPathModule.cpp	/^PathPointModule::PathPointModule(RevealedPathModule* path): $/;"	f	class:PathPointModule
+PathPointModule	modules/RevealedPathModule.cpp	/^PathPointModule::PathPointModule(RevealedPathModule* path, $/;"	f	class:PathPointModule
+PathPointModule	modules/RevealedPathModule.hpp	/^        PathPointModule(RevealedPathModule*);$/;"	p	class:PathPointModule
+PathPointModule	modules/RevealedPathModule.hpp	/^        PathPointModule(RevealedPathModule*, Module*);$/;"	p	class:PathPointModule
+PathPointModule	modules/RevealedPathModule.hpp	/^class PathPointModule : public PathPoint, public Listener {$/;"	c
+PreviewModule	modules/PreviewModule.cpp	/^PreviewModule::PreviewModule():Module() {$/;"	f	class:PreviewModule
+PreviewModule	modules/PreviewModule.hpp	/^        PreviewModule();$/;"	p	class:PreviewModule
+PreviewModule	modules/PreviewModule.hpp	/^class PreviewModule: public Module, public ContextHandler {$/;"	c
+PreviewModule_h	modules/PreviewModule.hpp	25;"	d
+ProcessBundle	osc/oscPack/osc/OscPacketListener.h	/^    virtual void ProcessBundle( const osc::ReceivedBundle& b, $/;"	f	class:osc::OscPacketListener
+ProcessMessage	osc/OscManager.cpp	/^void OscManager::ProcessMessage(const osc::ReceivedMessage& mess,$/;"	f	class:OscManager
+ProcessMessage	osc/OscManager.hpp	/^        virtual void ProcessMessage(const osc::ReceivedMessage& m,$/;"	p	class:OscManager
+ProcessMessage	osc/oscPack/osc/MessageMappingOscPacketListener.h	/^    virtual void ProcessMessage( const osc::ReceivedMessage& m,$/;"	f	class:osc::MessageMappingOscPacketListener
+ProcessMessage	osc/oscPack/osc/OscPacketListener.h	/^    virtual void ProcessMessage( const osc::ReceivedMessage& m, $/;"	p	class:osc::OscPacketListener
+ProcessPacket	osc/oscPack/ip/PacketListener.h	/^    virtual void ProcessPacket( const char *data, int size, $/;"	p	class:PacketListener
+ProcessPacket	osc/oscPack/osc/OscPacketListener.h	/^	virtual void ProcessPacket( const char *data, int size, $/;"	f	class:osc::OscPacketListener
+ProjectorModule	modules/ProjectorModule.cpp	/^ProjectorModule::ProjectorModule(): Module() {$/;"	f	class:ProjectorModule
+ProjectorModule	modules/ProjectorModule.hpp	/^        ProjectorModule();$/;"	p	class:ProjectorModule
+ProjectorModule	modules/ProjectorModule.hpp	/^class ProjectorModule : public Module, public ContextHandler {$/;"	c
+ProjectorModule_h	modules/ProjectorModule.hpp	25;"	d
+QuadGeometry	geoms/QuadGeometry.cpp	/^QuadGeometry::QuadGeometry(): Geometry() {$/;"	f	class:QuadGeometry
+QuadGeometry	geoms/QuadGeometry.hpp	/^        QuadGeometry();$/;"	p	class:QuadGeometry
+QuadGeometry	geoms/QuadGeometry.hpp	/^class QuadGeometry : public Geometry {$/;"	c
+QuadGeometry_h	geoms/QuadGeometry.hpp	25;"	d
+RENDERPROG	Reveal.hpp	/^            PREVIEWPROG, SLICEPROG, SELECTPROG, RENDERPROG, CALIBPROG$/;"	e	enum:Reveal::REVIL_PROGRAM
+REVBLOB	Reveal.hpp	/^            REVCURSOR, REVCOLOR, REVBLOB, REVEALEDBY, $/;"	e	enum:Reveal::REVIL_UNIFORM
+REVCENTER	Reveal.hpp	/^            REVSURFACE, REVINSIDE, REVCENTER,  $/;"	e	enum:Reveal::REVIL_UNIFORM
+REVCOLOR	Reveal.hpp	/^            REVCURSOR, REVCOLOR, REVBLOB, REVEALEDBY, $/;"	e	enum:Reveal::REVIL_UNIFORM
+REVCURSOR	Reveal.hpp	/^            REVCURSOR, REVCOLOR, REVBLOB, REVEALEDBY, $/;"	e	enum:Reveal::REVIL_UNIFORM
+REVEALEDBY	Reveal.hpp	/^            REVCURSOR, REVCOLOR, REVBLOB, REVEALEDBY, $/;"	e	enum:Reveal::REVIL_UNIFORM
+REVIL_PROGRAM	Reveal.hpp	/^        enum REVIL_PROGRAM {$/;"	g	class:Reveal
+REVIL_UNIFORM	Reveal.hpp	/^        enum REVIL_UNIFORM {$/;"	g	class:Reveal
+REVINSIDE	Reveal.hpp	/^            REVSURFACE, REVINSIDE, REVCENTER,  $/;"	e	enum:Reveal::REVIL_UNIFORM
+REVSURFACE	Reveal.hpp	/^            REVSURFACE, REVINSIDE, REVCENTER,  $/;"	e	enum:Reveal::REVIL_UNIFORM
+RGBA_COLOR_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    RGBA_COLOR_TYPE_TAG = 'r',$/;"	e	enum:osc::TypeTagValues
+ReceiveFrom	osc/oscPack/ip/UdpSocket.h	/^    std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size );$/;"	p	class:UdpSocket
+ReceiveFrom	osc/oscPack/ip/posix/UdpSocket.cpp	/^    std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )$/;"	f	class:UdpSocket::Implementation
+ReceiveFrom	osc/oscPack/ip/posix/UdpSocket.cpp	/^std::size_t UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )$/;"	f	class:UdpSocket
+ReceiveFrom	osc/oscPack/ip/win32/UdpSocket.cpp	/^    std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )$/;"	f	class:UdpSocket::Implementation
+ReceiveFrom	osc/oscPack/ip/win32/UdpSocket.cpp	/^std::size_t UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )$/;"	f	class:UdpSocket
+ReceivedBundle	osc/oscPack/osc/OscReceivedElements.cpp	/^ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement )$/;"	f	class:osc::ReceivedBundle
+ReceivedBundle	osc/oscPack/osc/OscReceivedElements.cpp	/^ReceivedBundle::ReceivedBundle( const ReceivedPacket& packet )$/;"	f	class:osc::ReceivedBundle
+ReceivedBundle	osc/oscPack/osc/OscReceivedElements.h	/^    explicit ReceivedBundle( const ReceivedBundleElement& bundleElement );$/;"	p	class:osc::ReceivedBundle
+ReceivedBundle	osc/oscPack/osc/OscReceivedElements.h	/^    explicit ReceivedBundle( const ReceivedPacket& packet );$/;"	p	class:osc::ReceivedBundle
+ReceivedBundle	osc/oscPack/osc/OscReceivedElements.h	/^class ReceivedBundle{$/;"	c	namespace:osc
+ReceivedBundleElement	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedBundleElement( const char *sizePtr )$/;"	f	class:osc::ReceivedBundleElement
+ReceivedBundleElement	osc/oscPack/osc/OscReceivedElements.h	/^class ReceivedBundleElement{$/;"	c	namespace:osc
+ReceivedBundleElementIterator	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedBundleElementIterator( const char *sizePtr )$/;"	f	class:osc::ReceivedBundleElementIterator
+ReceivedBundleElementIterator	osc/oscPack/osc/OscReceivedElements.h	/^class ReceivedBundleElementIterator{$/;"	c	namespace:osc
+ReceivedMessage	osc/oscPack/osc/OscReceivedElements.cpp	/^ReceivedMessage::ReceivedMessage( const ReceivedBundleElement& bundleElement )$/;"	f	class:osc::ReceivedMessage
+ReceivedMessage	osc/oscPack/osc/OscReceivedElements.cpp	/^ReceivedMessage::ReceivedMessage( const ReceivedPacket& packet )$/;"	f	class:osc::ReceivedMessage
+ReceivedMessage	osc/oscPack/osc/OscReceivedElements.h	/^    explicit ReceivedMessage( const ReceivedBundleElement& bundleElement );$/;"	p	class:osc::ReceivedMessage
+ReceivedMessage	osc/oscPack/osc/OscReceivedElements.h	/^    explicit ReceivedMessage( const ReceivedPacket& packet );$/;"	p	class:osc::ReceivedMessage
+ReceivedMessage	osc/oscPack/osc/OscReceivedElements.h	/^class ReceivedMessage{$/;"	c	namespace:osc
+ReceivedMessageArgument	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedMessageArgument( const char *typeTagPtr, const char *argumentPtr )$/;"	f	class:osc::ReceivedMessageArgument
+ReceivedMessageArgument	osc/oscPack/osc/OscReceivedElements.h	/^class ReceivedMessageArgument{$/;"	c	namespace:osc
+ReceivedMessageArgumentIterator	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedMessageArgumentIterator( const char *typeTags, const char *arguments )$/;"	f	class:osc::ReceivedMessageArgumentIterator
+ReceivedMessageArgumentIterator	osc/oscPack/osc/OscReceivedElements.h	/^class ReceivedMessageArgumentIterator{$/;"	c	namespace:osc
+ReceivedMessageArgumentStream	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream( const ReceivedMessageArgumentIterator& begin,$/;"	f	class:osc::ReceivedMessageArgumentStream
+ReceivedMessageArgumentStream	osc/oscPack/osc/OscReceivedElements.h	/^class ReceivedMessageArgumentStream{$/;"	c	namespace:osc
+ReceivedPacket	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedPacket( const char *contents, int size )$/;"	f	class:osc::ReceivedPacket
+ReceivedPacket	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedPacket( const char *contents, osc_bundle_element_size_t size )$/;"	f	class:osc::ReceivedPacket
+ReceivedPacket	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedPacket( const char *contents, std::size_t size )$/;"	f	class:osc::ReceivedPacket
+ReceivedPacket	osc/oscPack/osc/OscReceivedElements.h	/^class ReceivedPacket{$/;"	c	namespace:osc
+RegisterMessageFunction	osc/oscPack/osc/MessageMappingOscPacketListener.h	/^    void RegisterMessageFunction( const char *addressPattern, function_type f )$/;"	f	class:osc::MessageMappingOscPacketListener
+Reveal	Reveal.cpp	/^Reveal::Reveal() : GroupModule() {$/;"	f	class:Reveal
+Reveal	Reveal.hpp	/^        Reveal();$/;"	p	class:Reveal
+Reveal	Reveal.hpp	/^class Reveal : public GroupModule {$/;"	c
+Reveal_h	Reveal.hpp	25;"	d
+RevealedCutModule	modules/RevealedCutModule.cpp	/^RevealedCutModule::RevealedCutModule(): ShapeModule(), RevealedModule() {$/;"	f	class:RevealedCutModule
+RevealedCutModule	modules/RevealedCutModule.hpp	/^        RevealedCutModule();$/;"	p	class:RevealedCutModule
+RevealedCutModule	modules/RevealedCutModule.hpp	/^class RevealedCutModule : public ShapeModule, public RevealedModule {$/;"	c
+RevealedCutModule_h	modules/RevealedCutModule.hpp	25;"	d
+RevealedLayer	modules/RevealedModule.cpp	/^RevealedLayer::RevealedLayer(): m_playing(false), m_speed(1), $/;"	f	class:RevealedLayer
+RevealedLayer	modules/RevealedModule.hpp	/^        RevealedLayer();$/;"	p	class:RevealedLayer
+RevealedLayer	modules/RevealedModule.hpp	/^class RevealedLayer {$/;"	c
+RevealedLayerAnim	modules/RevealedModule.cpp	/^RevealedLayerAnim::RevealedLayerAnim():RevealedLayer() {$/;"	f	class:RevealedLayerAnim
+RevealedLayerAnim	modules/RevealedModule.hpp	/^        RevealedLayerAnim();$/;"	p	class:RevealedLayerAnim
+RevealedLayerAnim	modules/RevealedModule.hpp	/^class RevealedLayerAnim : public RevealedLayer {$/;"	c
+RevealedLayerImage	modules/RevealedModule.hpp	/^        RevealedLayerImage():RevealedLayer(){}$/;"	f	class:RevealedLayerImage
+RevealedLayerImage	modules/RevealedModule.hpp	/^class RevealedLayerImage : public RevealedLayer {$/;"	c
+RevealedLayerVideo	modules/RevealedModule.hpp	/^        RevealedLayerVideo():RevealedLayer(){}$/;"	f	class:RevealedLayerVideo
+RevealedLayerVideo	modules/RevealedModule.hpp	/^class RevealedLayerVideo: public RevealedLayer {$/;"	c
+RevealedModelModule	modules/RevealedModelModule.cpp	/^RevealedModelModule::RevealedModelModule(): ModelModule(), RevealedModule(){$/;"	f	class:RevealedModelModule
+RevealedModelModule	modules/RevealedModelModule.hpp	/^        RevealedModelModule();$/;"	p	class:RevealedModelModule
+RevealedModelModule	modules/RevealedModelModule.hpp	/^class RevealedModelModule : public ModelModule, public RevealedModule {$/;"	c
+RevealedModelModule_h	modules/RevealedModelModule.hpp	25;"	d
+RevealedModule	modules/RevealedModule.cpp	/^RevealedModule::RevealedModule(): GeomModule(), $/;"	f	class:RevealedModule
+RevealedModule	modules/RevealedModule.hpp	/^        RevealedModule();$/;"	p	class:RevealedModule
+RevealedModule	modules/RevealedModule.hpp	/^class RevealedModule : public virtual GeomModule {$/;"	c
+RevealedModule_h	modules/RevealedModule.hpp	25;"	d
+RevealedPathModule	modules/RevealedPathModule.cpp	/^RevealedPathModule::RevealedPathModule(): RevealedModule() {$/;"	f	class:RevealedPathModule
+RevealedPathModule	modules/RevealedPathModule.hpp	/^        RevealedPathModule();$/;"	p	class:RevealedPathModule
+RevealedPathModule	modules/RevealedPathModule.hpp	/^class RevealedPathModule : public RevealedModule, public ModuleListObserver {$/;"	c
+RevealedPathModule_h	modules/RevealedPathModule.hpp	25;"	d
+RevealedShapeModule	modules/RevealedShapeModule.cpp	/^RevealedShapeModule::RevealedShapeModule(): ShapeModule(), RevealedModule(){$/;"	f	class:RevealedShapeModule
+RevealedShapeModule	modules/RevealedShapeModule.hpp	/^        RevealedShapeModule();$/;"	p	class:RevealedShapeModule
+RevealedShapeModule	modules/RevealedShapeModule.hpp	/^class RevealedShapeModule : public ShapeModule, public RevealedModule {$/;"	c
+RevealedShapeModule_h	modules/RevealedShapeModule.hpp	25;"	d
+RevealedTextModule	modules/RevealedTextModule.cpp	/^RevealedTextModule::RevealedTextModule(): ShapeModule(), RevealedModule() {$/;"	f	class:RevealedTextModule
+RevealedTextModule	modules/RevealedTextModule.hpp	/^        RevealedTextModule();$/;"	p	class:RevealedTextModule
+RevealedTextModule	modules/RevealedTextModule.hpp	/^class RevealedTextModule : public ShapeModule, public RevealedModule {$/;"	c
+RevealedTextModule_h	modules/RevealedTextModule.hpp	25;"	d
+RgbaColor	osc/oscPack/osc/OscTypes.h	/^    RgbaColor() {}$/;"	f	struct:osc::RgbaColor
+RgbaColor	osc/oscPack/osc/OscTypes.h	/^    explicit RgbaColor( uint32 value_ ) : value( value_ ) {}$/;"	f	struct:osc::RgbaColor
+RgbaColor	osc/oscPack/osc/OscTypes.h	/^struct RgbaColor{$/;"	s	namespace:osc
+RootSceneGroupModule	modules/RootSceneGroupModule.cpp	/^RootSceneGroupModule::RootSceneGroupModule(): GroupModule() {$/;"	f	class:RootSceneGroupModule
+RootSceneGroupModule	modules/RootSceneGroupModule.hpp	/^        RootSceneGroupModule();$/;"	p	class:RootSceneGroupModule
+RootSceneGroupModule	modules/RootSceneGroupModule.hpp	/^class RootSceneGroupModule: public GroupModule {$/;"	c
+RootSceneGroupModule_h	modules/RootSceneGroupModule.hpp	24;"	d
+RoundUp4	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^static inline std::size_t RoundUp4( std::size_t x ) $/;"	f	namespace:osc
+RoundUp4	osc/oscPack/osc/OscReceivedElements.cpp	/^static inline uint32 RoundUp4( uint32 x ) $/;"	f	namespace:osc
+Run	osc/oscPack/ip/UdpSocket.h	/^    void Run() { mux_.Run(); }$/;"	f	class:UdpListeningReceiveSocket
+Run	osc/oscPack/ip/UdpSocket.h	/^    void Run();      \/\/ loop and block processing messages indefinitely$/;"	p	class:SocketReceiveMultiplexer
+Run	osc/oscPack/ip/posix/UdpSocket.cpp	/^    void Run()$/;"	f	class:SocketReceiveMultiplexer::Implementation
+Run	osc/oscPack/ip/posix/UdpSocket.cpp	/^void SocketReceiveMultiplexer::Run()$/;"	f	class:SocketReceiveMultiplexer
+Run	osc/oscPack/ip/win32/UdpSocket.cpp	/^    void Run()$/;"	f	class:SocketReceiveMultiplexer::Implementation
+Run	osc/oscPack/ip/win32/UdpSocket.cpp	/^void SocketReceiveMultiplexer::Run()$/;"	f	class:SocketReceiveMultiplexer
+RunUntilSigInt	osc/oscPack/ip/UdpSocket.h	/^	void RunUntilSigInt() { mux_.RunUntilSigInt(); }$/;"	f	class:UdpListeningReceiveSocket
+RunUntilSigInt	osc/oscPack/ip/UdpSocket.h	/^	void RunUntilSigInt();$/;"	p	class:SocketReceiveMultiplexer
+RunUntilSigInt	osc/oscPack/ip/posix/UdpSocket.cpp	/^void SocketReceiveMultiplexer::RunUntilSigInt()$/;"	f	class:SocketReceiveMultiplexer
+RunUntilSigInt	osc/oscPack/ip/win32/UdpSocket.cpp	/^void SocketReceiveMultiplexer::RunUntilSigInt()$/;"	f	class:SocketReceiveMultiplexer
+SELECTPROG	Reveal.hpp	/^            PREVIEWPROG, SLICEPROG, SELECTPROG, RENDERPROG, CALIBPROG$/;"	e	enum:Reveal::REVIL_PROGRAM
+SELECTTEX	Reveal.hpp	/^            OUTPUTTEX, SLICETEX, SELECTTEX, INSIDETEX, SURFACETEX, COORDSTEX,$/;"	e	enum:Reveal::REVIL_UNIFORM
+SHAPECOLOR	Reveal.hpp	/^            SHAPECOLOR, SHAPEID, SHAPEIDBIT, SUBSHAPEID, SUBSHAPESNB, $/;"	e	enum:Reveal::REVIL_UNIFORM
+SHAPEID	Reveal.hpp	/^            SHAPECOLOR, SHAPEID, SHAPEIDBIT, SUBSHAPEID, SUBSHAPESNB, $/;"	e	enum:Reveal::REVIL_UNIFORM
+SHAPEIDBIT	Reveal.hpp	/^            SHAPECOLOR, SHAPEID, SHAPEIDBIT, SUBSHAPEID, SUBSHAPESNB, $/;"	e	enum:Reveal::REVIL_UNIFORM
+SLICEPROG	Reveal.hpp	/^            PREVIEWPROG, SLICEPROG, SELECTPROG, RENDERPROG, CALIBPROG$/;"	e	enum:Reveal::REVIL_PROGRAM
+SLICETEX	Reveal.hpp	/^            OUTPUTTEX, SLICETEX, SELECTTEX, INSIDETEX, SURFACETEX, COORDSTEX,$/;"	e	enum:Reveal::REVIL_UNIFORM
+STRING_ATTRIBUTE	modules/Attribute.hpp	/^                   STRING_ATTRIBUTE, $/;"	e	enum:Attribute::TYPE
+STRING_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    STRING_TYPE_TAG = 's',$/;"	e	enum:osc::TypeTagValues
+SUBSHAPEID	Reveal.hpp	/^            SHAPECOLOR, SHAPEID, SHAPEIDBIT, SUBSHAPEID, SUBSHAPESNB, $/;"	e	enum:Reveal::REVIL_UNIFORM
+SUBSHAPESNB	Reveal.hpp	/^            SHAPECOLOR, SHAPEID, SHAPEIDBIT, SUBSHAPEID, SUBSHAPESNB, $/;"	e	enum:Reveal::REVIL_UNIFORM
+SURFACE	Reveal.hpp	/^            INSIDE, SURFACE, GRADIENTTYPE, SURFACETHICKNESS,$/;"	e	enum:Reveal::REVIL_UNIFORM
+SURFACETEX	Reveal.hpp	/^            OUTPUTTEX, SLICETEX, SELECTTEX, INSIDETEX, SURFACETEX, COORDSTEX,$/;"	e	enum:Reveal::REVIL_UNIFORM
+SURFACETHICKNESS	Reveal.hpp	/^            INSIDE, SURFACE, GRADIENTTYPE, SURFACETHICKNESS,$/;"	e	enum:Reveal::REVIL_UNIFORM
+SYMBOL_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    SYMBOL_TYPE_TAG = 'S',$/;"	e	enum:osc::TypeTagValues
+SceneGroupModule	modules/SceneGroupModule.cpp	/^SceneGroupModule::SceneGroupModule(): RootSceneGroupModule() {$/;"	f	class:SceneGroupModule
+SceneGroupModule	modules/SceneGroupModule.hpp	/^        SceneGroupModule();$/;"	p	class:SceneGroupModule
+SceneGroupModule	modules/SceneGroupModule.hpp	/^class SceneGroupModule: public RootSceneGroupModule {$/;"	c
+SceneGroupModule_h	modules/SceneGroupModule.hpp	24;"	d
+Send	osc/oscPack/ip/UdpSocket.h	/^	void Send( const char *data, std::size_t size );$/;"	p	class:UdpSocket
+Send	osc/oscPack/ip/posix/UdpSocket.cpp	/^	void Send( const char *data, std::size_t size )$/;"	f	class:UdpSocket::Implementation
+Send	osc/oscPack/ip/posix/UdpSocket.cpp	/^void UdpSocket::Send( const char *data, std::size_t size )$/;"	f	class:UdpSocket
+Send	osc/oscPack/ip/win32/UdpSocket.cpp	/^	void Send( const char *data, std::size_t size )$/;"	f	class:UdpSocket::Implementation
+Send	osc/oscPack/ip/win32/UdpSocket.cpp	/^void UdpSocket::Send( const char *data, std::size_t size )$/;"	f	class:UdpSocket
+SendTo	osc/oscPack/ip/UdpSocket.h	/^    void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size );$/;"	p	class:UdpSocket
+SendTo	osc/oscPack/ip/posix/UdpSocket.cpp	/^    void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )$/;"	f	class:UdpSocket::Implementation
+SendTo	osc/oscPack/ip/posix/UdpSocket.cpp	/^void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )$/;"	f	class:UdpSocket
+SendTo	osc/oscPack/ip/win32/UdpSocket.cpp	/^    void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )$/;"	f	class:UdpSocket::Implementation
+SendTo	osc/oscPack/ip/win32/UdpSocket.cpp	/^void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )$/;"	f	class:UdpSocket
+SetAllowReuse	osc/oscPack/ip/UdpSocket.h	/^	void SetAllowReuse( bool allowReuse );$/;"	p	class:UdpSocket
+SetAllowReuse	osc/oscPack/ip/posix/UdpSocket.cpp	/^	void SetAllowReuse( bool allowReuse )$/;"	f	class:UdpSocket::Implementation
+SetAllowReuse	osc/oscPack/ip/posix/UdpSocket.cpp	/^void UdpSocket::SetAllowReuse( bool allowReuse )$/;"	f	class:UdpSocket
+SetAllowReuse	osc/oscPack/ip/win32/UdpSocket.cpp	/^	void SetAllowReuse( bool allowReuse )$/;"	f	class:UdpSocket::Implementation
+SetAllowReuse	osc/oscPack/ip/win32/UdpSocket.cpp	/^void UdpSocket::SetAllowReuse( bool allowReuse )$/;"	f	class:UdpSocket
+SetEnableBroadcast	osc/oscPack/ip/UdpSocket.h	/^	void SetEnableBroadcast( bool enableBroadcast );$/;"	p	class:UdpSocket
+SetEnableBroadcast	osc/oscPack/ip/posix/UdpSocket.cpp	/^	void SetEnableBroadcast( bool enableBroadcast )$/;"	f	class:UdpSocket::Implementation
+SetEnableBroadcast	osc/oscPack/ip/posix/UdpSocket.cpp	/^void UdpSocket::SetEnableBroadcast( bool enableBroadcast )$/;"	f	class:UdpSocket
+SetEnableBroadcast	osc/oscPack/ip/win32/UdpSocket.cpp	/^	void SetEnableBroadcast( bool enableBroadcast )$/;"	f	class:UdpSocket::Implementation
+SetEnableBroadcast	osc/oscPack/ip/win32/UdpSocket.cpp	/^void UdpSocket::SetEnableBroadcast( bool enableBroadcast )$/;"	f	class:UdpSocket
+ShapeModule	modules/ShapeModule.cpp	/^ShapeModule::ShapeModule(): GeomModule() {$/;"	f	class:ShapeModule
+ShapeModule	modules/ShapeModule.hpp	/^        ShapeModule();$/;"	p	class:ShapeModule
+ShapeModule	modules/ShapeModule.hpp	/^class ShapeModule : public virtual GeomModule {$/;"	c
+ShapeModule_h	modules/ShapeModule.hpp	25;"	d
+Size	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^std::size_t OutboundPacketStream::Size() const$/;"	f	class:osc::OutboundPacketStream
+Size	osc/oscPack/osc/OscOutboundPacketStream.h	/^    std::size_t Size() const;$/;"	p	class:osc::OutboundPacketStream
+Size	osc/oscPack/osc/OscReceivedElements.cpp	/^osc_bundle_element_size_t ReceivedBundleElement::Size() const$/;"	f	class:osc::ReceivedBundleElement
+Size	osc/oscPack/osc/OscReceivedElements.h	/^    osc_bundle_element_size_t Size() const { return size_; }$/;"	f	class:osc::ReceivedPacket
+Size	osc/oscPack/osc/OscReceivedElements.h	/^    osc_bundle_element_size_t Size() const;$/;"	p	class:osc::ReceivedBundleElement
+SockaddrFromIpEndpointName	osc/oscPack/ip/posix/UdpSocket.cpp	/^static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )$/;"	f	file:
+SockaddrFromIpEndpointName	osc/oscPack/ip/win32/UdpSocket.cpp	/^static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )$/;"	f	file:
+Socket	osc/oscPack/ip/posix/UdpSocket.cpp	/^	int Socket() { return socket_; }$/;"	f	class:UdpSocket::Implementation
+Socket	osc/oscPack/ip/win32/UdpSocket.cpp	/^	SOCKET& Socket() { return socket_; }$/;"	f	class:UdpSocket::Implementation
+SocketReceiveMultiplexer	osc/oscPack/ip/UdpSocket.h	/^    SocketReceiveMultiplexer();$/;"	p	class:SocketReceiveMultiplexer
+SocketReceiveMultiplexer	osc/oscPack/ip/UdpSocket.h	/^class SocketReceiveMultiplexer{$/;"	c
+SocketReceiveMultiplexer	osc/oscPack/ip/posix/UdpSocket.cpp	/^SocketReceiveMultiplexer::SocketReceiveMultiplexer()$/;"	f	class:SocketReceiveMultiplexer
+SocketReceiveMultiplexer	osc/oscPack/ip/win32/UdpSocket.cpp	/^SocketReceiveMultiplexer::SocketReceiveMultiplexer()$/;"	f	class:SocketReceiveMultiplexer
+SpaceModule	modules/SpaceModule.cpp	/^SpaceModule::SpaceModule(): DepthGroupModule() {$/;"	f	class:SpaceModule
+SpaceModule	modules/SpaceModule.hpp	/^        SpaceModule();$/;"	p	class:SpaceModule
+SpaceModule	modules/SpaceModule.hpp	/^class SpaceModule : public DepthGroupModule {$/;"	c
+SpaceModule_h	modules/SpaceModule.hpp	25;"	d
+SpacesModule	modules/SpaceModule.hpp	/^        SpacesModule(): GroupModule() {$/;"	f	class:SpacesModule
+SpacesModule	modules/SpaceModule.hpp	/^class SpacesModule: public GroupModule {$/;"	c
+SphereGeometry	geoms/SphereGeometry.cpp	/^SphereGeometry::SphereGeometry(): Geometry() {$/;"	f	class:SphereGeometry
+SphereGeometry	geoms/SphereGeometry.hpp	/^        SphereGeometry();$/;"	p	class:SphereGeometry
+SphereGeometry	geoms/SphereGeometry.hpp	/^class SphereGeometry : public Geometry {$/;"	c
+SphereGeometry_h	geoms/SphereGeometry.hpp	25;"	d
+StringCallback	modules/Attribute.hpp	/^        typedef void (StringCallback) (Module*,const std::vector<std::string>&);$/;"	t	class:Attribute
+Symbol	osc/oscPack/osc/OscTypes.h	/^    Symbol() {}$/;"	f	struct:osc::Symbol
+Symbol	osc/oscPack/osc/OscTypes.h	/^    explicit Symbol( const char* value_ ) : value( value_ ) {}$/;"	f	struct:osc::Symbol
+Symbol	osc/oscPack/osc/OscTypes.h	/^struct Symbol{$/;"	s	namespace:osc
+TEXOFFSET	Reveal.hpp	/^            TEXOFFSET, TEXSCALE,$/;"	e	enum:Reveal::REVIL_UNIFORM
+TEXSCALE	Reveal.hpp	/^            TEXOFFSET, TEXSCALE,$/;"	e	enum:Reveal::REVIL_UNIFORM
+TIME_TAG_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    TIME_TAG_TYPE_TAG = 't',$/;"	e	enum:osc::TypeTagValues
+TRUE_TYPE_TAG	osc/oscPack/osc/OscTypes.h	/^    TRUE_TYPE_TAG = 'T',$/;"	e	enum:osc::TypeTagValues
+TYPE	modules/Attribute.hpp	/^        enum TYPE {FLOAT_ATTRIBUTE, $/;"	g	class:Attribute
+TimeTag	osc/oscPack/osc/OscReceivedElements.cpp	/^uint64 ReceivedBundle::TimeTag() const$/;"	f	class:osc::ReceivedBundle
+TimeTag	osc/oscPack/osc/OscReceivedElements.h	/^    uint64 TimeTag() const;$/;"	p	class:osc::ReceivedBundle
+TimeTag	osc/oscPack/osc/OscTypes.h	/^    TimeTag() {}$/;"	f	struct:osc::TimeTag
+TimeTag	osc/oscPack/osc/OscTypes.h	/^    explicit TimeTag( uint64 value_ ) : value( value_ ) {}$/;"	f	struct:osc::TimeTag
+TimeTag	osc/oscPack/osc/OscTypes.h	/^struct TimeTag{$/;"	s	namespace:osc
+TimerExpired	osc/oscPack/ip/TimerListener.h	/^    virtual void TimerExpired() = 0;$/;"	p	class:TimerListener
+TimerListener	osc/oscPack/ip/TimerListener.h	/^class TimerListener{$/;"	c
+ToInt32	osc/oscPack/osc/OscReceivedElements.cpp	/^static inline int32 ToInt32( const char *p )$/;"	f	namespace:osc
+ToInt64	osc/oscPack/osc/OscReceivedElements.cpp	/^static inline int64 ToInt64( const char *p )$/;"	f	namespace:osc
+ToUInt32	osc/oscPack/osc/OscReceivedElements.cpp	/^static inline uint32 ToUInt32( const char *p )$/;"	f	namespace:osc
+ToUInt64	osc/oscPack/osc/OscReceivedElements.cpp	/^static inline uint64 ToUInt64( const char *p )$/;"	f	namespace:osc
+Tracker	modules/DepthCamModule.hpp	/^class Tracker {$/;"	c
+TubeGeometry	geoms/TubeGeometry.cpp	/^TubeGeometry::TubeGeometry(): Geometry() {$/;"	f	class:TubeGeometry
+TubeGeometry	geoms/TubeGeometry.hpp	/^        TubeGeometry();$/;"	p	class:TubeGeometry
+TubeGeometry	geoms/TubeGeometry.hpp	/^class TubeGeometry : public Geometry {$/;"	c
+TubeGeometry_h	geoms/TubeGeometry.hpp	25;"	d
+TypeTag	osc/oscPack/osc/OscReceivedElements.h	/^	char TypeTag() const { return *typeTagPtr_; }$/;"	f	class:osc::ReceivedMessageArgument
+TypeTagValues	osc/oscPack/osc/OscTypes.h	/^enum TypeTagValues {$/;"	g	namespace:osc
+TypeTags	osc/oscPack/osc/OscReceivedElements.h	/^    const char *TypeTags() const { return typeTagsBegin_; }$/;"	f	class:osc::ReceivedMessage
+UdpListeningReceiveSocket	osc/oscPack/ip/UdpSocket.h	/^	UdpListeningReceiveSocket( const IpEndpointName& localEndpoint, PacketListener *listener )$/;"	f	class:UdpListeningReceiveSocket
+UdpListeningReceiveSocket	osc/oscPack/ip/UdpSocket.h	/^class UdpListeningReceiveSocket : public UdpSocket{$/;"	c
+UdpReceiveSocket	osc/oscPack/ip/UdpSocket.h	/^	UdpReceiveSocket( const IpEndpointName& localEndpoint )$/;"	f	class:UdpReceiveSocket
+UdpReceiveSocket	osc/oscPack/ip/UdpSocket.h	/^class UdpReceiveSocket : public UdpSocket{$/;"	c
+UdpSocket	osc/oscPack/ip/UdpSocket.h	/^	UdpSocket();$/;"	p	class:UdpSocket
+UdpSocket	osc/oscPack/ip/UdpSocket.h	/^class UdpSocket{$/;"	c
+UdpSocket	osc/oscPack/ip/posix/UdpSocket.cpp	/^UdpSocket::UdpSocket()$/;"	f	class:UdpSocket
+UdpSocket	osc/oscPack/ip/win32/UdpSocket.cpp	/^UdpSocket::UdpSocket()$/;"	f	class:UdpSocket
+UdpTransmitSocket	osc/oscPack/ip/UdpSocket.h	/^	UdpTransmitSocket( const IpEndpointName& remoteEndpoint )$/;"	f	class:UdpTransmitSocket
+UdpTransmitSocket	osc/oscPack/ip/UdpSocket.h	/^class UdpTransmitSocket : public UdpSocket{$/;"	c
+VIEWMAT	Reveal.hpp	/^            VIEWMAT, VIEWPROJMAT, MODELMAT, MIRRORED, $/;"	e	enum:Reveal::REVIL_UNIFORM
+VIEWPORTHEIGHT	Reveal.hpp	/^            VIEWPORTWIDTH, VIEWPORTHEIGHT, $/;"	e	enum:Reveal::REVIL_UNIFORM
+VIEWPORTWIDTH	Reveal.hpp	/^            VIEWPORTWIDTH, VIEWPORTHEIGHT, $/;"	e	enum:Reveal::REVIL_UNIFORM
+VIEWPROJMAT	Reveal.hpp	/^            VIEWMAT, VIEWPROJMAT, MODELMAT, MIRRORED, $/;"	e	enum:Reveal::REVIL_UNIFORM
+VISIBLE_FROM	Reveal.hpp	/^        enum VISIBLE_FROM {$/;"	g	class:Reveal
+VISIBLE_FROM_ALL	Reveal.hpp	/^            VISIBLE_FROM_NONE, VISIBLE_FROM_ALL$/;"	e	enum:Reveal::VISIBLE_FROM
+VISIBLE_FROM_NONE	Reveal.hpp	/^            VISIBLE_FROM_NONE, VISIBLE_FROM_ALL$/;"	e	enum:Reveal::VISIBLE_FROM
+ValidateSize	osc/oscPack/osc/OscReceivedElements.h	/^    static osc_bundle_element_size_t ValidateSize( osc_bundle_element_size_t size )$/;"	f	class:osc::ReceivedPacket
+ValueTypeSizes	osc/oscPack/osc/OscTypes.h	/^enum ValueTypeSizes{$/;"	g	namespace:osc
+WrongArgumentTypeException	osc/oscPack/osc/OscReceivedElements.h	/^    WrongArgumentTypeException( const char *w="wrong argument type" )$/;"	f	class:osc::WrongArgumentTypeException
+WrongArgumentTypeException	osc/oscPack/osc/OscReceivedElements.h	/^class WrongArgumentTypeException : public Exception{$/;"	c	namespace:osc
+_RINGBUFFER_H	osc/ringbuffer.h	22;"	d
+absPositionCallback	modules/Module.hpp	/^        static void absPositionCallback(Module* mod, $/;"	f	class:Module
+activateColor	modules/DepthCamModule.cpp	/^void DepthCamModule::activateColor() {$/;"	f	class:DepthCamModule
+activateColor	modules/DepthCamModule.hpp	/^        void activateColor();$/;"	p	class:DepthCamModule
+activeCallback	modules/PreviewModule.hpp	/^        static void activeCallback(Module* mod, $/;"	f	class:PreviewModule
+activeCallback	modules/ProjectorModule.hpp	/^        static void activeCallback(Module* mod, $/;"	f	class:ProjectorModule
+addAttribute	modules/Module.hpp	/^        inline void addAttribute(Attribute* attr) { $/;"	f	class:Module
+addCam	modules/DepthGroupModule.cpp	/^void DepthGroupModule::addCam() {$/;"	f	class:DepthGroupModule
+addCam	modules/DepthGroupModule.hpp	/^        void addCam();$/;"	p	class:DepthGroupModule
+addCamCallback	modules/DepthGroupModule.hpp	/^        static void addCamCallback(Module* mod) {$/;"	f	class:DepthGroupModule
+addChild	modules/DepthGroupModule.cpp	/^void DepthGroupModule::addChild(Module* mod) {$/;"	f	class:DepthGroupModule
+addChild	modules/DepthGroupModule.hpp	/^        virtual void addChild(Module*);$/;"	p	class:DepthGroupModule
+addChild	modules/GroupModule.cpp	/^void GroupModule::addChild(Module* mod) {$/;"	f	class:GroupModule
+addChild	modules/GroupModule.hpp	/^        virtual void addChild(Module* mod);$/;"	p	class:GroupModule
+addChild	modules/SpaceModule.cpp	/^void SpaceModule::addChild(Module* mod) {$/;"	f	class:SpaceModule
+addChild	modules/SpaceModule.hpp	/^        virtual void addChild(Module* mod);$/;"	p	class:SpaceModule
+addContextHandler	Reveal.cpp	/^void Reveal::addContextHandler(ContextHandler* cont) {$/;"	f	class:Reveal
+addContextHandler	Reveal.hpp	/^        void addContextHandler(ContextHandler* cont);$/;"	p	class:Reveal
+addCut	modules/RootSceneGroupModule.cpp	/^void RootSceneGroupModule::addCut(const std::string& name) {$/;"	f	class:RootSceneGroupModule
+addCut	modules/RootSceneGroupModule.hpp	/^        void addCut(const std::string&);$/;"	p	class:RootSceneGroupModule
+addCutCallback	modules/RootSceneGroupModule.hpp	/^        static void addCutCallback(Module* mod,$/;"	f	class:RootSceneGroupModule
+addDepthGroup	modules/DepthGroupModule.cpp	/^void DepthGroupModule::addDepthGroup(const string& name) {$/;"	f	class:DepthGroupModule
+addDepthGroup	modules/DepthGroupModule.hpp	/^        void addDepthGroup(const std::string& name);$/;"	p	class:DepthGroupModule
+addDepthGroupCallback	modules/DepthGroupModule.hpp	/^        static void addDepthGroupCallback(Module* mod,$/;"	f	class:DepthGroupModule
+addDepthMesh	modules/DepthGroupModule.cpp	/^void DepthGroupModule::addDepthMesh(const string& name) {$/;"	f	class:DepthGroupModule
+addDepthMesh	modules/DepthGroupModule.hpp	/^        void addDepthMesh(const std::string& name);$/;"	p	class:DepthGroupModule
+addDepthMeshCallback	modules/DepthGroupModule.hpp	/^        static void addDepthMeshCallback(Module* mod,$/;"	f	class:DepthGroupModule
+addDepthShape	modules/DepthGroupModule.cpp	/^void DepthGroupModule::addDepthShape(const string& name) {$/;"	f	class:DepthGroupModule
+addDepthShape	modules/DepthGroupModule.hpp	/^        void addDepthShape(const std::string& name);$/;"	p	class:DepthGroupModule
+addDepthShapeCallback	modules/DepthGroupModule.hpp	/^        static void addDepthShapeCallback(Module* mod, $/;"	f	class:DepthGroupModule
+addGroup	modules/RootSceneGroupModule.cpp	/^void RootSceneGroupModule::addGroup(const std::string& name) {$/;"	f	class:RootSceneGroupModule
+addGroup	modules/RootSceneGroupModule.hpp	/^        void addGroup(const std::string&);$/;"	p	class:RootSceneGroupModule
+addGroupAttributes	modules/RootSceneGroupModule.cpp	/^void RootSceneGroupModule::addGroupAttributes() {$/;"	f	class:RootSceneGroupModule
+addGroupAttributes	modules/RootSceneGroupModule.hpp	/^        void addGroupAttributes();$/;"	p	class:RootSceneGroupModule
+addGroupCallback	modules/RootSceneGroupModule.hpp	/^        static void addGroupCallback(Module* mod,$/;"	f	class:RootSceneGroupModule
+addListener	modules/Attribute.cpp	/^void Attribute::addListener(Listener* lis) {$/;"	f	class:Attribute
+addListener	modules/Attribute.hpp	/^        void addListener(Listener*);$/;"	p	class:Attribute
+addModel	modules/RootSceneGroupModule.cpp	/^void RootSceneGroupModule::addModel(const std::string& name) {$/;"	f	class:RootSceneGroupModule
+addModel	modules/RootSceneGroupModule.hpp	/^        void addModel(const std::string&);$/;"	p	class:RootSceneGroupModule
+addModelAttributes	modules/ModelModule.cpp	/^void ModelModule::addModelAttributes() {$/;"	f	class:ModelModule
+addModelAttributes	modules/ModelModule.hpp	/^        void addModelAttributes();$/;"	p	class:ModelModule
+addModelCallback	modules/RootSceneGroupModule.hpp	/^        static void addModelCallback(Module* mod,$/;"	f	class:RootSceneGroupModule
+addModuleListObserver	Reveal.cpp	/^void Reveal::addModuleListObserver(ModuleListObserver* obs) {$/;"	f	class:Reveal
+addModuleListObserver	Reveal.hpp	/^        void addModuleListObserver(ModuleListObserver* obs);$/;"	p	class:Reveal
+addModulePoint	modules/RevealedPathModule.cpp	/^void RevealedPathModule::addModulePoint(const std::string& moduleStr) {$/;"	f	class:RevealedPathModule
+addModulePoint	modules/RevealedPathModule.hpp	/^        void addModulePoint(const std::string&);$/;"	p	class:RevealedPathModule
+addModulePointCallback	modules/RevealedPathModule.hpp	/^        static void addModulePointCallback(Module* mod,$/;"	f	class:RevealedPathModule
+addNameAttribute	modules/Module.cpp	/^void Module::addNameAttribute() {$/;"	f	class:Module
+addNameAttribute	modules/Module.hpp	/^        virtual void addNameAttribute();$/;"	p	class:Module
+addPath	modules/RootSceneGroupModule.cpp	/^void RootSceneGroupModule::addPath(const std::string& name) {$/;"	f	class:RootSceneGroupModule
+addPath	modules/RootSceneGroupModule.hpp	/^        void addPath(const std::string&);$/;"	p	class:RootSceneGroupModule
+addPathCallback	modules/RootSceneGroupModule.hpp	/^        static void addPathCallback(Module* mod,$/;"	f	class:RootSceneGroupModule
+addPoint	modules/RevealedPathModule.cpp	/^void RevealedPathModule::addPoint(const float& x,   $/;"	f	class:RevealedPathModule
+addPoint	modules/RevealedPathModule.hpp	/^        void addPoint(const float& x, const float& y, const float& z);$/;"	p	class:RevealedPathModule
+addPointCallback	modules/RevealedPathModule.hpp	/^        static void addPointCallback(Module* mod, $/;"	f	class:RevealedPathModule
+addProj	modules/DepthGroupModule.cpp	/^void DepthGroupModule::addProj() {$/;"	f	class:DepthGroupModule
+addProj	modules/DepthGroupModule.hpp	/^        void addProj();$/;"	p	class:DepthGroupModule
+addProjCallback	modules/DepthGroupModule.hpp	/^        static void addProjCallback(Module* mod) {$/;"	f	class:DepthGroupModule
+addRemoveAttribute	modules/Module.cpp	/^void Module::addRemoveAttribute() {$/;"	f	class:Module
+addRemoveAttribute	modules/Module.hpp	/^        virtual void addRemoveAttribute();$/;"	p	class:Module
+addRevealedAttributes	modules/RevealedModule.cpp	/^void RevealedModule::addRevealedAttributes() {$/;"	f	class:RevealedModule
+addRevealedAttributes	modules/RevealedModule.hpp	/^        void addRevealedAttributes();$/;"	p	class:RevealedModule
+addRevealedByAttribute	modules/Module.cpp	/^void Module::addRevealedByAttribute() {$/;"	f	class:Module
+addRevealedByAttribute	modules/Module.hpp	/^        virtual void addRevealedByAttribute();$/;"	p	class:Module
+addRevealedInsideAttributes	modules/RevealedModule.cpp	/^void RevealedModule::addRevealedInsideAttributes() {$/;"	f	class:RevealedModule
+addRevealedInsideAttributes	modules/RevealedModule.hpp	/^        void addRevealedInsideAttributes();$/;"	p	class:RevealedModule
+addRevealedOutputAttributes	modules/RevealedModule.cpp	/^void RevealedModule::addRevealedOutputAttributes() {$/;"	f	class:RevealedModule
+addRevealedOutputAttributes	modules/RevealedModule.hpp	/^        void addRevealedOutputAttributes();$/;"	p	class:RevealedModule
+addShape	modules/RootSceneGroupModule.cpp	/^void RootSceneGroupModule::addShape(const std::string& name) {$/;"	f	class:RootSceneGroupModule
+addShape	modules/RootSceneGroupModule.hpp	/^        void addShape(const std::string&);$/;"	p	class:RootSceneGroupModule
+addShapeAttributes	modules/ShapeModule.cpp	/^void ShapeModule::addShapeAttributes() {$/;"	f	class:ShapeModule
+addShapeAttributes	modules/ShapeModule.hpp	/^        void addShapeAttributes();$/;"	p	class:ShapeModule
+addShapeCallback	modules/RootSceneGroupModule.hpp	/^        static void addShapeCallback(Module* mod,$/;"	f	class:RootSceneGroupModule
+addSpace	modules/SpaceModule.cpp	/^void SpacesModule::addSpace() {$/;"	f	class:SpacesModule
+addSpace	modules/SpaceModule.hpp	/^        void addSpace();$/;"	p	class:SpacesModule
+addSpaceCallback	modules/SpaceModule.hpp	/^        static void addSpaceCallback(Module* mod) {$/;"	f	class:SpacesModule
+addSpaceModule	modules/SpaceModule.cpp	/^void SpaceModule::addSpaceModule(Module* mod) {$/;"	f	class:SpaceModule
+addSpaceModule	modules/SpaceModule.hpp	/^        void addSpaceModule(Module*);$/;"	p	class:SpaceModule
+addText	modules/RootSceneGroupModule.cpp	/^void RootSceneGroupModule::addText(const std::string& name) {$/;"	f	class:RootSceneGroupModule
+addText	modules/RootSceneGroupModule.hpp	/^        void addText(const std::string&);$/;"	p	class:RootSceneGroupModule
+addTextCallback	modules/RootSceneGroupModule.hpp	/^        static void addTextCallback(Module* mod,$/;"	f	class:RootSceneGroupModule
+addTransformationAttributes	modules/Module.cpp	/^void Module::addTransformationAttributes() {$/;"	f	class:Module
+addTransformationAttributes	modules/Module.hpp	/^        virtual void addTransformationAttributes();$/;"	p	class:Module
+addUpdateObserver	Reveal.cpp	/^void Reveal::addUpdateObserver(Module* upObs) {$/;"	f	class:Reveal
+addUpdateObserver	Reveal.hpp	/^        void addUpdateObserver(Module* upObs);$/;"	p	class:Reveal
+addVertex	modules/DepthMeshModule.cpp	/^void DepthMeshModule::addVertex(const float& x,   $/;"	f	class:DepthMeshModule
+addVertex	modules/DepthMeshModule.hpp	/^        void addVertex(const float& z, const float& y, const float& x);$/;"	p	class:DepthMeshModule
+addVertexCallback	modules/DepthMeshModule.hpp	/^        static void addVertexCallback(Module* mod,$/;"	f	class:DepthMeshModule
+addVisibleAttribute	modules/Module.cpp	/^void Module::addVisibleAttribute() {$/;"	f	class:Module
+addVisibleAttribute	modules/Module.hpp	/^        virtual void addVisibleAttribute();$/;"	p	class:Module
+addVisibleFromAttribute	modules/Module.cpp	/^void Module::addVisibleFromAttribute() {$/;"	f	class:Module
+addVisibleFromAttribute	modules/Module.hpp	/^        virtual void addVisibleFromAttribute();$/;"	p	class:Module
+address	osc/oscPack/ip/IpEndpointName.h	/^    unsigned long address;$/;"	m	class:IpEndpointName
+addressPattern	osc/oscPack/osc/OscTypes.h	/^    const char *addressPattern;$/;"	m	struct:osc::BeginMessage
+addressPattern_	osc/oscPack/osc/OscReceivedElements.h	/^	const char *addressPattern_;$/;"	m	class:osc::ReceivedMessage
+animPlayCallback	modules/RevealedModule.hpp	/^        static void animPlayCallback(Module* mod, $/;"	f	class:RevealedModule
+animPosCallback	modules/RevealedModule.hpp	/^        static void animPosCallback(Module* mod, $/;"	f	class:RevealedModule
+animSpeedCallback	modules/RevealedModule.hpp	/^        static void animSpeedCallback(Module* mod, $/;"	f	class:RevealedModule
+argumentCurrent_	osc/oscPack/osc/OscOutboundPacketStream.h	/^    char *argumentCurrent_;$/;"	m	class:osc::OutboundPacketStream
+argumentPtr_	osc/oscPack/osc/OscReceivedElements.h	/^	const char *argumentPtr_;$/;"	m	class:osc::ReceivedMessageArgument
+arguments_	osc/oscPack/osc/OscReceivedElements.h	/^    const char *arguments_;$/;"	m	class:osc::ReceivedMessage
+askQuit	Reveal.cpp	/^void Reveal::askQuit() {$/;"	f	class:Reveal
+askQuit	Reveal.hpp	/^        void askQuit();$/;"	p	class:Reveal
+attachProj	modules/DepthCamModule.cpp	/^void DepthCamModule::attachProj(ProjectorModule* proj) {$/;"	f	class:DepthCamModule
+attachProj	modules/DepthCamModule.hpp	/^        void attachProj(ProjectorModule*);$/;"	p	class:DepthCamModule
+attachToCam	modules/ProjectorModule.cpp	/^void ProjectorModule::attachToCam(const string& camName) {$/;"	f	class:ProjectorModule
+attachToCam	modules/ProjectorModule.hpp	/^        void attachToCam(const std::string& camName);$/;"	p	class:ProjectorModule
+attachToCamCallback	modules/ProjectorModule.hpp	/^        static void attachToCamCallback(Module* mod, $/;"	f	class:ProjectorModule
+breakEvent_	osc/oscPack/ip/win32/UdpSocket.cpp	/^	HANDLE breakEvent_;$/;"	m	class:SocketReceiveMultiplexer::Implementation	file:
+breakPipe_	osc/oscPack/ip/posix/UdpSocket.cpp	/^	int breakPipe_[2]; \/\/ [0] is the reader descriptor and [1] the writer$/;"	m	class:SocketReceiveMultiplexer::Implementation	file:
+break_	osc/oscPack/ip/posix/UdpSocket.cpp	/^	volatile bool break_;$/;"	m	class:SocketReceiveMultiplexer::Implementation	file:
+break_	osc/oscPack/ip/win32/UdpSocket.cpp	/^	volatile bool break_;$/;"	m	class:SocketReceiveMultiplexer::Implementation	file:
+buf	osc/ringbuffer.c	/^    char	*buf;$/;"	m	struct:__anon7	file:
+buf	osc/ringbuffer.c	/^    char *buf;$/;"	m	struct:__anon6	file:
+buf	osc/ringbuffer.h	/^    char	*buf;$/;"	m	struct:__anon2
+buf	osc/ringbuffer.h	/^    char *buf;$/;"	m	struct:__anon1
+calculationCenterOfMarker	modules/DepthCamModule.cpp	/^cv::Point DepthCamModule::calculationCenterOfMarker(s_markerAndTime& marker){$/;"	f	class:DepthCamModule
+calculationCenterOfMarker	modules/DepthCamModule.hpp	/^        cv::Point calculationCenterOfMarker(s_markerAndTime& marker);$/;"	p	class:DepthCamModule
+calibrate	modules/DepthCamModule.cpp	/^void DepthCamModule::calibrate() {$/;"	f	class:DepthCamModule
+calibrate	modules/DepthCamModule.hpp	/^        void calibrate();$/;"	p	class:DepthCamModule
+calibrate	modules/ProjectorModule.cpp	/^void ProjectorModule::calibrate(const std::string& camName) {$/;"	f	class:ProjectorModule
+calibrate	modules/ProjectorModule.hpp	/^        void calibrate(const std::string& camName);$/;"	p	class:ProjectorModule
+calibrateCallback	modules/ProjectorModule.hpp	/^        static void calibrateCallback(Module* mod, $/;"	f	class:ProjectorModule
+calibrationCallback	modules/DepthCamModule.hpp	/^        static void calibrationCallback(Module* mod) {$/;"	f	class:DepthCamModule
+captureBackground	modules/DepthCamModule.cpp	/^void DepthCamModule::captureBackground() {$/;"	f	class:DepthCamModule
+captureBackground	modules/DepthCamModule.hpp	/^        void captureBackground();$/;"	p	class:DepthCamModule
+captureBackgroundCallback	modules/DepthCamModule.hpp	/^        static void captureBackgroundCallback(Module* mod,$/;"	f	class:DepthCamModule
+cbAction	gui/AttributeWidget.cpp	/^void AttributeWidget::cbAction(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbAction	gui/AttributeWidget.hpp	/^        void cbAction(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbAddListener	gui/AttributeWidget.cpp	/^void AttributeWidget::cbAddListener(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbAddListener	gui/AttributeWidget.hpp	/^        void cbAddListener(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbCalib	modules/DepthCamModule.cpp	/^static void cbCalib(int c, void* mod) {$/;"	f	file:
+cbCalib	modules/ProjectorModule.cpp	/^static void cbCalib(int c, void* mod) {$/;"	f	file:
+cbChecks	gui/AttributeWidget.cpp	/^void AttributeWidget::cbChecks(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbChecks	gui/AttributeWidget.hpp	/^        void cbChecks(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbChoices	gui/AttributeWidget.cpp	/^void AttributeWidget::cbChoices(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbChoices	gui/AttributeWidget.hpp	/^        void cbChoices(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbFileOpen	gui/AttributeWidget.cpp	/^void AttributeWidget::cbFileOpen(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbFileOpen	gui/AttributeWidget.hpp	/^        void cbFileOpen(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbFileSave	gui/AttributeWidget.cpp	/^void AttributeWidget::cbFileSave(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbFileSave	gui/AttributeWidget.hpp	/^        void cbFileSave(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbFloats	gui/AttributeWidget.cpp	/^void AttributeWidget::cbFloats(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbFloats	gui/AttributeWidget.hpp	/^        void cbFloats(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbFolderOpen	gui/AttributeWidget.cpp	/^void AttributeWidget::cbFolderOpen(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbFolderOpen	gui/AttributeWidget.hpp	/^        void cbFolderOpen(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbInts	gui/AttributeWidget.cpp	/^void AttributeWidget::cbInts(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbInts	gui/AttributeWidget.hpp	/^        void cbInts(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbMarkerPosY	modules/DepthCamModule.cpp	/^static void cbMarkerPosY(int y, void* mod) {$/;"	f	file:
+cbMarkerRotX	modules/DepthCamModule.cpp	/^static void cbMarkerRotX(int x, void* mod) {$/;"	f	file:
+cbMarkerRotY	modules/DepthCamModule.cpp	/^static void cbMarkerRotY(int y, void* mod) {$/;"	f	file:
+cbOpen	gui/MainWindow.cpp	/^void MainWindow::cbOpen() {$/;"	f	class:MainWindow
+cbOpen	gui/MainWindow.hpp	/^        void cbOpen();$/;"	p	class:MainWindow
+cbParams	gui/ListenerWidget.cpp	/^void ListenerWidget::cbParams(Fl_Widget*) {$/;"	f	class:ListenerWidget
+cbParams	gui/ListenerWidget.hpp	/^        void cbParams(Fl_Widget*);$/;"	p	class:ListenerWidget
+cbPatternBrightness	modules/ProjectorModule.cpp	/^static void cbPatternBrightness(int b, void* mod) {$/;"	f	file:
+cbPatternPosX	modules/ProjectorModule.cpp	/^static void cbPatternPosX(int x, void* mod) {$/;"	f	file:
+cbPatternPosY	modules/ProjectorModule.cpp	/^static void cbPatternPosY(int y, void* mod) {$/;"	f	file:
+cbPatternSquareWidth	modules/ProjectorModule.cpp	/^static void cbPatternSquareWidth(int w, void* mod) {$/;"	f	file:
+cbPatternThresh	modules/ProjectorModule.cpp	/^static void cbPatternThresh(int x, void* mod) {$/;"	f	file:
+cbQuit	gui/MainWindow.cpp	/^void MainWindow::cbQuit() {$/;"	f	class:MainWindow
+cbQuit	gui/MainWindow.hpp	/^        void cbQuit();$/;"	p	class:MainWindow
+cbRemove	gui/ListenerWidget.cpp	/^void ListenerWidget::cbRemove(Fl_Widget*) {$/;"	f	class:ListenerWidget
+cbRemove	gui/ListenerWidget.hpp	/^        void cbRemove(Fl_Widget*);$/;"	p	class:ListenerWidget
+cbSave	gui/MainWindow.cpp	/^void MainWindow::cbSave() {$/;"	f	class:MainWindow
+cbSave	gui/MainWindow.hpp	/^        void cbSave();$/;"	p	class:MainWindow
+cbSaveAs	gui/MainWindow.cpp	/^void MainWindow::cbSaveAs() {$/;"	f	class:MainWindow
+cbSaveAs	gui/MainWindow.hpp	/^        void cbSaveAs();$/;"	p	class:MainWindow
+cbShowListeners	gui/AttributeWidget.cpp	/^void AttributeWidget::cbShowListeners(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbShowListeners	gui/AttributeWidget.hpp	/^        void cbShowListeners(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbStrings	gui/AttributeWidget.cpp	/^void AttributeWidget::cbStrings(Fl_Widget*) {$/;"	f	class:AttributeWidget
+cbStrings	gui/AttributeWidget.hpp	/^        void cbStrings(Fl_Widget*);$/;"	p	class:AttributeWidget
+cbTree	gui/MainWindow.cpp	/^void MainWindow::cbTree(Fl_Widget* w) {$/;"	f	class:MainWindow
+cbTree	gui/MainWindow.hpp	/^        void cbTree(Fl_Widget*);$/;"	p	class:MainWindow
+clearListeners	modules/Attribute.cpp	/^void Attribute::clearListeners() {$/;"	f	class:Attribute
+clearListeners	modules/Attribute.hpp	/^        void clearListeners();$/;"	p	class:Attribute
+clearPoints	modules/RevealedPathModule.cpp	/^void RevealedPathModule::clearPoints() {$/;"	f	class:RevealedPathModule
+clearPoints	modules/RevealedPathModule.hpp	/^        void clearPoints();$/;"	p	class:RevealedPathModule
+clearPointsCallback	modules/RevealedPathModule.hpp	/^        static void clearPointsCallback(Module* mod) {$/;"	f	class:RevealedPathModule
+clearVertices	modules/DepthMeshModule.cpp	/^void DepthMeshModule::clearVertices() {$/;"	f	class:DepthMeshModule
+clearVertices	modules/DepthMeshModule.hpp	/^        void clearVertices();$/;"	p	class:DepthMeshModule
+clearVerticesCallback	modules/DepthMeshModule.hpp	/^        static void clearVerticesCallback(Module* mod) {$/;"	f	class:DepthMeshModule
+closeDevice	modules/DepthCamModule.cpp	/^void DepthCamModule::closeDevice() {$/;"	f	class:DepthCamModule
+closeDevice	modules/DepthCamModule.hpp	/^        void closeDevice();$/;"	p	class:DepthCamModule
+colorCallback	modules/RevealedModule.hpp	/^        static void colorCallback(Module* mod, $/;"	f	class:RevealedModule
+colorCamOpenCV	modules/DepthCamModule.hpp	/^        void colorCamOpenCV(void);$/;"	p	class:DepthCamModule
+compare	modules/ModelModule.hpp	/^            bool compare(ModelVertex& v) {$/;"	f	struct:ModelModule::ModelVertex
+computeNbPixPerRow	modules/RevealedCutModule.cpp	/^int CutWindow::computeNbPixPerRow(const int& srcW, const int& srcH) {$/;"	f	class:CutWindow
+computeNbPixPerRow	modules/RevealedCutModule.hpp	/^        int computeNbPixPerRow(const int& srcW, const int& srcH);$/;"	p	class:CutWindow
+connectedAddr_	osc/oscPack/ip/posix/UdpSocket.cpp	/^	struct sockaddr_in connectedAddr_;$/;"	m	class:UdpSocket::Implementation	typeref:struct:UdpSocket::Implementation::sockaddr_in	file:
+connectedAddr_	osc/oscPack/ip/win32/UdpSocket.cpp	/^	struct sockaddr_in connectedAddr_;$/;"	m	class:UdpSocket::Implementation	typeref:struct:UdpSocket::Implementation::sockaddr_in	file:
+const_iterator	osc/oscPack/osc/OscReceivedElements.h	/^    typedef ReceivedBundleElementIterator const_iterator;$/;"	t	class:osc::ReceivedBundle
+const_iterator	osc/oscPack/osc/OscReceivedElements.h	/^    typedef ReceivedMessageArgumentIterator const_iterator;$/;"	t	class:osc::ReceivedMessage
+contents_	osc/oscPack/osc/OscReceivedElements.h	/^    const char *contents_;$/;"	m	class:osc::ReceivedPacket
+contourThresholdCallback	modules/DepthCamModule.hpp	/^        static void contourThresholdCallback(Module* mod,$/;"	f	class:DepthCamModule
+corners	modules/DepthCamModule.hpp	/^    std::vector<cv::Point2f> corners;$/;"	m	struct:s_markerAndTime
+createListener	Reveal.cpp	/^Listener* Reveal::createListener(const std::string& typeStr) {$/;"	f	class:Reveal
+createListener	Reveal.hpp	/^        Listener* createListener(const std::string& typeStr);$/;"	p	class:Reveal
+createMatColor	modules/DepthCamModule.cpp	/^bool DepthCamModule::createMatColor(){$/;"	f	class:DepthCamModule
+createMatColor	modules/DepthCamModule.hpp	/^        bool createMatColor();$/;"	p	class:DepthCamModule
+createMatDepth	modules/DepthCamModule.cpp	/^bool DepthCamModule::createMatDepth(){$/;"	f	class:DepthCamModule
+createMatDepth	modules/DepthCamModule.hpp	/^        bool createMatDepth();$/;"	p	class:DepthCamModule
+createMatDepthAndColor	modules/DepthCamModule.cpp	/^bool DepthCamModule::createMatDepthAndColor(){$/;"	f	class:DepthCamModule
+createMatDepthAndColor	modules/DepthCamModule.hpp	/^        bool createMatDepthAndColor();$/;"	p	class:DepthCamModule
+createModule	Reveal.cpp	/^Module* Reveal::createModule(const std::string& typeStr) {$/;"	f	class:Reveal
+createModule	Reveal.hpp	/^        Module* createModule(const std::string& typeStr);$/;"	p	class:Reveal
+createProgram	Reveal.cpp	/^GLuint Reveal::createProgram(const char* vertSource, const char* fragSource) {$/;"	f	class:Reveal
+createProgram	Reveal.hpp	/^        GLuint createProgram(const char* vertSource, const char* fragSource);$/;"	p	class:Reveal
+createRTT	modules/ProjectorModule.cpp	/^void ProjectorModule::createRTT(GLuint& tex, GLuint& fbo) {$/;"	f	class:ProjectorModule
+createRTT	modules/ProjectorModule.hpp	/^        void createRTT(GLuint& tex, GLuint& fbo);$/;"	p	class:ProjectorModule
+cstr_compare	osc/oscPack/osc/MessageMappingOscPacketListener.h	/^    struct cstr_compare{$/;"	s	class:osc::MessageMappingOscPacketListener
+cursCallback	modules/DepthCamModule.hpp	/^        static void cursCallback(Module* mod, const std::vector<float>& vals) {}$/;"	f	class:DepthCamModule
+data	osc/oscPack/osc/OscTypes.h	/^    const void* data;$/;"	m	struct:osc::Blob
+data_	osc/oscPack/osc/OscOutboundPacketStream.h	/^    char *data_;$/;"	m	class:osc::OutboundPacketStream
+deactivateColor	modules/DepthCamModule.cpp	/^void DepthCamModule::deactivateColor() {$/;"	f	class:DepthCamModule
+deactivateColor	modules/DepthCamModule.hpp	/^        void deactivateColor();$/;"	p	class:DepthCamModule
+debugMarkers	modules/DepthCamModule.cpp	/^void DepthCamModule::debugMarkers(const bool& val) {$/;"	f	class:DepthCamModule
+debugMarkers	modules/DepthCamModule.hpp	/^        void debugMarkers(const bool& val);$/;"	p	class:DepthCamModule
+debugMarkersCallback	modules/DepthCamModule.hpp	/^        static void debugMarkersCallback(Module* mod,$/;"	f	class:DepthCamModule
+deleteCallback	modules/SceneGroupModule.hpp	/^        static void deleteCallback(Module* mod) {$/;"	f	class:SceneGroupModule
+deleteChildren	modules/GroupModule.cpp	/^void GroupModule::deleteChildren() {$/;"	f	class:GroupModule
+deleteChildren	modules/GroupModule.hpp	/^        void deleteChildren();$/;"	p	class:GroupModule
+deleteListener	Reveal.cpp	/^void Reveal::deleteListener(Listener* lis) {$/;"	f	class:Reveal
+deleteListener	Reveal.hpp	/^        void deleteListener(Listener*);$/;"	p	class:Reveal
+deleteListener	modules/Listener.cpp	/^void Listener::deleteListener() {$/;"	f	class:Listener
+deleteListener	modules/Listener.hpp	/^        void deleteListener();$/;"	p	class:Listener
+deleteModule	Reveal.cpp	/^void Reveal::deleteModule(Module* mod) {$/;"	f	class:Reveal
+deleteModule	Reveal.hpp	/^        void deleteModule(Module*);$/;"	p	class:Reveal
+deleteModule	modules/DepthCamModule.cpp	/^void DepthCamModule::deleteModule() {$/;"	f	class:DepthCamModule
+deleteModule	modules/DepthCamModule.hpp	/^        void deleteModule();$/;"	p	class:DepthCamModule
+deleteModule	modules/DepthGroupModule.cpp	/^void DepthGroupModule::deleteModule() {$/;"	f	class:DepthGroupModule
+deleteModule	modules/DepthGroupModule.hpp	/^        void deleteModule();$/;"	p	class:DepthGroupModule
+deleteModule	modules/DepthModule.cpp	/^void DepthModule::deleteModule() {$/;"	f	class:DepthModule
+deleteModule	modules/DepthModule.hpp	/^        void deleteModule();$/;"	p	class:DepthModule
+deleteModule	modules/GeomModule.cpp	/^void GeomModule::deleteModule() {$/;"	f	class:GeomModule
+deleteModule	modules/GeomModule.hpp	/^        void deleteModule();$/;"	p	class:GeomModule
+deleteModule	modules/GroupModule.cpp	/^void GroupModule::deleteModule() {$/;"	f	class:GroupModule
+deleteModule	modules/GroupModule.hpp	/^        void deleteModule();$/;"	p	class:GroupModule
+deleteModule	modules/Module.cpp	/^void Module::deleteModule() {$/;"	f	class:Module
+deleteModule	modules/Module.hpp	/^        virtual void deleteModule();$/;"	p	class:Module
+deleteModule	modules/ProjectorModule.cpp	/^void ProjectorModule::deleteModule() {$/;"	f	class:ProjectorModule
+deleteModule	modules/ProjectorModule.hpp	/^        void deleteModule();$/;"	p	class:ProjectorModule
+deleteModule	modules/RevealedModule.cpp	/^void RevealedModule::deleteModule() {$/;"	f	class:RevealedModule
+deleteModule	modules/RevealedModule.hpp	/^        void deleteModule();$/;"	p	class:RevealedModule
+delimitation	modules/DepthCamModule.cpp	/^void DepthCamModule::delimitation(cv::Mat& img) {$/;"	f	class:DepthCamModule
+delimitation	modules/DepthCamModule.hpp	/^        void delimitation(cv::Mat& img);$/;"	p	class:DepthCamModule
+detachProj	modules/DepthCamModule.cpp	/^void DepthCamModule::detachProj(ProjectorModule* proj) {$/;"	f	class:DepthCamModule
+detachProj	modules/DepthCamModule.hpp	/^        void detachProj(ProjectorModule*);$/;"	p	class:DepthCamModule
+detectMarkers	modules/DepthCamModule.cpp	/^void DepthCamModule::detectMarkers() {$/;"	f	class:DepthCamModule
+detectMarkers	modules/DepthCamModule.hpp	/^        void detectMarkers();$/;"	p	class:DepthCamModule
+detected	modules/DepthCamModule.hpp	/^    bool detected;$/;"	m	struct:s_markerAndTime
+detection	modules/DepthCamModule.hpp	/^    time_t detection;$/;"	m	struct:s_markerAndTime
+deviceCallback	modules/DepthCamModule.hpp	/^        static void deviceCallback(Module* mod,$/;"	f	class:DepthCamModule
+dimensionsCallback	modules/RevealedTextModule.hpp	/^        static void dimensionsCallback(Module* mod, $/;"	f	class:RevealedTextModule
+dimensionsCallback	modules/ShapeModule.hpp	/^        static void dimensionsCallback(Module* mod, $/;"	f	class:ShapeModule
+displayAttributes	gui/MainWindow.cpp	/^void MainWindow::displayAttributes(ModuleWidget* mod) {$/;"	f	class:MainWindow
+displayAttributes	gui/MainWindow.hpp	/^        void displayAttributes(ModuleWidget*);$/;"	p	class:MainWindow
+draw	geoms/Geometry.cpp	/^void Geometry::draw(const int& contextID,$/;"	f	class:Geometry
+draw	geoms/Geometry.hpp	/^        virtual void draw(const int& contextID,$/;"	p	class:Geometry
+draw	modules/DepthCamModule.cpp	/^void DepthCamModule::draw(const int& contextID,$/;"	f	class:DepthCamModule
+draw	modules/DepthCamModule.hpp	/^        virtual void draw(const int& contextID,$/;"	p	class:DepthCamModule
+draw	modules/DepthModule.cpp	/^void DepthModule::draw(const int& contextID,$/;"	f	class:DepthModule
+draw	modules/DepthModule.hpp	/^        virtual void draw(const int& contextID,$/;"	p	class:DepthModule
+draw	modules/GeomModule.cpp	/^void GeomModule::draw(const int& contextID,$/;"	f	class:GeomModule
+draw	modules/GeomModule.hpp	/^        virtual void draw(const int& contextID,$/;"	p	class:GeomModule
+draw	modules/GroupModule.cpp	/^void GroupModule::draw() {$/;"	f	class:GroupModule
+draw	modules/GroupModule.hpp	/^        virtual void draw();$/;"	p	class:GroupModule
+draw	modules/Module.hpp	/^        virtual void draw(){}$/;"	f	class:Module
+draw	modules/PreviewModule.cpp	/^void PreviewModule::draw() {$/;"	f	class:PreviewModule
+draw	modules/PreviewModule.hpp	/^        virtual void draw();$/;"	p	class:PreviewModule
+draw	modules/ProjectorModule.cpp	/^void ProjectorModule::draw() {$/;"	f	class:ProjectorModule
+draw	modules/ProjectorModule.hpp	/^        virtual void draw();$/;"	p	class:ProjectorModule
+draw	modules/RevealedCutModule.cpp	/^void RevealedCutModule::draw(const int& contextID, $/;"	f	class:RevealedCutModule
+draw	modules/RevealedCutModule.hpp	/^        void draw(const int& contextID,$/;"	p	class:RevealedCutModule
+draw	modules/RevealedModelModule.cpp	/^void RevealedModelModule::draw(const int& contextID, $/;"	f	class:RevealedModelModule
+draw	modules/RevealedModelModule.hpp	/^        void draw(const int& contextID,$/;"	p	class:RevealedModelModule
+draw	modules/RevealedModule.cpp	/^void RevealedModule::draw(const int& contextID,$/;"	f	class:RevealedModule
+draw	modules/RevealedModule.hpp	/^        void draw(const int& contextID,$/;"	p	class:RevealedModule
+draw	modules/SpaceModule.cpp	/^void SpaceModule::draw() {$/;"	f	class:SpaceModule
+draw	modules/SpaceModule.hpp	/^        virtual void draw();$/;"	p	class:SpaceModule
+drawDelaunay	modules/DepthCamModule.cpp	/^void DepthCamModule::drawDelaunay(cv::Mat& img, cv::Subdiv2D& subdiv, cv::Scalar delaunayColor ){$/;"	f	class:DepthCamModule
+drawDelaunay	modules/DepthCamModule.hpp	/^        void drawDelaunay(cv::Mat& img, cv::Subdiv2D& subdiv, $/;"	p	class:DepthCamModule
+drawDirect	geoms/Geometry.cpp	/^void Geometry::drawDirect(const int& contextID) {$/;"	f	class:Geometry
+drawDirect	geoms/Geometry.hpp	/^        virtual void drawDirect(const int& contextID);$/;"	p	class:Geometry
+drawVoronoi	modules/DepthCamModule.cpp	/^void DepthCamModule::drawVoronoi( cv::Mat& img, cv::Subdiv2D& subdiv) {$/;"	f	class:DepthCamModule
+drawVoronoi	modules/DepthCamModule.hpp	/^        void drawVoronoi(cv::Mat& img, cv::Subdiv2D& subdiv);$/;"	p	class:DepthCamModule
+draw_point	modules/DepthCamModule.cpp	/^void DepthCamModule::draw_point(cv::Mat& img, cv::Point2f fp){$/;"	f	class:DepthCamModule
+draw_point	modules/DepthCamModule.hpp	/^        void draw_point(cv::Mat& img, cv::Point2f fp);$/;"	p	class:DepthCamModule
+edgesCallback	modules/RevealedPathModule.hpp	/^        static void edgesCallback(Module* mod, $/;"	f	class:RevealedPathModule
+editAttributes	modules/Module.hpp	/^        inline std::vector<Attribute*>& editAttributes() { $/;"	f	class:Module
+editCompoSizes	geoms/Geometry.hpp	/^        std::vector<int>& editCompoSizes(){return m_compoSizes;}$/;"	f	class:Geometry
+editIndexBufferData	geoms/Geometry.hpp	/^        std::vector<GLuint>& editIndexBufferData(){return m_indexBufferData;}$/;"	f	class:Geometry
+editListenerType	modules/Listener.hpp	/^        inline std::string& editListenerType(){return m_listenerType;}$/;"	f	class:Listener
+editListeners	modules/Attribute.hpp	/^        inline std::vector<Listener*>& editListeners(){return m_listeners;}$/;"	f	class:Attribute
+editParameters	modules/Listener.hpp	/^        inline std::vector<std::string>& editParameters(){return m_parameters;}$/;"	f	class:Listener
+editPos	modules/RevealedPathModule.hpp	/^        inline glm::vec4& editPos(){return m_point;}$/;"	f	class:PathPoint
+editRegisteredOutputDepthCams	Reveal.hpp	/^        inline std::vector<DepthCamModule*>& editRegisteredOutputDepthCams() {$/;"	f	class:Reveal
+editRegisteredOutputRevealed	Reveal.hpp	/^        inline std::vector<RevealedModule*>& editRegisteredOutputRevealed() {$/;"	f	class:Reveal
+editStringValuesChoices	modules/Attribute.hpp	/^                                        editStringValuesChoices() {$/;"	f	class:Attribute
+editValueLabels	modules/Attribute.hpp	/^        inline std::vector<std::string>& editValueLabels() {$/;"	f	class:Attribute
+editValuesMax	modules/Attribute.hpp	/^        inline std::vector<float>& editValuesMax() {return m_valuesMax;}$/;"	f	class:Attribute
+editValuesMin	modules/Attribute.hpp	/^        inline std::vector<float>& editValuesMin() {return m_valuesMin;}$/;"	f	class:Attribute
+editVertexBufferData	geoms/Geometry.hpp	/^        std::vector<GLfloat>& editVertexBufferData(){return m_vertexBufferData;}$/;"	f	class:Geometry
+editWindowList	modules/RevealedCutModule.hpp	/^        std::vector<CutWindow*>& editWindowList(){return m_windowList;}$/;"	f	class:CutWindowsManager
+elementCount_	osc/oscPack/osc/OscReceivedElements.h	/^    uint32 elementCount_;$/;"	m	class:osc::ReceivedBundle
+elementSizePtr_	osc/oscPack/osc/OscOutboundPacketStream.h	/^    uint32 *elementSizePtr_;$/;"	m	class:osc::OutboundPacketStream
+end_	osc/oscPack/osc/OscOutboundPacketStream.h	/^    char *end_;$/;"	m	class:osc::OutboundPacketStream
+end_	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentIterator p_, end_;$/;"	m	class:osc::ReceivedMessageArgumentStream
+end_	osc/oscPack/osc/OscReceivedElements.h	/^    const char *end_;$/;"	m	class:osc::ReceivedBundle
+extractOutputValue	modules/ProjectorModule.cpp	/^void ProjectorModule::extractOutputValue(const unsigned int& offset,$/;"	f	class:ProjectorModule
+extractOutputValue	modules/ProjectorModule.hpp	/^        void extractOutputValue(const unsigned int& offset, $/;"	p	class:ProjectorModule
+eyePositionCallback	modules/PreviewModule.hpp	/^        static void eyePositionCallback(Module* mod, $/;"	f	class:PreviewModule
+fillGroupWithAttributes	gui/ModuleWidget.cpp	/^void ModuleWidget::fillGroupWithAttributes(Fl_Pack* group) {$/;"	f	class:ModuleWidget
+fillGroupWithAttributes	gui/ModuleWidget.hpp	/^        void fillGroupWithAttributes(Fl_Pack*);$/;"	p	class:ModuleWidget
+filterCallback	modules/DepthCamModule.hpp	/^        static void filterCallback(Module* mod,$/;"	f	class:DepthCamModule
+filterMarkers	modules/DepthCamModule.cpp	/^void DepthCamModule::filterMarkers(vector<vector<cv::Point2f> >& cor,$/;"	f	class:DepthCamModule
+filterMarkers	modules/DepthCamModule.hpp	/^        void filterMarkers(std::vector<std::vector<cv::Point2f> >& cor,$/;"	p	class:DepthCamModule
+findAttribute	Reveal.cpp	/^Attribute* Reveal::findAttribute(const std::string& fullName) {$/;"	f	class:Reveal
+findAttribute	Reveal.hpp	/^        Attribute* findAttribute(const std::string& fullName);$/;"	p	class:Reveal
+findModule	Reveal.cpp	/^Module* Reveal::findModule(const std::string& fullName) {$/;"	f	class:Reveal
+findModule	Reveal.hpp	/^        Module* findModule(const std::string& fullName);$/;"	p	class:Reveal
+fontSizeCallback	modules/RevealedTextModule.hpp	/^        static void fontSizeCallback(Module* mod, $/;"	f	class:RevealedTextModule
+framebufferSizeCallback	modules/ProjectorModule.hpp	/^        static void framebufferSizeCallback(GLFWwindow* win, int w, int h) {$/;"	f	class:ProjectorModule
+fullscreenMonitor	modules/ProjectorModule.cpp	/^void ProjectorModule::fullscreenMonitor(const std::string& monitorName) {$/;"	f	class:ProjectorModule
+fullscreenMonitor	modules/ProjectorModule.hpp	/^        void fullscreenMonitor(const std::string& monitor);$/;"	p	class:ProjectorModule
+fullscreenMonitorCallback	modules/ProjectorModule.hpp	/^        static void fullscreenMonitorCallback(Module* mod, $/;"	f	class:ProjectorModule
+function_map_type	osc/oscPack/osc/MessageMappingOscPacketListener.h	/^    typedef std::map<const char*, function_type, cstr_compare> function_map_type;$/;"	t	class:osc::MessageMappingOscPacketListener
+function_type	osc/oscPack/osc/MessageMappingOscPacketListener.h	/^    typedef void (T::*function_type)(const osc::ReceivedMessage&, const IpEndpointName&);$/;"	t	class:osc::MessageMappingOscPacketListener
+functions_	osc/oscPack/osc/MessageMappingOscPacketListener.h	/^    function_map_type functions_;$/;"	m	class:osc::MessageMappingOscPacketListener
+generateLayers	modules/RevealedModelModule.cpp	/^void RevealedModelModule::generateLayers() {$/;"	f	class:RevealedModelModule
+generateLayers	modules/RevealedModelModule.hpp	/^        void generateLayers();$/;"	p	class:RevealedModelModule
+generateLayersCallback	modules/RevealedModelModule.hpp	/^        static void generateLayersCallback(Module* mod) {$/;"	f	class:RevealedModelModule
+generateReduction	modules/RevealedModule.cpp	/^void RevealedModule::generateReduction() {$/;"	f	class:RevealedModule
+generateReduction	modules/RevealedModule.hpp	/^        virtual void generateReduction();$/;"	p	class:RevealedModule
+generateReductionCallback	modules/RevealedModule.hpp	/^        static void generateReductionCallback(Module* mod) {$/;"	f	class:RevealedModule
+getAbsPathFromRev	modules/Attribute.cpp	/^void Attribute::getAbsPathFromRev(const string& rel, $/;"	f	class:Attribute
+getAbsPathFromRev	modules/Attribute.hpp	/^        void getAbsPathFromRev(const std::string& rel, $/;"	p	class:Attribute
+getAccessibility	modules/Attribute.hpp	/^        ACCESSIBILITY getAccessibility(){return m_accessibility;}$/;"	f	class:Attribute
+getAttribute	modules/Module.hpp	/^        inline Attribute* getAttribute(const std::string& attr) { $/;"	f	class:Module
+getAttribute	modules/Module.hpp	/^        inline Attribute* getAttribute(const unsigned int& attr) { $/;"	f	class:Module
+getBool	modules/Attribute.hpp	/^        bool getBool(const unsigned int& i) {return m_boolValues[i];}$/;"	f	class:Attribute
+getChildID	modules/Module.hpp	/^        const unsigned int& getChildID(){return m_childID;}$/;"	f	class:Module
+getColorFrame	modules/DepthCamModule.hpp	/^        inline openni::VideoFrameRef getColorFrame(){return m_colorFrame;}$/;"	f	class:DepthCamModule
+getContextHandlerID	modules/ContextHandler.hpp	/^        const int& getContextHandlerID(){return m_contextHandlerID;}$/;"	f	class:ContextHandler
+getCurrentFile	Reveal.hpp	/^        const std::string& getCurrentFile(){return m_currentFile;}$/;"	f	class:Reveal
+getDepth	modules/Module.hpp	/^        inline const unsigned int& getDepth(){return m_depth;}$/;"	f	class:Module
+getDepthCamModule	modules/SpaceModule.cpp	/^DepthCamModule* SpaceModule::getDepthCamModule(const std::string& name) {$/;"	f	class:SpaceModule
+getDepthCamModule	modules/SpaceModule.hpp	/^        DepthCamModule* getDepthCamModule(const std::string& name);$/;"	p	class:SpaceModule
+getDepthCamModule	modules/SpaceModule.hpp	/^        inline DepthCamModule* getDepthCamModule(const unsigned int& mod) {$/;"	f	class:SpaceModule
+getDepthFrame	modules/DepthCamModule.hpp	/^        inline openni::VideoFrameRef getDepthFrame(){return m_depthFrame;}$/;"	f	class:DepthCamModule
+getDepthID	modules/DepthModule.hpp	/^        const unsigned int& getDepthID(){return m_depthID;}$/;"	f	class:DepthModule
+getDepthModuleFromID	modules/SpaceModule.hpp	/^        DepthModule* getDepthModuleFromID(const unsigned int& id){ $/;"	f	class:SpaceModule
+getDepthStream	modules/DepthCamModule.hpp	/^        inline openni::VideoStream& getDepthStream(){return m_depth;}$/;"	f	class:DepthCamModule
+getDeviceID	modules/DepthCamModule.hpp	/^        inline const std::string& getDeviceID(){return m_deviceID;}$/;"	f	class:DepthCamModule
+getFile	modules/Attribute.hpp	/^        const std::string& getFile() {return m_stringValues[0];}$/;"	f	class:Attribute
+getFloat	modules/Attribute.hpp	/^        const float& getFloat(const unsigned int& f) {return m_floatValues[f];}$/;"	f	class:Attribute
+getFloats	modules/Attribute.hpp	/^        const std::vector<float>& getFloats(){return m_floatValues;}$/;"	f	class:Attribute
+getFrames	modules/DepthCamModule.cpp	/^bool DepthCamModule::getFrames() {$/;"	f	class:DepthCamModule
+getFrames	modules/DepthCamModule.hpp	/^        bool getFrames();$/;"	p	class:DepthCamModule
+getFullName	modules/Attribute.hpp	/^        inline const std::string& getFullName(){return m_fullName;}$/;"	f	class:Attribute
+getFullName	modules/Module.hpp	/^        inline const std::string& getFullName(){return m_fullName;}$/;"	f	class:Module
+getGeom	Reveal.hpp	/^        Geometry* getGeom(const GEOM_ID& geomStr) { $/;"	f	class:Reveal
+getGeom	modules/SpaceModule.hpp	/^        Geometry* getGeom(const Reveal::GEOM_ID& geomStr) { $/;"	f	class:SpaceModule
+getGeomID	geoms/Geometry.hpp	/^        inline const Reveal::GEOM_ID& getGeomID() {return m_geomID;}$/;"	f	class:Geometry
+getGeomID	modules/GeomModule.hpp	/^        virtual const unsigned int& getGeomID(){return m_geomID;}$/;"	f	class:GeomModule
+getGeoms	Reveal.hpp	/^        const std::vector<Geometry*>& getGeoms(){return m_geoms;}$/;"	f	class:Reveal
+getGeoms	modules/SpaceModule.hpp	/^        const std::vector<Geometry*>& getGeoms(){return m_geoms;}$/;"	f	class:SpaceModule
+getHeight	modules/RevealedCutModule.hpp	/^        const int& getHeight(){return m_height;} $/;"	f	class:CutWindow
+getHorizontalFOV	modules/DepthCamModule.hpp	/^        inline double& getHorizontalFOV(){return m_horizontalFOV;}$/;"	f	class:DepthCamModule
+getID	modules/Listener.hpp	/^        inline const int& getID(){return m_listenerID;}$/;"	f	class:Listener
+getInstance	Reveal.cpp	/^Reveal* Reveal::getInstance() {$/;"	f	class:Reveal
+getInstance	Reveal.hpp	/^        static Reveal* getInstance();$/;"	p	class:Reveal
+getInstance	gui/MainWindow.cpp	/^MainWindow* MainWindow::getInstance() {$/;"	f	class:MainWindow
+getInstance	gui/MainWindow.hpp	/^        static MainWindow* getInstance();$/;"	p	class:MainWindow
+getInstance	modules/RevealedCutModule.cpp	/^CutWindowsManager* CutWindowsManager::getInstance() {$/;"	f	class:CutWindowsManager
+getInstance	modules/RevealedCutModule.hpp	/^        static CutWindowsManager* getInstance();$/;"	p	class:CutWindowsManager
+getInstance	osc/OscManager.cpp	/^OscManager* OscManager::getInstance() {$/;"	f	class:OscManager
+getInstance	osc/OscManager.hpp	/^        static OscManager* getInstance();$/;"	p	class:OscManager
+getInt	modules/Attribute.hpp	/^        const int& getInt(const unsigned int& i) {return m_intValues[i];}$/;"	f	class:Attribute
+getListenerType	modules/Listener.hpp	/^        inline const std::string& getListenerType(){return m_listenerType;}$/;"	f	class:Listener
+getListenersGroup	gui/MainWindow.hpp	/^        inline Fl_Pack* getListenersGroup(){return m_listeners;}$/;"	f	class:MainWindow
+getMaxNbDepthCams	Reveal.hpp	/^        inline const int& getMaxNbDepthCams(){return m_maxNbDepthCams;}$/;"	f	class:Reveal
+getMaxNbRevealed	Reveal.hpp	/^        inline const int& getMaxNbRevealed(){return m_maxNbRevealed;}$/;"	f	class:Reveal
+getModelMat	modules/Module.hpp	/^        const glm::mat4& getModelMat(){return m_modelMat;}$/;"	f	class:Module
+getModule	gui/ModuleWidget.hpp	/^        inline Module* getModule(){return m_module;}$/;"	f	class:ModuleWidget
+getModuleListObsID	Reveal.hpp	/^        const unsigned int& getModuleListObsID(){return m_moduleListObsID;}$/;"	f	class:ModuleListObserver
+getModules	geoms/Geometry.hpp	/^        inline const std::vector<GeomModule*>& getModules(){return m_modules;}$/;"	f	class:Geometry
+getName	modules/Attribute.hpp	/^        inline const std::string& getName(){return m_name;}$/;"	f	class:Attribute
+getName	modules/Module.hpp	/^        inline const std::string& getName(){return m_name;}$/;"	f	class:Module
+getName	modules/RevealedCutModule.hpp	/^        const std::string& getName(){return m_name;}$/;"	f	class:CutWindow
+getNbAttributes	modules/Module.hpp	/^        inline unsigned int getNbAttributes(){return m_attributesVec.size();}$/;"	f	class:Module
+getNbDepthModulesFromID	modules/SpaceModule.hpp	/^        unsigned int getNbDepthModulesFromID(){return m_depthIDsModules.size();}$/;"	f	class:SpaceModule
+getNbRevealed	Reveal.hpp	/^	unsigned int getNbRevealed(){return m_revealedVec.size();}$/;"	f	class:Reveal
+getNbSubDepthIDs	modules/DepthCamModule.hpp	/^        inline virtual int getNbSubDepthIDs(){return m_maxNbMarkers;}$/;"	f	class:DepthCamModule
+getNbSubDepthIDs	modules/DepthModule.hpp	/^        inline virtual int getNbSubDepthIDs(){return 1;}$/;"	f	class:DepthModule
+getNbValues	modules/Attribute.hpp	/^        inline const unsigned int& getNbValues(){return m_nbValues;}$/;"	f	class:Attribute
+getNbWindows	modules/RevealedCutModule.hpp	/^        int getNbWindows(){return m_windowList.size();}$/;"	f	class:CutWindowsManager
+getPos	modules/RevealedPathModule.hpp	/^        inline const glm::vec4& getPos(){return m_point;}$/;"	f	class:PathPoint
+getPreviewWindow	Reveal.cpp	/^GLFWwindow* Reveal::getPreviewWindow() {$/;"	f	class:Reveal
+getPreviewWindow	Reveal.hpp	/^        GLFWwindow* getPreviewWindow();$/;"	p	class:Reveal
+getProjID	modules/ProjectorModule.hpp	/^        inline const int& getProjID(){return m_projID;}$/;"	f	class:ProjectorModule
+getRelPathToRev	modules/Attribute.cpp	/^void Attribute::getRelPathToRev(const string& abs, $/;"	f	class:Attribute
+getRelPathToRev	modules/Attribute.hpp	/^        void getRelPathToRev(const std::string& abs, $/;"	p	class:Attribute
+getRevID	modules/RevealedModule.hpp	/^        inline const unsigned int& getRevID(){return m_revID;}$/;"	f	class:RevealedModule
+getRevealedModule	Reveal.hpp	/^        RevealedModule* getRevealedModule(const unsigned int& s) { $/;"	f	class:Reveal
+getString	modules/Attribute.hpp	/^        const std::string& getString(const unsigned int& s) { $/;"	f	class:Attribute
+getStringValuesChoices	modules/Attribute.hpp	/^                                        getStringValuesChoices() {$/;"	f	class:Attribute
+getSubTree	modules/GroupModule.cpp	/^void GroupModule::getSubTree(std::vector<Module*>& children) {$/;"	f	class:GroupModule
+getSubTree	modules/GroupModule.hpp	/^        virtual void getSubTree(std::vector<Module*>& children); $/;"	p	class:GroupModule
+getSubTree	modules/Module.hpp	/^        virtual void getSubTree(std::vector<Module*>& children) {$/;"	f	class:Module
+getType	modules/Attribute.hpp	/^        inline const TYPE& getType(){return m_type;}$/;"	f	class:Attribute
+getType	modules/Module.hpp	/^        inline const std::string& getType(){return m_type;}$/;"	f	class:Module
+getUpID	modules/Module.hpp	/^        inline const int& getUpID(){return m_upID;}$/;"	f	class:Module
+getValueLabels	modules/Attribute.hpp	/^        inline const std::vector<std::string>& getValueLabels() {$/;"	f	class:Attribute
+getValuesMax	modules/Attribute.hpp	/^        inline const std::vector<float>& getValuesMax() {return m_valuesMax;}$/;"	f	class:Attribute
+getValuesMin	modules/Attribute.hpp	/^        inline const std::vector<float>& getValuesMin() {return m_valuesMin;}$/;"	f	class:Attribute
+getVerticalFOV	modules/DepthCamModule.hpp	/^        inline double& getVerticalFOV(){return m_verticalFOV;}$/;"	f	class:DepthCamModule
+getVisibilityMask	Reveal.cpp	/^int Reveal::getVisibilityMask(const std::string& visibleFrom) {$/;"	f	class:Reveal
+getVisibilityMask	Reveal.hpp	/^        int getVisibilityMask(const std::string& visibleFrom);$/;"	p	class:Reveal
+getVisibilityMask	modules/Module.hpp	/^        inline const int& getVisibilityMask(){return m_visibilityMask;}$/;"	f	class:Module
+getVisibleFromList	modules/GroupModule.cpp	/^void GroupModule::getVisibleFromList(std::vector<string>& modVec, $/;"	f	class:GroupModule
+getVisibleFromList	modules/GroupModule.hpp	/^        virtual void getVisibleFromList(std::vector<std::string>& modVec, $/;"	p	class:GroupModule
+getVisibleFromList	modules/Module.hpp	/^        virtual void getVisibleFromList(std::vector<std::string>& modVec, $/;"	f	class:Module
+getVisibleFromList	modules/SpaceModule.cpp	/^void SpaceModule::getVisibleFromList(vector<string>& modVec, $/;"	f	class:SpaceModule
+getVisibleFromList	modules/SpaceModule.hpp	/^        virtual void getVisibleFromList(std::vector<std::string>& modVec, $/;"	p	class:SpaceModule
+getWidth	modules/RevealedCutModule.hpp	/^        const int& getWidth(){return m_width;} $/;"	f	class:CutWindow
+getWinList	modules/RevealedCutModule.cpp	/^Window* CutWindowsManager::getWinList(Display* disp, unsigned long* len) {$/;"	f	class:CutWindowsManager
+getWinList	modules/RevealedCutModule.hpp	/^        Window* getWinList(Display* disp, unsigned long* len);$/;"	p	class:CutWindowsManager
+getWinName	modules/RevealedCutModule.cpp	/^char* CutWindowsManager::getWinName(Display* disp, Window win) {$/;"	f	class:CutWindowsManager
+getWinName	modules/RevealedCutModule.hpp	/^        char* getWinName(Display* disp, Window);$/;"	p	class:CutWindowsManager
+getWindow	modules/PreviewModule.hpp	/^        inline GLFWwindow* getWindow(){return m_previewWindow;}$/;"	f	class:PreviewModule
+getWindow	modules/RevealedCutModule.hpp	/^        CutWindow* getWindow(const std::string& name) {$/;"	f	class:CutWindowsManager
+globalFunction	modules/DepthCamModule.cpp	/^void DepthCamModule::globalFunction(cv::Mat &mat) {$/;"	f	class:DepthCamModule
+globalFunction	modules/DepthCamModule.hpp	/^        void globalFunction(cv::Mat &mat);$/;"	p	class:DepthCamModule
+gotAttributeListenersUpdate	modules/DepthCamModule.cpp	/^void DepthCamModule::gotAttributeListenersUpdate(Attribute* att) {$/;"	f	class:DepthCamModule
+gotAttributeListenersUpdate	modules/DepthCamModule.hpp	/^        void gotAttributeListenersUpdate(Attribute*);$/;"	p	class:DepthCamModule
+gotAttributeListenersUpdate	modules/Module.hpp	/^        virtual void gotAttributeListenersUpdate(Attribute*){}$/;"	f	class:Module
+gotAttributeListenersUpdate	modules/RevealedModelModule.hpp	/^        void gotAttributeListenersUpdate(Attribute* att) { $/;"	f	class:RevealedModelModule
+gotAttributeListenersUpdate	modules/RevealedModule.cpp	/^void RevealedModule::gotAttributeListenersUpdate(Attribute* att) {$/;"	f	class:RevealedModule
+gotAttributeListenersUpdate	modules/RevealedModule.hpp	/^        void gotAttributeListenersUpdate(Attribute*);$/;"	p	class:RevealedModule
+gotAttributeListenersUpdate	modules/RevealedShapeModule.hpp	/^        void gotAttributeListenersUpdate(Attribute* att) { $/;"	f	class:RevealedShapeModule
+grabImage	modules/RevealedCutModule.cpp	/^uchar* CutWindow::grabImage() {$/;"	f	class:CutWindow
+grabImage	modules/RevealedCutModule.hpp	/^        uchar* grabImage();$/;"	p	class:CutWindow
+gradientTypeCallback	modules/RevealedModule.hpp	/^        static void gradientTypeCallback(Module* mod, $/;"	f	class:RevealedModule
+handle	gui/MainWindow.cpp	/^int MainWindow::handle(int event) {$/;"	f	class:MainWindow
+handle	gui/MainWindow.hpp	/^        int handle(int event);$/;"	p	class:MainWindow
+hasTexCoords	geoms/Geometry.hpp	/^        void hasTexCoords(bool tc){m_hasTexCoords=tc;}$/;"	f	class:Geometry
+hideListeners	gui/MainWindow.cpp	/^void MainWindow::hideListeners() {$/;"	f	class:MainWindow
+hideListeners	gui/MainWindow.hpp	/^        void hideListeners();$/;"	p	class:MainWindow
+hsv2rgb	modules/RevealedModule.cpp	/^void RevealedModule::hsv2rgb(const vector<float>& hsv, $/;"	f	class:RevealedModule
+hsv2rgb	modules/RevealedModule.hpp	/^        void hsv2rgb(const std::vector<float>& hsv, $/;"	p	class:RevealedModule
+id	modules/DepthCamModule.hpp	/^    int id;$/;"	m	struct:s_markerAndTime
+idleFunc	Reveal.cpp	/^void idleFunc(void* data) {$/;"	f
+imageMarkersFolderCallback	modules/DepthCamModule.hpp	/^        static void imageMarkersFolderCallback(Module* mod, $/;"	f	class:DepthCamModule
+impl_	osc/oscPack/ip/UdpSocket.h	/^    Implementation *impl_;$/;"	m	class:SocketReceiveMultiplexer
+impl_	osc/oscPack/ip/UdpSocket.h	/^    Implementation *impl_;$/;"	m	class:UdpSocket
+init	Reveal.cpp	/^void Reveal::init() {$/;"	f	class:Reveal
+init	Reveal.hpp	/^        void init();$/;"	p	class:Reveal
+init	gui/MainWindow.cpp	/^void MainWindow::init() {$/;"	f	class:MainWindow
+init	gui/MainWindow.hpp	/^        void init();$/;"	p	class:MainWindow
+init	modules/DepthCamModule.cpp	/^void ArucoTracker::init() {$/;"	f	class:ArucoTracker
+init	modules/DepthCamModule.cpp	/^void ImageTracker::init() {$/;"	f	class:ImageTracker
+init	modules/DepthCamModule.hpp	/^        virtual void init()=0;$/;"	p	class:Tracker
+init	modules/DepthCamModule.hpp	/^        void init();$/;"	p	class:ArucoTracker
+init	modules/DepthCamModule.hpp	/^        void init();$/;"	p	class:ImageTracker
+init	osc/OscManager.cpp	/^void OscManager::init() {$/;"	f	class:OscManager
+init	osc/OscManager.hpp	/^        void init();$/;"	p	class:OscManager
+initBools	modules/Attribute.hpp	/^        void initBools(const std::vector<bool>& bools) {$/;"	f	class:Attribute
+initCount_	osc/oscPack/ip/win32/NetworkingUtils.cpp	/^static LONG initCount_ = 0;$/;"	v	file:
+initFile	modules/Attribute.hpp	/^        void initFile(const std::string& f) {m_stringValues[0]=f;}$/;"	f	class:Attribute
+initFloats	modules/Attribute.hpp	/^        void initFloats(const std::vector<float>& floats) {$/;"	f	class:Attribute
+initGL	modules/PreviewModule.cpp	/^void PreviewModule::initGL() {$/;"	f	class:PreviewModule
+initGL	modules/PreviewModule.hpp	/^        void initGL();$/;"	p	class:PreviewModule
+initGL	modules/ProjectorModule.cpp	/^void ProjectorModule::initGL() {$/;"	f	class:ProjectorModule
+initGL	modules/ProjectorModule.hpp	/^        void initGL();$/;"	p	class:ProjectorModule
+initInts	modules/Attribute.hpp	/^        void initInts(const std::vector<int>& ints) {$/;"	f	class:Attribute
+initPrograms	Reveal.hpp	/^        void initPrograms();$/;"	p	class:Reveal
+initStrings	modules/Attribute.hpp	/^        void initStrings(const std::vector<std::string>& strings) {$/;"	f	class:Attribute
+initialDelayMs	osc/oscPack/ip/posix/UdpSocket.cpp	/^	int initialDelayMs;$/;"	m	struct:AttachedTimerListener	file:
+initialDelayMs	osc/oscPack/ip/win32/UdpSocket.cpp	/^	int initialDelayMs;$/;"	m	struct:AttachedTimerListener	file:
+insideAxesCallback	modules/RevealedModule.hpp	/^        static void insideAxesCallback(Module* mod, $/;"	f	class:RevealedModule
+insideCallback	modules/RevealedModule.hpp	/^        static void insideCallback(Module* mod, $/;"	f	class:RevealedModule
+int32	osc/oscPack/osc/OscTypes.h	/^typedef signed int int32;$/;"	t	namespace:osc
+int32	osc/oscPack/osc/OscTypes.h	/^typedef signed long int32;$/;"	t	namespace:osc
+int64	osc/oscPack/osc/OscTypes.h	/^typedef __int64 int64;$/;"	t	namespace:osc
+isBound_	osc/oscPack/ip/posix/UdpSocket.cpp	/^	bool isBound_;$/;"	m	class:UdpSocket::Implementation	file:
+isBound_	osc/oscPack/ip/win32/UdpSocket.cpp	/^	bool isBound_;$/;"	m	class:UdpSocket::Implementation	file:
+isConnected_	osc/oscPack/ip/posix/UdpSocket.cpp	/^	bool isConnected_;$/;"	m	class:UdpSocket::Implementation	file:
+isConnected_	osc/oscPack/ip/win32/UdpSocket.cpp	/^	bool isConnected_;$/;"	m	class:UdpSocket::Implementation	file:
+isOpen	modules/DepthCamModule.hpp	/^        bool isOpen(){return m_open;}$/;"	f	class:DepthCamModule
+isOutputActive	modules/RevealedModule.hpp	/^        inline bool isOutputActive(){return m_outputActive;}$/;"	f	class:RevealedModule
+isVisible	modules/Module.hpp	/^        inline bool isVisible(){return m_visible && m_parentVisible;}$/;"	f	class:Module
+jack_ringbuffer_create	osc/ringbuffer.c	/^ jack_ringbuffer_t *jack_ringbuffer_create(size_t sz);$/;"	p	file:
+jack_ringbuffer_create	osc/ringbuffer.c	/^jack_ringbuffer_create (size_t sz)$/;"	f
+jack_ringbuffer_create	osc/ringbuffer.h	/^jack_ringbuffer_t *jack_ringbuffer_create(size_t sz);$/;"	p
+jack_ringbuffer_data_t	osc/ringbuffer.c	/^jack_ringbuffer_data_t ;$/;"	t	typeref:struct:__anon6	file:
+jack_ringbuffer_data_t	osc/ringbuffer.h	/^jack_ringbuffer_data_t ;$/;"	t	typeref:struct:__anon1
+jack_ringbuffer_free	osc/ringbuffer.c	/^ void jack_ringbuffer_free(jack_ringbuffer_t *rb);$/;"	p	file:
+jack_ringbuffer_free	osc/ringbuffer.c	/^jack_ringbuffer_free (jack_ringbuffer_t * rb)$/;"	f
+jack_ringbuffer_free	osc/ringbuffer.h	/^void jack_ringbuffer_free(jack_ringbuffer_t *rb);$/;"	p
+jack_ringbuffer_get_read_vector	osc/ringbuffer.c	/^ void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb,$/;"	p	file:
+jack_ringbuffer_get_read_vector	osc/ringbuffer.c	/^jack_ringbuffer_get_read_vector (const jack_ringbuffer_t * rb,$/;"	f
+jack_ringbuffer_get_read_vector	osc/ringbuffer.h	/^void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb,$/;"	p
+jack_ringbuffer_get_write_vector	osc/ringbuffer.c	/^ void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb,$/;"	p	file:
+jack_ringbuffer_get_write_vector	osc/ringbuffer.c	/^jack_ringbuffer_get_write_vector (const jack_ringbuffer_t * rb,$/;"	f
+jack_ringbuffer_get_write_vector	osc/ringbuffer.h	/^void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb,$/;"	p
+jack_ringbuffer_mlock	osc/ringbuffer.c	/^ int jack_ringbuffer_mlock(jack_ringbuffer_t *rb);$/;"	p	file:
+jack_ringbuffer_mlock	osc/ringbuffer.c	/^jack_ringbuffer_mlock (jack_ringbuffer_t * rb)$/;"	f
+jack_ringbuffer_mlock	osc/ringbuffer.h	/^int jack_ringbuffer_mlock(jack_ringbuffer_t *rb);$/;"	p
+jack_ringbuffer_peek	osc/ringbuffer.c	/^ size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt);$/;"	p	file:
+jack_ringbuffer_peek	osc/ringbuffer.c	/^jack_ringbuffer_peek (jack_ringbuffer_t * rb, char *dest, size_t cnt)$/;"	f
+jack_ringbuffer_peek	osc/ringbuffer.h	/^size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt);$/;"	p
+jack_ringbuffer_read	osc/ringbuffer.c	/^ size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt);$/;"	p	file:
+jack_ringbuffer_read	osc/ringbuffer.c	/^jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt)$/;"	f
+jack_ringbuffer_read	osc/ringbuffer.h	/^size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt);$/;"	p
+jack_ringbuffer_read_advance	osc/ringbuffer.c	/^ void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt);$/;"	p	file:
+jack_ringbuffer_read_advance	osc/ringbuffer.c	/^jack_ringbuffer_read_advance (jack_ringbuffer_t * rb, size_t cnt)$/;"	f
+jack_ringbuffer_read_advance	osc/ringbuffer.h	/^void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt);$/;"	p
+jack_ringbuffer_read_space	osc/ringbuffer.c	/^ size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb);$/;"	p	file:
+jack_ringbuffer_read_space	osc/ringbuffer.c	/^jack_ringbuffer_read_space (const jack_ringbuffer_t * rb)$/;"	f
+jack_ringbuffer_read_space	osc/ringbuffer.h	/^size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb);$/;"	p
+jack_ringbuffer_reset	osc/ringbuffer.c	/^ void jack_ringbuffer_reset(jack_ringbuffer_t *rb);$/;"	p	file:
+jack_ringbuffer_reset	osc/ringbuffer.c	/^jack_ringbuffer_reset (jack_ringbuffer_t * rb)$/;"	f
+jack_ringbuffer_reset	osc/ringbuffer.h	/^void jack_ringbuffer_reset(jack_ringbuffer_t *rb);$/;"	p
+jack_ringbuffer_reset_size	osc/ringbuffer.c	/^ void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz);$/;"	p	file:
+jack_ringbuffer_reset_size	osc/ringbuffer.c	/^jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz)$/;"	f
+jack_ringbuffer_reset_size	osc/ringbuffer.h	/^void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz);$/;"	p
+jack_ringbuffer_t	osc/ringbuffer.c	/^jack_ringbuffer_t ;$/;"	t	typeref:struct:__anon7	file:
+jack_ringbuffer_t	osc/ringbuffer.h	/^jack_ringbuffer_t ;$/;"	t	typeref:struct:__anon2
+jack_ringbuffer_write	osc/ringbuffer.c	/^ size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src,$/;"	p	file:
+jack_ringbuffer_write	osc/ringbuffer.c	/^jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt)$/;"	f
+jack_ringbuffer_write	osc/ringbuffer.h	/^size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src,$/;"	p
+jack_ringbuffer_write_advance	osc/ringbuffer.c	/^jack_ringbuffer_write_advance (jack_ringbuffer_t * rb, size_t cnt)$/;"	f
+jack_ringbuffer_write_advance	osc/ringbuffer.c	/^void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt);$/;"	p	file:
+jack_ringbuffer_write_advance	osc/ringbuffer.h	/^void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt);$/;"	p
+jack_ringbuffer_write_space	osc/ringbuffer.c	/^jack_ringbuffer_write_space (const jack_ringbuffer_t * rb)$/;"	f
+jack_ringbuffer_write_space	osc/ringbuffer.c	/^size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb);$/;"	p	file:
+jack_ringbuffer_write_space	osc/ringbuffer.h	/^size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb);$/;"	p
+jointly	modules/DepthCamModule.cpp	/^int DepthCamModule::jointly(vector<cv::Point2f> points, cv::Point2f pt){$/;"	f	class:DepthCamModule
+jointly	modules/DepthCamModule.hpp	/^        int jointly(std::vector<cv::Point2f> points, cv::Point2f pt);$/;"	p	class:DepthCamModule
+len	osc/ringbuffer.c	/^    size_t len;$/;"	m	struct:__anon6	file:
+len	osc/ringbuffer.h	/^    size_t len;$/;"	m	struct:__anon1
+listModulesAndAttributes	modules/GroupModule.cpp	/^void GroupModule::listModulesAndAttributes(const std::string& parentName, $/;"	f	class:GroupModule
+listModulesAndAttributes	modules/GroupModule.hpp	/^        void listModulesAndAttributes(const std::string& parentName, $/;"	p	class:GroupModule
+listModulesAndAttributes	modules/Module.cpp	/^void Module::listModulesAndAttributes(const std::string& parentName, $/;"	f	class:Module
+listModulesAndAttributes	modules/Module.hpp	/^        virtual void listModulesAndAttributes(const std::string& parentName, $/;"	p	class:Module
+listener	osc/oscPack/ip/posix/UdpSocket.cpp	/^	TimerListener *listener;$/;"	m	struct:AttachedTimerListener	file:
+listener	osc/oscPack/ip/win32/UdpSocket.cpp	/^	TimerListener *listener;$/;"	m	struct:AttachedTimerListener	file:
+listener_	osc/oscPack/ip/UdpSocket.h	/^    PacketListener *listener_;$/;"	m	class:UdpListeningReceiveSocket
+load	Reveal.cpp	/^void Reveal::load(xmlNodePtr node) {$/;"	f	class:Reveal
+load	Reveal.hpp	/^        virtual void load(xmlNodePtr);$/;"	p	class:Reveal
+load	modules/Attribute.cpp	/^void Attribute::load(xmlNodePtr node) {$/;"	f	class:Attribute
+load	modules/Attribute.hpp	/^        void load(xmlNodePtr node);$/;"	p	class:Attribute
+load	modules/GroupModule.cpp	/^void GroupModule::load(xmlNodePtr node) {$/;"	f	class:GroupModule
+load	modules/GroupModule.hpp	/^        virtual void load(xmlNodePtr node);$/;"	p	class:GroupModule
+load	modules/Listener.cpp	/^void Listener::load(xmlNodePtr lisNode) {$/;"	f	class:Listener
+load	modules/Listener.hpp	/^        virtual void load(xmlNodePtr node);$/;"	p	class:Listener
+load	modules/Module.cpp	/^void Module::load(xmlNodePtr node) {$/;"	f	class:Module
+load	modules/Module.hpp	/^        virtual void load(xmlNodePtr node);$/;"	p	class:Module
+load	modules/PreviewModule.cpp	/^void PreviewModule::load(xmlNodePtr node) {$/;"	f	class:PreviewModule
+load	modules/PreviewModule.hpp	/^        virtual void load(xmlNodePtr node);$/;"	p	class:PreviewModule
+load	modules/RevealedPathModule.cpp	/^void RevealedPathModule::load(xmlNodePtr node) {$/;"	f	class:RevealedPathModule
+load	modules/RevealedPathModule.hpp	/^        virtual void load(xmlNodePtr node);$/;"	p	class:RevealedPathModule
+load	modules/SpaceModule.cpp	/^void SpacesModule::load(xmlNodePtr node) {$/;"	f	class:SpacesModule
+load	modules/SpaceModule.hpp	/^        virtual void load(xmlNodePtr node);$/;"	p	class:SpacesModule
+loadPnt	modules/RevealedPathModule.cpp	/^void PathPoint::loadPnt(xmlNodePtr node) {$/;"	f	class:PathPoint
+loadPnt	modules/RevealedPathModule.cpp	/^void PathPointModule::loadPnt(xmlNodePtr node) {$/;"	f	class:PathPointModule
+loadPnt	modules/RevealedPathModule.hpp	/^        virtual void loadPnt(xmlNodePtr node);$/;"	p	class:PathPoint
+loadPnt	modules/RevealedPathModule.hpp	/^        virtual void loadPnt(xmlNodePtr node);$/;"	p	class:PathPointModule
+lookAtCallback	modules/PreviewModule.hpp	/^        static void lookAtCallback(Module* mod, $/;"	f	class:PreviewModule
+m_absPoint	modules/RevealedPathModule.hpp	/^        glm::vec4 m_absPoint;$/;"	m	class:PathPoint
+m_accessibility	modules/Attribute.hpp	/^        ACCESSIBILITY m_accessibility;$/;"	m	class:Attribute
+m_accumTimeDiff	modules/RevealedModule.hpp	/^        int m_accumTimeDiff;$/;"	m	class:RevealedLayer
+m_actionCallback	modules/Attribute.hpp	/^        ActionCallback* m_actionCallback;$/;"	m	class:Attribute
+m_active	modules/PreviewModule.hpp	/^        bool m_active;$/;"	m	class:PreviewModule
+m_active	modules/ProjectorModule.hpp	/^        bool m_active;$/;"	m	class:ProjectorModule
+m_addListenerBut	gui/AttributeWidget.hpp	/^        Fl_Button* m_addListenerBut;$/;"	m	class:AttributeWidget
+m_adress	osc/OscListener.hpp	/^        std::string m_adress;$/;"	m	class:OscListener
+m_adress	osc/OscManager.hpp	/^    std::string m_adress;$/;"	m	struct:OscStream
+m_aliveMarkers	modules/DepthCamModule.hpp	/^        std::map<int, s_markerAndTime> m_aliveMarkers;$/;"	m	class:DepthCamModule
+m_arucoTracker	modules/DepthCamModule.hpp	/^        ArucoTracker* m_arucoTracker;$/;"	m	class:DepthCamModule
+m_attachedProjs	modules/DepthCamModule.hpp	/^        std::map<int, ProjectorModule*> m_attachedProjs;$/;"	m	class:DepthCamModule
+m_attachedToCam	modules/ProjectorModule.hpp	/^        DepthCamModule* m_attachedToCam;$/;"	m	class:ProjectorModule
+m_attribute	gui/AttributeWidget.hpp	/^        Attribute* m_attribute;$/;"	m	class:AttributeWidget
+m_attribute	modules/Listener.hpp	/^        Attribute* m_attribute;$/;"	m	class:Listener
+m_attributeWidget	gui/GuiListener.hpp	/^        AttributeWidget* m_attributeWidget;$/;"	m	class:GuiListener
+m_attributes	gui/MainWindow.hpp	/^        Fl_Pack* m_attributes;$/;"	m	class:MainWindow
+m_attributesDeleteVec	Reveal.hpp	/^        std::vector<Attribute*> m_attributesDeleteVec;$/;"	m	class:Reveal
+m_attributesMap	modules/Module.hpp	/^        std::map<std::string, Attribute*> m_attributesMap;$/;"	m	class:Module
+m_attributesVec	modules/Module.hpp	/^        std::vector<Attribute*> m_attributesVec;$/;"	m	class:Module
+m_attributesWidth	gui/MainWindow.hpp	/^        int m_attributesWidth;$/;"	m	class:MainWindow
+m_backImg	modules/DepthCamModule.hpp	/^        cv::Mat m_backImg;$/;"	m	class:DepthCamModule
+m_backgroundActive	modules/DepthCamModule.hpp	/^        bool m_backgroundActive;$/;"	m	class:DepthCamModule
+m_bbPnts	modules/GeomModule.hpp	/^        glm::vec3 m_bbPnts[2];$/;"	m	class:GeomModule
+m_bboxLocalMin	modules/GeomModule.hpp	/^        std::map<unsigned int, glm::vec4> m_bboxLocalMin;$/;"	m	class:GeomModule
+m_bboxLocalSizes	modules/GeomModule.hpp	/^        std::map<unsigned int, glm::vec4> m_bboxLocalSizes;$/;"	m	class:GeomModule
+m_bboxMins	modules/GeomModule.hpp	/^        std::map<unsigned int, glm::vec4> m_bboxMins;$/;"	m	class:GeomModule
+m_bboxRots	modules/GeomModule.hpp	/^        std::map<unsigned int, glm::mat4> m_bboxRots;$/;"	m	class:GeomModule
+m_bboxSizes	modules/GeomModule.hpp	/^        std::map<unsigned int, glm::vec4> m_bboxSizes;$/;"	m	class:GeomModule
+m_blueXmm	modules/DepthCamModule.hpp	/^        int m_blueXmm, m_blueYmm, m_blueZmm;$/;"	m	class:DepthCamModule
+m_blueYmm	modules/DepthCamModule.hpp	/^        int m_blueXmm, m_blueYmm, m_blueZmm;$/;"	m	class:DepthCamModule
+m_blueZmm	modules/DepthCamModule.hpp	/^        int m_blueXmm, m_blueYmm, m_blueZmm;$/;"	m	class:DepthCamModule
+m_boolCallback	modules/Attribute.hpp	/^        BoolCallback* m_boolCallback;$/;"	m	class:Attribute
+m_boolValues	modules/Attribute.hpp	/^        std::vector<bool> m_boolValues;$/;"	m	class:Attribute
+m_boolValues	osc/OscManager.hpp	/^    std::vector<bool> m_boolValues;$/;"	m	struct:OscMessage
+m_buffer	osc/OscManager.hpp	/^        char m_buffer[IP_MTU_SIZE];$/;"	m	class:OscManager
+m_buffer	osc/OscManager.hpp	/^    char m_buffer[IP_MTU_SIZE];$/;"	m	struct:OscStream
+m_bundleStarted	osc/OscManager.hpp	/^    bool m_bundleStarted;$/;"	m	struct:OscStream
+m_button	gui/AttributeWidget.hpp	/^        Fl_Button* m_button;$/;"	m	class:AttributeWidget
+m_calibGeom	modules/ProjectorModule.hpp	/^        QuadGeometry* m_calibGeom;$/;"	m	class:ProjectorModule
+m_calibrated	modules/ProjectorModule.hpp	/^        bool m_calibrated;$/;"	m	class:ProjectorModule
+m_calibrating	modules/DepthCamModule.hpp	/^        int m_calibrating;$/;"	m	class:DepthCamModule
+m_calibrating	modules/ProjectorModule.hpp	/^        int m_calibrating;$/;"	m	class:ProjectorModule
+m_calibrationCam	modules/ProjectorModule.hpp	/^        DepthCamModule* m_calibrationCam;$/;"	m	class:ProjectorModule
+m_calibrationProj	modules/DepthCamModule.hpp	/^        ProjectorModule* m_calibrationProj;$/;"	m	class:DepthCamModule
+m_calibrationStopped	modules/DepthCamModule.hpp	/^        bool m_calibrationStopped;$/;"	m	class:DepthCamModule
+m_calibrationStopped	modules/ProjectorModule.hpp	/^        bool m_calibrationStopped;$/;"	m	class:ProjectorModule
+m_camTexMap	modules/DepthCamModule.hpp	/^        std::map<int, GLuint> m_camTexMap;$/;"	m	class:DepthCamModule
+m_camTexMap1	modules/DepthCamModule.hpp	/^        std::map<int, GLuint> m_camTexMap1;$/;"	m	class:DepthCamModule
+m_camTexMap2	modules/DepthCamModule.hpp	/^        std::map<int, GLuint> m_camTexMap2;$/;"	m	class:DepthCamModule
+m_camTexUpMap	modules/DepthCamModule.hpp	/^        std::map<int, bool> m_camTexUpMap;$/;"	m	class:DepthCamModule
+m_capturedBackground	modules/DepthCamModule.hpp	/^        bool m_capturedBackground;$/;"	m	class:DepthCamModule
+m_capturingBackground	modules/DepthCamModule.hpp	/^        int m_capturingBackground;$/;"	m	class:DepthCamModule
+m_checks	gui/AttributeWidget.hpp	/^        std::vector<Fl_Toggle_Button*> m_checks;$/;"	m	class:AttributeWidget
+m_childID	modules/Module.hpp	/^        unsigned int m_childID;$/;"	m	class:Module
+m_children	modules/GroupModule.hpp	/^        std::vector<Module*> m_children;$/;"	m	class:GroupModule
+m_childrenMap	modules/GroupModule.hpp	/^        std::map<unsigned int, Module*> m_childrenMap;$/;"	m	class:GroupModule
+m_choices	gui/AttributeWidget.hpp	/^        std::vector<Fl_Choice*> m_choices;$/;"	m	class:AttributeWidget
+m_color	modules/DepthCamModule.hpp	/^        openni::VideoStream m_depth, m_color;$/;"	m	class:DepthCamModule
+m_color	modules/RevealedModule.hpp	/^        std::vector<float> m_color;$/;"	m	class:RevealedModule
+m_colorActivated	modules/DepthCamModule.hpp	/^        bool m_colorActivated;$/;"	m	class:DepthCamModule
+m_colorFrame	modules/DepthCamModule.hpp	/^        openni::VideoFrameRef m_colorFrame;$/;"	m	class:DepthCamModule
+m_cols	modules/DepthCamModule.hpp	/^        std::vector<int> m_cols;$/;"	m	class:ImageTracker
+m_compoLocalSizes	modules/RevealedPathModule.hpp	/^        std::map<unsigned int, glm::vec4> m_compoLocalSizes;$/;"	m	class:RevealedPathModule
+m_compoRots	modules/RevealedPathModule.hpp	/^        std::map<unsigned int, glm::mat4> m_compoRots;$/;"	m	class:RevealedPathModule
+m_compoSizes	geoms/Geometry.hpp	/^        std::vector<int> m_compoSizes;$/;"	m	class:Geometry
+m_compoVertices	modules/RevealedPathModule.hpp	/^        std::map<unsigned int, std::vector<glm::vec4> > m_compoVertices;$/;"	m	class:RevealedPathModule
+m_contextHandlerID	modules/ContextHandler.hpp	/^        int m_contextHandlerID;$/;"	m	class:ContextHandler
+m_contextHandlers	Reveal.hpp	/^        std::map<unsigned int, ContextHandler*> m_contextHandlers;$/;"	m	class:Reveal
+m_contextHandlersCounter	Reveal.hpp	/^        int m_contextHandlersCounter;$/;"	m	class:Reveal
+m_contexts	geoms/Geometry.hpp	/^        std::map<int, ContextGeometry> m_contexts;$/;"	m	class:Geometry
+m_contourThreshold	modules/DepthCamModule.hpp	/^        float m_contourThreshold;$/;"	m	class:DepthCamModule
+m_coordImage	modules/ModelModule.hpp	/^        float* m_coordImage;$/;"	m	class:ModelModule
+m_coordImage	modules/RevealedCutModule.hpp	/^        float* m_coordImage;$/;"	m	class:RevealedCutModule
+m_coordsIDMap	modules/RevealedModule.hpp	/^        std::map<int, GLuint> m_coordsIDMap;$/;"	m	class:RevealedModule
+m_coordsUpMap	modules/RevealedModule.hpp	/^        std::map<int, bool> m_coordsUpMap;$/;"	m	class:RevealedModule
+m_current	modules/RevealedModule.hpp	/^        int m_current;$/;"	m	class:RevealedLayerAnim
+m_currentFile	Reveal.hpp	/^        std::string m_currentFile;$/;"	m	class:Reveal
+m_currentGeom	modules/GeomModule.hpp	/^        Geometry* m_currentGeom;$/;"	m	class:GeomModule
+m_currentShape	modules/ShapeModule.hpp	/^        std::string m_currentShape;$/;"	m	class:ShapeModule
+m_currentTracker	modules/DepthCamModule.hpp	/^        Tracker* m_currentTracker;$/;"	m	class:DepthCamModule
+m_cursorValues	modules/DepthCamModule.hpp	/^        std::vector<float> m_cursorValues;$/;"	m	class:DepthCamModule
+m_cutWin	modules/RevealedCutModule.hpp	/^        CutWindow* m_cutWin;$/;"	m	class:RevealedCutModule
+m_debuggingMarkers	modules/DepthCamModule.hpp	/^        bool m_debuggingMarkers;$/;"	m	class:DepthCamModule
+m_defaultDepthFrame	modules/DepthCamModule.hpp	/^        unsigned short *m_defaultDepthFrame;$/;"	m	class:DepthCamModule
+m_defaultFps	modules/DepthCamModule.hpp	/^        uint16_t m_defaultWidth, m_defaultHeight, m_defaultFps;$/;"	m	class:DepthCamModule
+m_defaultHeight	modules/DepthCamModule.hpp	/^        uint16_t m_defaultWidth, m_defaultHeight, m_defaultFps;$/;"	m	class:DepthCamModule
+m_defaultImgData	modules/RevealedCutModule.hpp	/^        uchar* m_defaultImgData;$/;"	m	class:CutWindow
+m_defaultWidth	modules/DepthCamModule.hpp	/^        uint16_t m_defaultWidth, m_defaultHeight, m_defaultFps;$/;"	m	class:DepthCamModule
+m_depth	modules/DepthCamModule.hpp	/^        openni::VideoStream m_depth, m_color;$/;"	m	class:DepthCamModule
+m_depth	modules/Module.hpp	/^        unsigned int m_depth;$/;"	m	class:Module
+m_depthCamModules	modules/SpaceModule.hpp	/^        std::vector<DepthCamModule*> m_depthCamModules;$/;"	m	class:SpaceModule
+m_depthFrame	modules/DepthCamModule.hpp	/^        openni::VideoFrameRef m_depthFrame;$/;"	m	class:DepthCamModule
+m_depthID	modules/DepthModule.hpp	/^        unsigned int m_depthID;$/;"	m	class:DepthModule
+m_depthIDsModules	modules/SpaceModule.hpp	/^        std::map<unsigned int, DepthModule*> m_depthIDsModules;$/;"	m	class:SpaceModule
+m_depthImg	modules/DepthCamModule.hpp	/^        cv::Mat m_depthImg;$/;"	m	class:DepthCamModule
+m_depthMeshModules	modules/SpaceModule.hpp	/^        std::vector<DepthMeshModule*> m_depthMeshModules;$/;"	m	class:SpaceModule
+m_depthModsMap	modules/RevealedModule.hpp	/^        std::map<unsigned int, bool> m_depthModsMap;$/;"	m	class:RevealedModule
+m_depthModules	modules/SpaceModule.hpp	/^        std::vector<DepthModule*> m_depthModules;$/;"	m	class:SpaceModule
+m_depthShapeModules	modules/SpaceModule.hpp	/^        std::vector<DepthShapeModule*> m_depthShapeModules;$/;"	m	class:SpaceModule
+m_depthType	modules/DepthModule.hpp	/^        int m_depthType;$/;"	m	class:DepthModule
+m_descriptors	modules/DepthCamModule.hpp	/^        std::vector<cv::Mat> m_descriptors;$/;"	m	class:ImageTracker
+m_destIndices	modules/RevealedCutModule.hpp	/^        std::vector<int> m_destIndices;$/;"	m	class:RevealedCutModule
+m_detDepthImg	modules/DepthCamModule.hpp	/^	cv::Mat m_detDepthImg;$/;"	m	class:DepthCamModule
+m_detMarkImg	modules/DepthCamModule.hpp	/^        cv::Mat m_detMarkImg;$/;"	m	class:DepthCamModule
+m_detRgbImg	modules/DepthCamModule.hpp	/^        cv::Mat m_detRgbImg;$/;"	m	class:DepthCamModule
+m_detectLock	modules/DepthCamModule.hpp	/^        std::mutex m_detectLock;$/;"	m	class:DepthCamModule
+m_detectedMarkers	modules/DepthCamModule.hpp	/^        std::vector<s_markerAndTime> m_detectedMarkers;$/;"	m	class:DepthCamModule
+m_detectingMarkers	modules/DepthCamModule.hpp	/^        bool m_detectingMarkers;$/;"	m	class:DepthCamModule
+m_detector	modules/DepthCamModule.hpp	/^        cv::Ptr<cv::Feature2D> m_detector;$/;"	m	class:ImageTracker
+m_device	modules/DepthCamModule.hpp	/^        openni::Device m_device;$/;"	m	class:DepthCamModule
+m_deviceID	modules/DepthCamModule.hpp	/^        std::string m_deviceID;$/;"	m	class:DepthCamModule
+m_dimensions	modules/ShapeModule.hpp	/^        glm::vec3 m_dimensions;$/;"	m	class:ShapeModule
+m_disp	modules/RevealedCutModule.hpp	/^        Display* m_disp;$/;"	m	class:CutWindow
+m_disp	modules/RevealedCutModule.hpp	/^        Display* m_disp;$/;"	m	class:CutWindowsManager
+m_eyePos	modules/PreviewModule.hpp	/^        glm::vec3 m_eyePos;$/;"	m	class:PreviewModule
+m_far	modules/PreviewModule.hpp	/^        float m_far;$/;"	m	class:PreviewModule
+m_fileCallback	modules/Attribute.hpp	/^        FileCallback* m_fileCallback;$/;"	m	class:Attribute
+m_fileName	gui/MainWindow.hpp	/^        std::string m_fileName;$/;"	m	class:MainWindow
+m_fillingMarkers	modules/DepthCamModule.hpp	/^        bool m_fillingMarkers;$/;"	m	class:DepthCamModule
+m_filter	modules/DepthCamModule.hpp	/^        bool m_filter;$/;"	m	class:DepthCamModule
+m_filterCursorSize	modules/DepthCamModule.hpp	/^        float m_filterCursorSize;$/;"	m	class:DepthCamModule
+m_filterCursorSums	modules/DepthCamModule.hpp	/^        std::vector<float> m_filterCursorSums;$/;"	m	class:DepthCamModule
+m_filterCursorValues	modules/DepthCamModule.hpp	/^        std::vector<std::deque<float> > m_filterCursorValues;$/;"	m	class:DepthCamModule
+m_finalCombin	modules/DepthCamModule.hpp	/^        cv::Mat m_finalCombin;$/;"	m	class:DepthCamModule
+m_floatCallback	modules/Attribute.hpp	/^        FloatCallback* m_floatCallback;$/;"	m	class:Attribute
+m_floatValues	modules/Attribute.hpp	/^        std::vector<float> m_floatValues;$/;"	m	class:Attribute
+m_floatValues	osc/OscManager.hpp	/^    std::vector<float> m_floatValues;$/;"	m	struct:OscMessage
+m_foundCorners	modules/ProjectorModule.hpp	/^        std::vector<cv::Point2f> m_foundCorners;$/;"	m	class:ProjectorModule
+m_fps	modules/DepthCamModule.hpp	/^        uint16_t m_width, m_height, m_fps;$/;"	m	class:DepthCamModule
+m_frame	modules/RevealedModule.hpp	/^        cv::Mat m_frame;$/;"	m	class:RevealedLayerVideo
+m_fullAttributesMap	Reveal.hpp	/^        std::map<std::string, Attribute*> m_fullAttributesMap;$/;"	m	class:Reveal
+m_fullName	gui/AttributeWidget.hpp	/^        std::string m_fullName;$/;"	m	class:AttributeWidget
+m_fullName	modules/Attribute.hpp	/^        std::string m_fullName;$/;"	m	class:Attribute
+m_fullName	modules/Module.hpp	/^        std::string m_fullName;$/;"	m	class:Module
+m_generatedCorners	modules/ProjectorModule.hpp	/^        std::vector<cv::Point2f> m_generatedCorners;$/;"	m	class:ProjectorModule
+m_geomID	geoms/Geometry.hpp	/^        Reveal::GEOM_ID m_geomID;$/;"	m	class:Geometry
+m_geomID	modules/GeomModule.hpp	/^        unsigned int m_geomID;$/;"	m	class:GeomModule
+m_geometries	modules/PreviewModule.hpp	/^        std::vector<Geometry*> m_geometries;$/;"	m	class:PreviewModule
+m_geoms	Reveal.hpp	/^        std::vector<Geometry*> m_geoms;$/;"	m	class:Reveal
+m_geoms	modules/SpaceModule.hpp	/^        std::vector<Geometry*> m_geoms;$/;"	m	class:SpaceModule
+m_geomsMap	Reveal.hpp	/^        std::map<GEOM_ID, Geometry*> m_geomsMap;$/;"	m	class:Reveal
+m_geomsMap	modules/SpaceModule.hpp	/^        std::map<Reveal::GEOM_ID, Geometry*> m_geomsMap;$/;"	m	class:SpaceModule
+m_gotColor	modules/DepthCamModule.hpp	/^        bool m_gotDepth, m_gotColor;$/;"	m	class:DepthCamModule
+m_gotDepth	modules/DepthCamModule.hpp	/^        bool m_gotDepth, m_gotColor;$/;"	m	class:DepthCamModule
+m_grabbed	modules/RevealedCutModule.hpp	/^        bool m_grabbed;$/;"	m	class:CutWindow
+m_gradientType	modules/RevealedModule.hpp	/^        int m_gradientType;$/;"	m	class:RevealedModule
+m_gradientTypes	modules/RevealedModule.hpp	/^        std::vector<std::string> m_gradientTypes;$/;"	m	class:RevealedModule
+m_greenXmm	modules/DepthCamModule.hpp	/^        int m_greenXmm, m_greenYmm, m_greenZmm;$/;"	m	class:DepthCamModule
+m_greenYmm	modules/DepthCamModule.hpp	/^        int m_greenXmm, m_greenYmm, m_greenZmm;$/;"	m	class:DepthCamModule
+m_greenZmm	modules/DepthCamModule.hpp	/^        int m_greenXmm, m_greenYmm, m_greenZmm;$/;"	m	class:DepthCamModule
+m_guiListener	gui/AttributeWidget.hpp	/^        GuiListener* m_guiListener;$/;"	m	class:AttributeWidget
+m_hasTexCoords	geoms/Geometry.hpp	/^        bool m_hasTexCoords;$/;"	m	class:Geometry
+m_height	modules/DepthCamModule.hpp	/^        uint16_t m_width, m_height, m_fps;$/;"	m	class:DepthCamModule
+m_height	modules/ProjectorModule.hpp	/^        float m_width, m_height;$/;"	m	class:ProjectorModule
+m_height	modules/RevealedCutModule.hpp	/^        int m_posX, m_posY, m_width, m_height;$/;"	m	class:CutWindow
+m_horizontalFOV	modules/DepthCamModule.hpp	/^        double m_horizontalFOV, m_verticalFOV;$/;"	m	class:DepthCamModule
+m_id	osc/OscManager.hpp	/^    std::string m_id;$/;"	m	struct:OscStream
+m_image	modules/RevealedModule.hpp	/^        Fl_Shared_Image* m_image;$/;"	m	class:RevealedLayerImage
+m_imageSize	modules/ProjectorModule.hpp	/^        cv::Size m_imageSize;$/;"	m	class:ProjectorModule
+m_imageTracker	modules/DepthCamModule.hpp	/^        ImageTracker* m_imageTracker;$/;"	m	class:DepthCamModule
+m_images	modules/RevealedModule.hpp	/^        std::vector<Fl_Shared_Image*> m_images;$/;"	m	class:RevealedLayerAnim
+m_imgData	modules/RevealedCutModule.hpp	/^        uchar* m_imgData;$/;"	m	class:CutWindow
+m_imgFolder	modules/DepthCamModule.hpp	/^        std::string m_imgFolder;$/;"	m	class:ImageTracker
+m_indexBuffer	geoms/Geometry.hpp	/^    GLuint m_indexBuffer;$/;"	m	struct:ContextGeometry
+m_indexBufferData	geoms/Geometry.hpp	/^        std::vector<GLuint> m_indexBufferData;$/;"	m	class:Geometry
+m_init	modules/RevealedCutModule.hpp	/^        bool m_init;$/;"	m	class:CutWindow
+m_initialized	modules/PreviewModule.hpp	/^        bool m_initialized;$/;"	m	class:PreviewModule
+m_initialized	modules/ProjectorModule.hpp	/^        bool m_initialized;$/;"	m	class:ProjectorModule
+m_inputs	gui/AttributeWidget.hpp	/^        std::vector<Fl_Input*> m_inputs;$/;"	m	class:AttributeWidget
+m_inside	modules/RevealedModule.hpp	/^        int m_inside;$/;"	m	class:RevealedModule
+m_insideAxes	modules/RevealedModule.hpp	/^        std::vector<std::string> m_insideAxes;$/;"	m	class:RevealedModule
+m_insideIDMap	modules/RevealedModule.hpp	/^        std::map<int, GLuint> m_insideIDMap;$/;"	m	class:RevealedModule
+m_insideImage	modules/RevealedModule.hpp	/^        Fl_Shared_Image* m_insideImage;$/;"	m	class:RevealedModule
+m_insideUpMap	modules/RevealedModule.hpp	/^        std::map<int, bool> m_insideUpMap;$/;"	m	class:RevealedModule
+m_insides	modules/RevealedModule.hpp	/^        std::vector<std::string> m_insides;$/;"	m	class:RevealedModule
+m_intCallback	modules/Attribute.hpp	/^        IntCallback* m_intCallback;$/;"	m	class:Attribute
+m_intValues	modules/Attribute.hpp	/^        std::vector<int> m_intValues;$/;"	m	class:Attribute
+m_intValues	osc/OscManager.hpp	/^    std::vector<int> m_intValues;$/;"	m	struct:OscMessage
+m_keypoints	modules/DepthCamModule.hpp	/^        std::vector<std::vector<cv::KeyPoint> > m_keypoints;$/;"	m	class:ImageTracker
+m_label	gui/ModuleWidget.hpp	/^        std::string m_label;$/;"	m	class:ModuleWidget
+m_label	modules/RevealedTextModule.hpp	/^        Fl_Box* m_label;$/;"	m	class:RevealedTextModule
+m_layers	modules/RevealedModule.hpp	/^        std::vector<RevealedLayer*> m_layers;$/;"	m	class:RevealedModule
+m_layersData	modules/RevealedModule.hpp	/^        char* m_layersData;$/;"	m	class:RevealedModule
+m_layersImages	modules/RevealedModule.hpp	/^        std::vector<Fl_Shared_Image*> m_layersImages;$/;"	m	class:RevealedModule
+m_layersNb	modules/RevealedModule.hpp	/^        int m_layersNb;$/;"	m	class:RevealedModule
+m_listener	gui/ListenerWidget.hpp	/^        Listener* m_listener;$/;"	m	class:ListenerWidget
+m_listenerID	modules/Listener.hpp	/^        int m_listenerID;$/;"	m	class:Listener
+m_listenerType	modules/Listener.hpp	/^        std::string m_listenerType;$/;"	m	class:Listener
+m_listeners	gui/MainWindow.hpp	/^        Fl_Pack* m_listeners;$/;"	m	class:MainWindow
+m_listeners	modules/Attribute.hpp	/^        std::vector<Listener*> m_listeners;$/;"	m	class:Attribute
+m_listenersBut	gui/AttributeWidget.hpp	/^        Fl_Toggle_Button* m_listenersBut;$/;"	m	class:AttributeWidget
+m_listenersDeleteVec	Reveal.hpp	/^        std::vector<Listener*> m_listenersDeleteVec;$/;"	m	class:Reveal
+m_listenersMap	modules/Attribute.hpp	/^        std::map<int, Listener*> m_listenersMap;$/;"	m	class:Attribute
+m_loadable	modules/Attribute.hpp	/^        bool m_loadable;$/;"	m	class:Attribute
+m_localInsideAxes	modules/GeomModule.hpp	/^        bool m_localInsideAxes;$/;"	m	class:GeomModule
+m_lookAt	modules/PreviewModule.hpp	/^        glm::vec3 m_lookAt;$/;"	m	class:PreviewModule
+m_markTexMap	modules/DepthCamModule.hpp	/^        std::map<int, GLuint> m_markTexMap;$/;"	m	class:DepthCamModule
+m_markTexUpMap	modules/DepthCamModule.hpp	/^        std::map<int, bool> m_markTexUpMap;$/;"	m	class:DepthCamModule
+m_markerPosY	modules/DepthCamModule.hpp	/^        int m_markerPosY;$/;"	m	class:DepthCamModule
+m_markerRotX	modules/DepthCamModule.hpp	/^        int m_markerRotX;$/;"	m	class:DepthCamModule
+m_markerRotY	modules/DepthCamModule.hpp	/^        int m_markerRotY;$/;"	m	class:DepthCamModule
+m_markersFrame	modules/DepthCamModule.hpp	/^        unsigned char *m_markersFrame;$/;"	m	class:DepthCamModule
+m_markersThread	modules/DepthCamModule.hpp	/^        std::thread* m_markersThread;$/;"	m	class:DepthCamModule
+m_matcher	modules/DepthCamModule.hpp	/^        cv::Ptr<cv::DescriptorMatcher> m_matcher;$/;"	m	class:ImageTracker
+m_maxNbDepthCams	Reveal.hpp	/^        int m_maxNbDepthCams;$/;"	m	class:Reveal
+m_maxNbMarkers	modules/DepthCamModule.hpp	/^        int m_maxNbMarkers;$/;"	m	class:DepthCamModule
+m_maxNbRevealed	Reveal.hpp	/^        int m_maxNbRevealed;$/;"	m	class:Reveal
+m_measurePixelNb	Reveal.hpp	/^        std::map<int, int> m_measurePixelNb;$/;"	m	class:Reveal
+m_measurePixelTimes	Reveal.hpp	/^        std::map<int, int> m_measurePixelTimes;$/;"	m	class:Reveal
+m_measureTime	Reveal.hpp	/^        timeval m_measureTime;$/;"	m	class:Reveal
+m_measuring	Reveal.hpp	/^        bool m_measuring;$/;"	m	class:Reveal
+m_meshGeom	modules/DepthMeshModule.hpp	/^        Geometry* m_meshGeom;$/;"	m	class:DepthMeshModule
+m_messageSize	osc/OscManager.hpp	/^        size_t m_messageSize;$/;"	m	class:OscManager
+m_messagesRingBuffer	osc/OscManager.hpp	/^        jack_ringbuffer_t* m_messagesRingBuffer;$/;"	m	class:OscManager
+m_mirrored	modules/DepthCamModule.hpp	/^        bool m_mirrored;$/;"	m	class:DepthCamModule
+m_mirrored	modules/ProjectorModule.hpp	/^        bool m_mirrored;$/;"	m	class:ProjectorModule
+m_modelGeom	modules/ModelModule.hpp	/^        Geometry* m_modelGeom;$/;"	m	class:ModelModule
+m_modelMat	modules/Module.hpp	/^        glm::mat4 m_modelMat;$/;"	m	class:Module
+m_modes	modules/DepthCamModule.hpp	/^        std::vector<std::string> m_modes;$/;"	m	class:DepthCamModule
+m_module	gui/ModuleWidget.hpp	/^        Module* m_module;$/;"	m	class:ModuleWidget
+m_module	modules/Attribute.hpp	/^        Module* m_module;$/;"	m	class:Attribute
+m_module	modules/RevealedPathModule.hpp	/^        Module* m_module;$/;"	m	class:PathPointModule
+m_moduleButtonsMap	gui/MainWindow.hpp	/^        std::map<std::string, ModuleWidget*> m_moduleButtonsMap;$/;"	m	class:MainWindow
+m_moduleListObsID	Reveal.hpp	/^        unsigned int m_moduleListObsID;$/;"	m	class:ModuleListObserver
+m_moduleListObservers	Reveal.hpp	/^        std::map<unsigned int, ModuleListObserver*> m_moduleListObservers;$/;"	m	class:Reveal
+m_moduleName	modules/RevealedPathModule.hpp	/^        std::string m_moduleName;$/;"	m	class:PathPointModule
+m_modules	geoms/Geometry.hpp	/^        std::vector<GeomModule*> m_modules;$/;"	m	class:Geometry
+m_modules	gui/MainWindow.hpp	/^        Fl_Pack* m_modules;$/;"	m	class:MainWindow
+m_modulesDeleteVec	Reveal.hpp	/^        std::vector<Module*> m_modulesDeleteVec;$/;"	m	class:Reveal
+m_modulesMap	Reveal.hpp	/^        std::map<std::string, Module*> m_modulesMap;$/;"	m	class:Reveal
+m_modulesMap	geoms/Geometry.hpp	/^        std::map<unsigned int, GeomModule*> m_modulesMap;$/;"	m	class:Geometry
+m_name	gui/AttributeWidget.hpp	/^        std::string m_name;$/;"	m	class:AttributeWidget
+m_name	modules/Attribute.hpp	/^        std::string m_name; $/;"	m	class:Attribute
+m_name	modules/Module.hpp	/^        std::string m_name;$/;"	m	class:Module
+m_name	modules/RevealedCutModule.hpp	/^        std::string m_name;$/;"	m	class:CutWindow
+m_name	osc/OscManager.hpp	/^    std::string m_name;$/;"	m	struct:OscMessage
+m_nbEdges	modules/RevealedPathModule.hpp	/^        int m_nbEdges;$/;"	m	class:RevealedPathModule
+m_nbPixPerRow	modules/RevealedCutModule.hpp	/^        int m_nbPixPerRow;$/;"	m	class:RevealedCutModule
+m_nbValues	gui/AttributeWidget.hpp	/^        unsigned int m_nbValues;$/;"	m	class:AttributeWidget
+m_nbValues	modules/Attribute.hpp	/^        unsigned int m_nbValues;$/;"	m	class:Attribute
+m_near	modules/PreviewModule.hpp	/^        float m_near;$/;"	m	class:PreviewModule
+m_neededFramesNb	modules/ProjectorModule.hpp	/^        int m_neededFramesNb;$/;"	m	class:ProjectorModule
+m_notVoronoi	modules/DepthCamModule.hpp	/^        bool m_notVoronoi;$/;"	m	class:DepthCamModule
+m_offsetX	modules/RevealedCutModule.hpp	/^        int m_offsetX, m_offsetY, m_pixPerRow;$/;"	m	class:CutWindow
+m_offsetY	modules/RevealedCutModule.hpp	/^        int m_offsetX, m_offsetY, m_pixPerRow;$/;"	m	class:CutWindow
+m_open	modules/DepthCamModule.hpp	/^        bool m_open;$/;"	m	class:DepthCamModule
+m_openPlanned	Reveal.hpp	/^        int m_openPlanned;$/;"	m	class:Reveal
+m_openPlannedName	Reveal.hpp	/^        std::string m_openPlannedName;$/;"	m	class:Reveal
+m_outBlobSize	modules/ProjectorModule.hpp	/^        int m_outBlobSize;$/;"	m	class:ProjectorModule
+m_outDepthSize	modules/ProjectorModule.hpp	/^        int m_outDepthSize;$/;"	m	class:ProjectorModule
+m_outNbDepth	modules/ProjectorModule.hpp	/^        int m_outNbDepth;$/;"	m	class:ProjectorModule
+m_outShapeSize	modules/ProjectorModule.hpp	/^        int m_outShapeSize;$/;"	m	class:ProjectorModule
+m_output	gui/AttributeWidget.hpp	/^        Fl_Output* m_output;$/;"	m	class:AttributeWidget
+m_outputActive	modules/RevealedModule.hpp	/^        bool m_outputActive;$/;"	m	class:RevealedModule
+m_outputImg	modules/ProjectorModule.hpp	/^        unsigned char* m_outputImg;$/;"	m	class:ProjectorModule
+m_outputImgInit	modules/ProjectorModule.hpp	/^        unsigned char* m_outputImgInit;$/;"	m	class:ProjectorModule
+m_outputImgSize	modules/ProjectorModule.hpp	/^        unsigned int m_outputImgSize;$/;"	m	class:ProjectorModule
+m_outputTex	modules/ProjectorModule.hpp	/^        GLuint m_outputTex;$/;"	m	class:ProjectorModule
+m_parameters	gui/ListenerWidget.hpp	/^        std::vector<Fl_Input*> m_parameters;$/;"	m	class:ListenerWidget
+m_parameters	modules/Listener.hpp	/^        std::vector<std::string> m_parameters;$/;"	m	class:Listener
+m_parent	modules/Module.hpp	/^        GroupModule* m_parent;$/;"	m	class:Module
+m_parentMat	modules/Module.hpp	/^        glm::mat4 m_parentMat;$/;"	m	class:Module
+m_parentVisible	modules/Module.hpp	/^        bool m_parentVisible;$/;"	m	class:Module
+m_path	modules/RevealedPathModule.hpp	/^        RevealedPathModule* m_path;$/;"	m	class:PathPointModule
+m_pathGeom	modules/RevealedPathModule.hpp	/^        Geometry* m_pathGeom;$/;"	m	class:RevealedPathModule
+m_patternBrightness	modules/ProjectorModule.hpp	/^        int m_patternBrightness;$/;"	m	class:ProjectorModule
+m_patternPosition	modules/ProjectorModule.hpp	/^        cv::Size m_patternPosition; $/;"	m	class:ProjectorModule
+m_patternPositionX	modules/DepthCamModule.hpp	/^        int m_patternPositionX;$/;"	m	class:DepthCamModule
+m_patternPositionY	modules/DepthCamModule.hpp	/^        int m_patternPositionY;$/;"	m	class:DepthCamModule
+m_patternSize	modules/DepthCamModule.hpp	/^        cv::Size m_patternSize;$/;"	m	class:DepthCamModule
+m_patternSize	modules/ProjectorModule.hpp	/^        cv::Size m_patternSize;$/;"	m	class:ProjectorModule
+m_patternSquareWidth	modules/ProjectorModule.hpp	/^        int m_patternSquareWidth; $/;"	m	class:ProjectorModule
+m_patternThresh	modules/ProjectorModule.hpp	/^        int m_patternThresh;$/;"	m	class:ProjectorModule
+m_patternWidth	modules/DepthCamModule.hpp	/^        int m_patternWidth;$/;"	m	class:DepthCamModule
+m_pixPerRow	modules/RevealedCutModule.hpp	/^        int m_offsetX, m_offsetY, m_pixPerRow;$/;"	m	class:CutWindow
+m_playing	modules/RevealedModule.hpp	/^        bool m_playing;$/;"	m	class:RevealedLayer
+m_point	modules/RevealedPathModule.hpp	/^        glm::vec4 m_point;$/;"	m	class:PathPoint
+m_points	geoms/Geometry.hpp	/^        bool m_points;$/;"	m	class:Geometry
+m_points	modules/RevealedPathModule.hpp	/^        std::vector<PathPoint*> m_points;$/;"	m	class:RevealedPathModule
+m_port	osc/OscListener.hpp	/^        unsigned int m_port;$/;"	m	class:OscListener
+m_port	osc/OscManager.hpp	/^    int m_port;$/;"	m	struct:OscStream
+m_posX	modules/ProjectorModule.hpp	/^        float m_posX, m_posY;$/;"	m	class:ProjectorModule
+m_posX	modules/RevealedCutModule.hpp	/^        int m_posX, m_posY, m_width, m_height;$/;"	m	class:CutWindow
+m_posY	modules/ProjectorModule.hpp	/^        float m_posX, m_posY;$/;"	m	class:ProjectorModule
+m_posY	modules/RevealedCutModule.hpp	/^        int m_posX, m_posY, m_width, m_height;$/;"	m	class:CutWindow
+m_position	modules/Module.hpp	/^        glm::vec3 m_position;$/;"	m	class:Module
+m_prevTime	Reveal.hpp	/^        timeval m_prevTime;$/;"	m	class:Reveal
+m_preview	Reveal.hpp	/^        PreviewModule* m_preview;$/;"	m	class:Reveal
+m_previewWindow	modules/PreviewModule.hpp	/^        GLFWwindow* m_previewWindow;$/;"	m	class:PreviewModule
+m_processOutput	modules/ProjectorModule.hpp	/^        bool m_processOutput;$/;"	m	class:ProjectorModule
+m_program	modules/PreviewModule.hpp	/^        GLint m_program;$/;"	m	class:PreviewModule
+m_programs	modules/ProjectorModule.hpp	/^        std::map<Reveal::REVIL_PROGRAM, GLint> m_programs;$/;"	m	class:ProjectorModule
+m_projID	modules/ProjectorModule.hpp	/^        int m_projID;$/;"	m	class:ProjectorModule
+m_projMat	modules/PreviewModule.hpp	/^        glm::mat4 m_projMat;$/;"	m	class:PreviewModule
+m_projMat	modules/ProjectorModule.hpp	/^        glm::mat4 m_projMat;$/;"	m	class:ProjectorModule
+m_projModules	modules/SpaceModule.hpp	/^        std::vector<ProjectorModule*> m_projModules;$/;"	m	class:SpaceModule
+m_projWindow	modules/ProjectorModule.hpp	/^        GLFWwindow* m_projWindow;$/;"	m	class:ProjectorModule
+m_projectedImg	modules/ProjectorModule.hpp	/^        cv::Mat m_projectedImg;$/;"	m	class:ProjectorModule
+m_redTexSize	modules/RevealedModule.hpp	/^        int m_redTexSize;$/;"	m	class:RevealedModule
+m_redXmm	modules/DepthCamModule.hpp	/^        int m_redXmm, m_redYmm, m_redZmm;$/;"	m	class:DepthCamModule
+m_redYmm	modules/DepthCamModule.hpp	/^        int m_redXmm, m_redYmm, m_redZmm;$/;"	m	class:DepthCamModule
+m_redZmm	modules/DepthCamModule.hpp	/^        int m_redXmm, m_redYmm, m_redZmm;$/;"	m	class:DepthCamModule
+m_refresh	geoms/Geometry.hpp	/^    bool m_refresh;$/;"	m	struct:ContextGeometry
+m_registeredOutputDepthCams	Reveal.hpp	/^        std::vector<DepthCamModule*> m_registeredOutputDepthCams;$/;"	m	class:Reveal
+m_registeredOutputRevealed	Reveal.hpp	/^        std::vector<RevealedModule*> m_registeredOutputRevealed;$/;"	m	class:Reveal
+m_removeBut	gui/ListenerWidget.hpp	/^        Fl_Button* m_removeBut;$/;"	m	class:ListenerWidget
+m_removedMarkers	modules/DepthCamModule.hpp	/^        std::vector<s_markerAndTime> m_removedMarkers;$/;"	m	class:DepthCamModule
+m_resImg	modules/DepthCamModule.hpp	/^        cv::Mat m_resImg;$/;"	m	class:DepthCamModule
+m_revAttributes	modules/RevealedModule.hpp	/^        std::vector<Attribute*> m_revAttributes;$/;"	m	class:RevealedModule
+m_revBlob	modules/ProjectorModule.hpp	/^        float m_revSurf, m_revIns, m_revCent, m_revCol, m_revBlob;$/;"	m	class:ProjectorModule
+m_revCent	modules/ProjectorModule.hpp	/^        float m_revSurf, m_revIns, m_revCent, m_revCol, m_revBlob;$/;"	m	class:ProjectorModule
+m_revCol	modules/ProjectorModule.hpp	/^        float m_revSurf, m_revIns, m_revCent, m_revCol, m_revBlob;$/;"	m	class:ProjectorModule
+m_revID	modules/RevealedModule.hpp	/^        unsigned int m_revID;$/;"	m	class:RevealedModule
+m_revIDBit	modules/RevealedModule.hpp	/^        float m_revIDBit;$/;"	m	class:RevealedModule
+m_revIns	modules/ProjectorModule.hpp	/^        float m_revSurf, m_revIns, m_revCent, m_revCol, m_revBlob;$/;"	m	class:ProjectorModule
+m_revSurf	modules/ProjectorModule.hpp	/^        float m_revSurf, m_revIns, m_revCent, m_revCol, m_revBlob;$/;"	m	class:ProjectorModule
+m_revealedBy	modules/Module.hpp	/^        int m_revealedBy;$/;"	m	class:Module
+m_revealedBys	modules/Module.hpp	/^        std::vector<std::string> m_revealedBys;$/;"	m	class:Module
+m_revealedMap	Reveal.hpp	/^        std::map<unsigned int, RevealedModule*> m_revealedMap;$/;"	m	class:Reveal
+m_revealedVec	Reveal.hpp	/^        std::vector<RevealedModule*> m_revealedVec;$/;"	m	class:Reveal
+m_rgbDepthImg	modules/DepthCamModule.hpp	/^        cv::Mat m_rgbDepthImg;$/;"	m	class:DepthCamModule
+m_rgbImg	modules/DepthCamModule.hpp	/^        cv::Mat m_rgbImg;$/;"	m	class:DepthCamModule
+m_rotEuler	modules/Module.hpp	/^        glm::vec3 m_rotEuler;$/;"	m	class:Module
+m_rotMat	modules/Module.hpp	/^        glm::mat4 m_rotMat;$/;"	m	class:Module
+m_rotQuat	modules/Module.hpp	/^        glm::quat m_rotQuat;$/;"	m	class:Module
+m_rows	modules/DepthCamModule.hpp	/^        std::vector<int> m_rows;$/;"	m	class:ImageTracker
+m_rttHeight	modules/ProjectorModule.hpp	/^        int m_rttWidth, m_rttHeight;$/;"	m	class:ProjectorModule
+m_rttWidth	modules/ProjectorModule.hpp	/^        int m_rttWidth, m_rttHeight;$/;"	m	class:ProjectorModule
+m_scale	modules/Module.hpp	/^        glm::vec3 m_scale;$/;"	m	class:Module
+m_scene	Reveal.hpp	/^        RootSceneGroupModule* m_scene;$/;"	m	class:Reveal
+m_scrollAttributes	gui/MainWindow.hpp	/^        Fl_Scroll* m_scrollAttributes;$/;"	m	class:MainWindow
+m_scrollListeners	gui/MainWindow.hpp	/^        Fl_Scroll* m_scrollListeners;$/;"	m	class:MainWindow
+m_scrollModules	gui/MainWindow.hpp	/^        Fl_Scroll* m_scrollModules;$/;"	m	class:MainWindow
+m_selectFBO	modules/ProjectorModule.hpp	/^        GLuint m_selectFBO;$/;"	m	class:ProjectorModule
+m_selectTex	modules/ProjectorModule.hpp	/^        GLuint m_selectTex;$/;"	m	class:ProjectorModule
+m_selectedModulePath	gui/MainWindow.hpp	/^        std::string m_selectedModulePath;$/;"	m	class:MainWindow
+m_sentDetectedMarkers	modules/DepthCamModule.hpp	/^        std::vector<s_markerAndTime> m_sentDetectedMarkers;$/;"	m	class:DepthCamModule
+m_sentRemovedMarkers	modules/DepthCamModule.hpp	/^        std::vector<s_markerAndTime> m_sentRemovedMarkers;$/;"	m	class:DepthCamModule
+m_shapes	modules/ShapeModule.hpp	/^        std::vector<std::string> m_shapes;$/;"	m	class:ShapeModule
+m_shapesMap	modules/ShapeModule.hpp	/^        std::map<std::string, Reveal::GEOM_ID> m_shapesMap;$/;"	m	class:ShapeModule
+m_sliceFBO	modules/ProjectorModule.hpp	/^        GLuint m_sliceFBO;$/;"	m	class:ProjectorModule
+m_sliceRttTex	modules/ProjectorModule.hpp	/^        GLuint m_sliceRttTex;$/;"	m	class:ProjectorModule
+m_sliceSmpTex	modules/ProjectorModule.hpp	/^        GLuint m_sliceSmpTex;$/;"	m	class:ProjectorModule
+m_sliceTex	modules/ProjectorModule.hpp	/^        GLuint m_sliceTex;$/;"	m	class:ProjectorModule
+m_socket	osc/OscManager.hpp	/^        UdpListeningReceiveSocket* m_socket;$/;"	m	class:OscManager
+m_space	modules/DepthModule.hpp	/^        SpaceModule* m_space;$/;"	m	class:DepthModule
+m_space	modules/ProjectorModule.hpp	/^        SpaceModule* m_space;$/;"	m	class:ProjectorModule
+m_spaces	Reveal.hpp	/^        SpacesModule* m_spaces;$/;"	m	class:Reveal
+m_speed	modules/RevealedModule.hpp	/^        float m_speed;$/;"	m	class:RevealedLayer
+m_srcCoords	modules/RevealedCutModule.hpp	/^        std::vector<std::vector<int> > m_srcCoords;$/;"	m	class:RevealedCutModule
+m_srcIndices	modules/RevealedCutModule.hpp	/^        std::vector<int> m_srcIndices;$/;"	m	class:RevealedCutModule
+m_strValues	osc/OscManager.hpp	/^    std::vector<std::string> m_strValues;$/;"	m	struct:OscMessage
+m_stream	osc/OscManager.hpp	/^    osc::OutboundPacketStream* m_stream;$/;"	m	struct:OscStream
+m_streams	modules/DepthCamModule.hpp	/^        openni::VideoStream** m_streams;$/;"	m	class:DepthCamModule
+m_streamsMap	osc/OscManager.hpp	/^        std::map<std::string, OscStream*> m_streamsMap;$/;"	m	class:OscManager
+m_streamsVec	osc/OscManager.hpp	/^        std::vector<OscStream*> m_streamsVec;$/;"	m	class:OscManager
+m_stringCallback	modules/Attribute.hpp	/^        StringCallback* m_stringCallback;$/;"	m	class:Attribute
+m_stringIsChoice	gui/AttributeWidget.hpp	/^        std::vector<bool> m_stringIsChoice;$/;"	m	class:AttributeWidget
+m_stringValues	modules/Attribute.hpp	/^        std::vector<std::string> m_stringValues;$/;"	m	class:Attribute
+m_stringValuesChoices	modules/Attribute.hpp	/^        std::vector<std::vector<std::string> > m_stringValuesChoices;$/;"	m	class:Attribute
+m_surface	modules/RevealedModule.hpp	/^        int m_surface;$/;"	m	class:RevealedModule
+m_surfaceIDMap	modules/RevealedModule.hpp	/^        std::map<int, GLuint> m_surfaceIDMap;$/;"	m	class:RevealedModule
+m_surfaceImage	modules/RevealedModule.hpp	/^        Fl_Shared_Image* m_surfaceImage;$/;"	m	class:RevealedModule
+m_surfaceThickness	modules/RevealedModule.hpp	/^        float m_surfaceThickness;$/;"	m	class:RevealedModule
+m_surfaceUpMap	modules/RevealedModule.hpp	/^        std::map<int, bool> m_surfaceUpMap;$/;"	m	class:RevealedModule
+m_surfaces	modules/RevealedModule.hpp	/^        std::vector<std::string> m_surfaces;$/;"	m	class:RevealedModule
+m_texHeight	modules/Module.hpp	/^        int m_texHeight;$/;"	m	class:Module
+m_texMirrors	modules/RevealedModule.hpp	/^        std::vector<std::string> m_texMirrors;$/;"	m	class:RevealedModule
+m_texWidth	modules/Module.hpp	/^        int m_texWidth;$/;"	m	class:Module
+m_text	modules/RevealedCutModule.hpp	/^        std::string m_text;$/;"	m	class:RevealedCutModule
+m_text	modules/RevealedTextModule.hpp	/^        std::string m_text;$/;"	m	class:RevealedTextModule
+m_textImg	modules/RevealedTextModule.hpp	/^        Fl_RGB_Image* m_textImg;$/;"	m	class:RevealedTextModule
+m_textureOffset	modules/RevealedModule.hpp	/^        float m_textureOffset[3];$/;"	m	class:RevealedModule
+m_textureScale	modules/RevealedModule.hpp	/^        float m_textureScale[3];$/;"	m	class:RevealedModule
+m_thickness	modules/RevealedPathModule.hpp	/^        float m_thickness;$/;"	m	class:RevealedPathModule
+m_thread	osc/OscManager.hpp	/^        pthread_t m_thread;$/;"	m	class:OscManager
+m_timeDiffMs	modules/RevealedModule.hpp	/^        int m_timeDiffMs;$/;"	m	class:RevealedModule
+m_transViewMat	modules/ProjectorModule.hpp	/^        glm::mat4 m_transViewMat;$/;"	m	class:ProjectorModule
+m_transform	modules/Module.hpp	/^        glm::mat4 m_transform;$/;"	m	class:Module
+m_treeWidth	gui/MainWindow.hpp	/^        int m_treeWidth;$/;"	m	class:MainWindow
+m_type	modules/Attribute.hpp	/^        TYPE m_type;$/;"	m	class:Attribute
+m_type	modules/Module.hpp	/^        std::string m_type;$/;"	m	class:Module
+m_typesMap	Reveal.hpp	/^        std::map<std::string, Module*> m_typesMap;$/;"	m	class:Reveal
+m_uniforms	modules/PreviewModule.hpp	/^        std::map<Reveal::REVIL_UNIFORM, GLint> m_uniforms;$/;"	m	class:PreviewModule
+m_uniforms	modules/ProjectorModule.hpp	/^                 std::map<Reveal::REVIL_UNIFORM, GLint> > m_uniforms;$/;"	m	class:ProjectorModule
+m_upCamCounter	modules/DepthCamModule.hpp	/^        std::map<int, int> m_upCamCounter;$/;"	m	class:DepthCamModule
+m_upID	modules/Module.hpp	/^        int m_upID;$/;"	m	class:Module
+m_upObsIdCounter	Reveal.hpp	/^        unsigned int m_upObsIdCounter;$/;"	m	class:Reveal
+m_update	modules/RevealedModule.hpp	/^        bool m_update;$/;"	m	class:RevealedLayer
+m_updateObservers	Reveal.hpp	/^        std::vector<Module*> m_updateObservers;$/;"	m	class:Reveal
+m_updateOnce	modules/RevealedCutModule.hpp	/^        bool m_updateOnce;$/;"	m	class:RevealedCutModule
+m_updateOnceDone	modules/RevealedCutModule.hpp	/^        bool m_updateOnceDone;$/;"	m	class:RevealedCutModule
+m_upsideDown	modules/DepthCamModule.hpp	/^        bool m_upsideDown;$/;"	m	class:DepthCamModule
+m_url	osc/OscListener.hpp	/^        std::string m_url;$/;"	m	class:OscListener
+m_valueInputs	gui/AttributeWidget.hpp	/^        std::vector<Fl_Value_Input*> m_valueInputs;$/;"	m	class:AttributeWidget
+m_valuesLabels	modules/Attribute.hpp	/^        std::vector<std::string> m_valuesLabels;$/;"	m	class:Attribute
+m_valuesMax	modules/Attribute.hpp	/^        std::vector<float> m_valuesMax;$/;"	m	class:Attribute
+m_valuesMin	modules/Attribute.hpp	/^        std::vector<float> m_valuesMin;$/;"	m	class:Attribute
+m_vertexArrayID	geoms/Geometry.hpp	/^    GLuint m_vertexArrayID;$/;"	m	struct:ContextGeometry
+m_vertexBuffer	geoms/Geometry.hpp	/^    GLuint m_vertexBuffer;$/;"	m	struct:ContextGeometry
+m_vertexBufferData	geoms/Geometry.hpp	/^        std::vector<GLfloat> m_vertexBufferData;$/;"	m	class:Geometry
+m_verticalFOV	modules/DepthCamModule.hpp	/^        double m_horizontalFOV, m_verticalFOV;$/;"	m	class:DepthCamModule
+m_video	modules/RevealedModule.hpp	/^        cv::VideoCapture m_video;$/;"	m	class:RevealedLayerVideo
+m_viewMat	modules/PreviewModule.hpp	/^        glm::mat4 m_viewMat;$/;"	m	class:PreviewModule
+m_viewMat	modules/ProjectorModule.hpp	/^        glm::mat4 m_viewMat;$/;"	m	class:ProjectorModule
+m_viewProjMat	modules/PreviewModule.hpp	/^        glm::mat4 m_viewProjMat;$/;"	m	class:PreviewModule
+m_viewProjMat	modules/ProjectorModule.hpp	/^        glm::mat4 m_viewProjMat;$/;"	m	class:ProjectorModule
+m_viewProjUniform	modules/PreviewModule.hpp	/^        GLint m_viewProjUniform;$/;"	m	class:PreviewModule
+m_visibilityMask	modules/Module.hpp	/^        int m_visibilityMask;$/;"	m	class:Module
+m_visible	modules/Module.hpp	/^        bool m_visible;$/;"	m	class:Module
+m_visibleFromMap	Reveal.hpp	/^        std::map<std::string, int> m_visibleFromMap;$/;"	m	class:Reveal
+m_visibleFromVec	Reveal.hpp	/^        std::vector<std::string> m_visibleFromVec;$/;"	m	class:Reveal
+m_volumeTextureHeight	modules/RevealedModule.hpp	/^        int m_volumeTextureHeight;$/;"	m	class:RevealedModule
+m_volumeTextureWidth	modules/RevealedModule.hpp	/^        int m_volumeTextureWidth;$/;"	m	class:RevealedModule
+m_width	modules/DepthCamModule.hpp	/^        uint16_t m_width, m_height, m_fps;$/;"	m	class:DepthCamModule
+m_width	modules/ProjectorModule.hpp	/^        float m_width, m_height;$/;"	m	class:ProjectorModule
+m_width	modules/RevealedCutModule.hpp	/^        int m_posX, m_posY, m_width, m_height;$/;"	m	class:CutWindow
+m_win	modules/RevealedCutModule.hpp	/^        Window m_win;$/;"	m	class:CutWindow
+m_winH	modules/RevealedCutModule.hpp	/^        int m_winX, m_winY, m_winW, m_winH;$/;"	m	class:RevealedCutModule
+m_winID	modules/RevealedCutModule.hpp	/^        int m_winID;$/;"	m	class:CutWindow
+m_winW	modules/RevealedCutModule.hpp	/^        int m_winX, m_winY, m_winW, m_winH;$/;"	m	class:RevealedCutModule
+m_winX	modules/RevealedCutModule.hpp	/^        int m_winX, m_winY, m_winW, m_winH;$/;"	m	class:RevealedCutModule
+m_winY	modules/RevealedCutModule.hpp	/^        int m_winX, m_winY, m_winW, m_winH;$/;"	m	class:RevealedCutModule
+m_windowList	modules/RevealedCutModule.hpp	/^        std::vector<CutWindow*> m_windowList;$/;"	m	class:CutWindowsManager
+m_windowMap	modules/RevealedCutModule.hpp	/^        std::map<unsigned int, CutWindow*> m_windowMap;$/;"	m	class:CutWindowsManager
+m_winsMan	modules/RevealedCutModule.hpp	/^        CutWindowsManager* m_winsMan;$/;"	m	class:CutWindow
+m_worldCorners	modules/DepthCamModule.hpp	/^        std::vector<cv::Point3f> m_worldCorners;$/;"	m	class:DepthCamModule
+m_ximg	modules/RevealedCutModule.hpp	/^        XImage* m_ximg;$/;"	m	class:CutWindow
+main	Reveal.cpp	/^int main( int argc, char **argv ) {$/;"	f
+markersDetectionCallback	modules/DepthCamModule.hpp	/^        static void markersDetectionCallback(Module* mod,$/;"	f	class:DepthCamModule
+markersDetectionMethodCallback	modules/DepthCamModule.hpp	/^        static void markersDetectionMethodCallback(Module* mod,$/;"	f	class:DepthCamModule
+markersThreadFunction	modules/DepthCamModule.cpp	/^void* markersThreadFunction(void* pvParam) {$/;"	f
+measureStart	Reveal.cpp	/^void Reveal::measureStart() {$/;"	f	class:Reveal
+measureStart	Reveal.hpp	/^        void measureStart();$/;"	p	class:Reveal
+measureStore	Reveal.cpp	/^void Reveal::measureStore(const int& nbPixels) {$/;"	f	class:Reveal
+measureStore	Reveal.hpp	/^        void measureStore(const int& nbPixels);$/;"	p	class:Reveal
+messageCursor_	osc/oscPack/osc/OscOutboundPacketStream.h	/^    char *messageCursor_;$/;"	m	class:osc::OutboundPacketStream
+messageIsInProgress_	osc/oscPack/osc/OscOutboundPacketStream.h	/^    bool messageIsInProgress_;$/;"	m	class:osc::OutboundPacketStream
+mirroredCallback	modules/ProjectorModule.hpp	/^        static void mirroredCallback(Module* mod, $/;"	f	class:ProjectorModule
+mlocked	osc/ringbuffer.c	/^    int	mlocked;$/;"	m	struct:__anon7	file:
+mlocked	osc/ringbuffer.h	/^    int	mlocked;$/;"	m	struct:__anon2
+modeCallback	modules/DepthCamModule.hpp	/^        static void modeCallback(Module* mod,$/;"	f	class:DepthCamModule
+modelCallback	modules/ModelModule.hpp	/^        static void modelCallback(Module* mod, $/;"	f	class:ModelModule
+multiplexerInstanceToAbortWithSigInt_	osc/oscPack/ip/posix/UdpSocket.cpp	/^SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;$/;"	v
+multiplexerInstanceToAbortWithSigInt_	osc/oscPack/ip/win32/UdpSocket.cpp	/^SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;$/;"	v
+mux_	osc/oscPack/ip/UdpSocket.h	/^    SocketReceiveMultiplexer mux_;$/;"	m	class:UdpListeningReceiveSocket
+nameCallback	modules/DepthGroupModule.hpp	/^        static void nameCallback(Module* mod, $/;"	f	class:DepthGroupModule
+nameCallback	modules/Module.hpp	/^        static void nameCallback(Module* mod, $/;"	f	class:Module
+nameCallback	modules/SceneGroupModule.hpp	/^        static void nameCallback(Module* mod, $/;"	f	class:SceneGroupModule
+networkInitializer_	osc/oscPack/ip/win32/UdpSocket.cpp	/^    NetworkInitializer networkInitializer_;$/;"	m	class:SocketReceiveMultiplexer::Implementation	file:
+networkInitializer_	osc/oscPack/ip/win32/UdpSocket.cpp	/^    NetworkInitializer networkInitializer_;$/;"	m	class:UdpSocket::Implementation	file:
+newSetOfPoint	modules/DepthCamModule.cpp	/^vector<cv::Point2f> DepthCamModule::newSetOfPoint(vector<cv::Point2f> points, $/;"	f	class:DepthCamModule
+newSetOfPoint	modules/DepthCamModule.hpp	/^        std::vector<cv::Point2f> newSetOfPoint(std::vector<cv::Point2f> points, $/;"	p	class:DepthCamModule
+open	Reveal.cpp	/^void Reveal::open(const std::string& fileName) {$/;"	f	class:Reveal
+open	Reveal.hpp	/^        void open(const std::string& f);$/;"	p	class:Reveal
+openCallback	Reveal.hpp	/^        static void openCallback(Module* mod, const std::string& f) {$/;"	f	class:Reveal
+openDevice	modules/DepthCamModule.cpp	/^void DepthCamModule::openDevice(const std::string& devStr, bool calib) {$/;"	f	class:DepthCamModule
+openDevice	modules/DepthCamModule.hpp	/^        virtual void openDevice(const std::string& dev, bool calib=false);$/;"	p	class:DepthCamModule
+operator !=	osc/oscPack/ip/IpEndpointName.h	/^inline bool operator!=( const IpEndpointName& lhs, const IpEndpointName& rhs )$/;"	f
+operator !=	osc/oscPack/osc/OscReceivedElements.h	/^inline bool operator!=(const ReceivedBundleElementIterator& lhs,$/;"	f	namespace:osc
+operator !=	osc/oscPack/osc/OscReceivedElements.h	/^inline bool operator!=(const ReceivedMessageArgumentIterator& lhs,$/;"	f	namespace:osc
+operator ()	osc/oscPack/osc/MessageMappingOscPacketListener.h	/^        bool operator()( const char *lhs, const char *rhs ) const$/;"	f	struct:osc::MessageMappingOscPacketListener::cstr_compare
+operator *	osc/oscPack/osc/OscReceivedElements.h	/^	const ReceivedBundleElement& operator*() const { return value_; }$/;"	f	class:osc::ReceivedBundleElementIterator
+operator *	osc/oscPack/osc/OscReceivedElements.h	/^	const ReceivedMessageArgument& operator*() const { return value_; }$/;"	f	class:osc::ReceivedMessageArgumentIterator
+operator ++	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedBundleElementIterator operator++()$/;"	f	class:osc::ReceivedBundleElementIterator
+operator ++	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedMessageArgumentIterator operator++()$/;"	f	class:osc::ReceivedMessageArgumentIterator
+operator ++	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedBundleElementIterator operator++(int)$/;"	f	class:osc::ReceivedBundleElementIterator
+operator ++	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentIterator operator++(int)$/;"	f	class:osc::ReceivedMessageArgumentIterator
+operator ->	osc/oscPack/osc/OscReceivedElements.h	/^    const ReceivedBundleElement* operator->() const { return &value_; }$/;"	f	class:osc::ReceivedBundleElementIterator
+operator ->	osc/oscPack/osc/OscReceivedElements.h	/^    const ReceivedMessageArgument* operator->() const { return &value_; }$/;"	f	class:osc::ReceivedMessageArgumentIterator
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( bool rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( char rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayTerminator& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const BundleTerminator& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const InfinitumType& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const MidiMessage& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const NilType& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const RgbaColor& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const TimeTag& rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( float rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( int32 rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream& OutboundPacketStream::operator<<( int64 rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( bool rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( char rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const ArrayInitiator& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const ArrayTerminator& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const BeginMessage& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const Blob& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const BundleInitiator& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const BundleTerminator& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const InfinitumType& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const MessageTerminator& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const MidiMessage& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const NilType& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const RgbaColor& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const Symbol& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const TimeTag& rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( const char* rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( double rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( float rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( int rhs )$/;"	f	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( int32 rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscOutboundPacketStream.h	/^    OutboundPacketStream& operator<<( int64 rhs );$/;"	p	class:osc::OutboundPacketStream
+operator <<	osc/oscPack/osc/OscPrintReceivedElements.cpp	/^std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b )$/;"	f	namespace:osc
+operator <<	osc/oscPack/osc/OscPrintReceivedElements.cpp	/^std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m )$/;"	f	namespace:osc
+operator <<	osc/oscPack/osc/OscPrintReceivedElements.cpp	/^std::ostream& operator<<( std::ostream & os, const ReceivedPacket& p )$/;"	f	namespace:osc
+operator <<	osc/oscPack/osc/OscPrintReceivedElements.cpp	/^std::ostream& operator<<( std::ostream & os,$/;"	f	namespace:osc
+operator <<	osc/oscPack/osc/OscPrintReceivedElements.h	/^std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b );$/;"	p	namespace:osc
+operator <<	osc/oscPack/osc/OscPrintReceivedElements.h	/^std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m );$/;"	p	namespace:osc
+operator <<	osc/oscPack/osc/OscPrintReceivedElements.h	/^std::ostream& operator<<( std::ostream & os, const ReceivedMessageArgument& arg );$/;"	p	namespace:osc
+operator <<	osc/oscPack/osc/OscPrintReceivedElements.h	/^std::ostream& operator<<( std::ostream & os, const ReceivedPacket& p );$/;"	p	namespace:osc
+operator =	osc/oscPack/osc/OscException.h	/^    Exception& operator=( const Exception& src ) throw()$/;"	f	class:osc::Exception
+operator ==	osc/oscPack/ip/IpEndpointName.h	/^inline bool operator==( const IpEndpointName& lhs, const IpEndpointName& rhs )$/;"	f
+operator ==	osc/oscPack/osc/OscReceivedElements.h	/^	friend bool operator==(const ReceivedBundleElementIterator& lhs,$/;"	p	class:osc::ReceivedBundleElementIterator
+operator ==	osc/oscPack/osc/OscReceivedElements.h	/^	friend bool operator==(const ReceivedMessageArgumentIterator& lhs,$/;"	p	class:osc::ReceivedMessageArgumentIterator
+operator ==	osc/oscPack/osc/OscReceivedElements.h	/^inline bool operator==(const ReceivedBundleElementIterator& lhs,$/;"	f	namespace:osc
+operator ==	osc/oscPack/osc/OscReceivedElements.h	/^inline bool operator==(const ReceivedMessageArgumentIterator& lhs,$/;"	f	namespace:osc
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( Blob& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( MidiMessage& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( RgbaColor& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( Symbol& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( TimeTag& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( bool& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( char& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( const char*& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( double& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( float& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( int32& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator >>	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentStream& operator>>( int64& rhs )$/;"	f	class:osc::ReceivedMessageArgumentStream
+operator const char *	osc/oscPack/osc/OscTypes.h	/^    operator const char *() const { return value; }$/;"	f	struct:osc::Symbol
+operator uint32	osc/oscPack/osc/OscTypes.h	/^    operator uint32() const { return value; }$/;"	f	struct:osc::MidiMessage
+operator uint32	osc/oscPack/osc/OscTypes.h	/^    operator uint32() const { return value; }$/;"	f	struct:osc::RgbaColor
+operator uint64	osc/oscPack/osc/OscTypes.h	/^    operator uint64() const { return value; }$/;"	f	struct:osc::TimeTag
+orientation	modules/DepthCamModule.hpp	/^    glm::vec3 orientation;$/;"	m	struct:s_markerAndTime
+osc	osc/oscPack/osc/MessageMappingOscPacketListener.h	/^namespace osc{$/;"	n
+osc	osc/oscPack/osc/OscException.h	/^namespace osc{$/;"	n
+osc	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^namespace osc{$/;"	n	file:
+osc	osc/oscPack/osc/OscOutboundPacketStream.h	/^namespace osc{$/;"	n
+osc	osc/oscPack/osc/OscPacketListener.h	/^namespace osc{$/;"	n
+osc	osc/oscPack/osc/OscPrintReceivedElements.cpp	/^namespace osc{$/;"	n	file:
+osc	osc/oscPack/osc/OscPrintReceivedElements.h	/^namespace osc{$/;"	n
+osc	osc/oscPack/osc/OscReceivedElements.cpp	/^namespace osc{$/;"	n	file:
+osc	osc/oscPack/osc/OscReceivedElements.h	/^namespace osc{$/;"	n
+osc	osc/oscPack/osc/OscTypes.cpp	/^namespace osc{$/;"	n	file:
+osc	osc/oscPack/osc/OscTypes.h	/^namespace osc{$/;"	n
+oscThreadFunction	osc/OscManager.cpp	/^void* oscThreadFunction(void* pvParam) {$/;"	f
+osc_bundle_element_size_t	osc/oscPack/osc/OscTypes.h	/^typedef int32 osc_bundle_element_size_t;$/;"	t	namespace:osc
+outputMarkers	modules/DepthCamModule.hpp	/^        inline void outputMarkers(const std::vector<float>& vals){}$/;"	f	class:DepthCamModule
+outputMarkersCallback	modules/DepthCamModule.hpp	/^        static void outputMarkersCallback(Module* mod,$/;"	f	class:DepthCamModule
+outputRevealed	modules/ProjectorModule.cpp	/^void ProjectorModule::outputRevealed(bool output) {$/;"	f	class:ProjectorModule
+outputRevealed	modules/ProjectorModule.hpp	/^        void outputRevealed(bool output);$/;"	p	class:ProjectorModule
+outputRevealedCallback	modules/ProjectorModule.hpp	/^        static void outputRevealedCallback(Module* mod, $/;"	f	class:ProjectorModule
+p_	osc/oscPack/osc/OscReceivedElements.h	/^    ReceivedMessageArgumentIterator p_, end_;$/;"	m	class:osc::ReceivedMessageArgumentStream
+periodMs	osc/oscPack/ip/posix/UdpSocket.cpp	/^	int periodMs;$/;"	m	struct:AttachedTimerListener	file:
+periodMs	osc/oscPack/ip/win32/UdpSocket.cpp	/^	int periodMs;$/;"	m	struct:AttachedTimerListener	file:
+plan	modules/DepthCamModule.hpp	/^    int plan = -1;$/;"	m	struct:s_markerAndTime
+planOpen	Reveal.cpp	/^void Reveal::planOpen(std::string opSt) {$/;"	f	class:Reveal
+planOpen	Reveal.hpp	/^        void planOpen(std::string);    $/;"	p	class:Reveal
+port	osc/oscPack/ip/IpEndpointName.h	/^    int port;$/;"	m	class:IpEndpointName
+pos	modules/ModelModule.hpp	/^            glm::vec3 pos;$/;"	m	struct:ModelModule::ModelVertex
+positionCallback	modules/Module.hpp	/^        static void positionCallback(Module* mod, $/;"	f	class:Module
+positionCallback	modules/SceneGroupModule.hpp	/^        static void positionCallback(Module* mod, $/;"	f	class:SceneGroupModule
+processCursor	modules/DepthCamModule.cpp	/^void DepthCamModule::processCursor(const std::vector<float>& pos) {$/;"	f	class:DepthCamModule
+processCursor	modules/DepthCamModule.hpp	/^        void processCursor(const std::vector<float>& pos);$/;"	p	class:DepthCamModule
+processOutput	modules/ProjectorModule.cpp	/^void ProjectorModule::processOutput() {$/;"	f	class:ProjectorModule
+processOutput	modules/ProjectorModule.hpp	/^        void processOutput();$/;"	p	class:ProjectorModule
+processReveal	modules/RevealedModule.cpp	/^void RevealedModule::processReveal(const unsigned int& depthID,$/;"	f	class:RevealedModule
+processReveal	modules/RevealedModule.hpp	/^        virtual void processReveal(const unsigned int& id,$/;"	p	class:RevealedModule
+processReveal	modules/RevealedPathModule.cpp	/^void RevealedPathModule::processReveal(const vector<string>& names,$/;"	f	class:RevealedPathModule
+processReveal	modules/RevealedPathModule.hpp	/^        virtual void processReveal(const std::vector<std::string>&, $/;"	p	class:RevealedPathModule
+projectionMatrixCallback	modules/ProjectorModule.hpp	/^        static void projectionMatrixCallback(Module* mod, $/;"	f	class:ProjectorModule
+quaternionCallback	modules/Module.hpp	/^        static void quaternionCallback(Module* mod, $/;"	f	class:Module
+quit	Reveal.cpp	/^void Reveal::quit() {$/;"	f	class:Reveal
+quit	Reveal.hpp	/^        void quit();$/;"	p	class:Reveal
+quitCallback	Reveal.hpp	/^        static void quitCallback(Module* mod) {$/;"	f	class:Reveal
+read_ptr	osc/ringbuffer.c	/^    volatile size_t read_ptr;$/;"	m	struct:__anon7	file:
+read_ptr	osc/ringbuffer.h	/^    volatile size_t read_ptr;$/;"	m	struct:__anon2
+recomputePixels	modules/RevealedCutModule.cpp	/^void RevealedCutModule::recomputePixels() {$/;"	f	class:RevealedCutModule
+recomputePixels	modules/RevealedCutModule.hpp	/^        void recomputePixels();$/;"	p	class:RevealedCutModule
+refresh	geoms/Geometry.cpp	/^void Geometry::refresh() {$/;"	f	class:Geometry
+refresh	geoms/Geometry.hpp	/^        void refresh();$/;"	p	class:Geometry
+refreshDepthCamList	modules/ProjectorModule.cpp	/^void ProjectorModule::refreshDepthCamList(const vector<DepthCamModule*> cams) {$/;"	f	class:ProjectorModule
+refreshDepthCamList	modules/ProjectorModule.hpp	/^        void refreshDepthCamList(const std::vector<DepthCamModule*>);$/;"	p	class:ProjectorModule
+refreshDepthCamList	modules/SpaceModule.cpp	/^void SpaceModule::refreshDepthCamList() {$/;"	f	class:SpaceModule
+refreshDepthCamList	modules/SpaceModule.hpp	/^        void refreshDepthCamList();$/;"	p	class:SpaceModule
+refreshGeometry	modules/RevealedPathModule.cpp	/^void RevealedPathModule::refreshGeometry() {$/;"	f	class:RevealedPathModule
+refreshGeometry	modules/RevealedPathModule.hpp	/^        void refreshGeometry();$/;"	p	class:RevealedPathModule
+refreshModules	Reveal.cpp	/^void Reveal::refreshModules() {$/;"	f	class:Reveal
+refreshModules	Reveal.hpp	/^        void refreshModules();$/;"	p	class:Reveal
+refreshModules	gui/MainWindow.cpp	/^void MainWindow::refreshModules(bool clearAttributes, bool clearListeners) {$/;"	f	class:MainWindow
+refreshModules	gui/MainWindow.hpp	/^        void refreshModules(bool clearAttributes=false, $/;"	p	class:MainWindow
+refreshMonitors	modules/ProjectorModule.cpp	/^void ProjectorModule::refreshMonitors(){$/;"	f	class:ProjectorModule
+refreshMonitors	modules/ProjectorModule.hpp	/^        void refreshMonitors();$/;"	p	class:ProjectorModule
+refreshPos	modules/RevealedPathModule.cpp	/^void PathPointModule::refreshPos() {$/;"	f	class:PathPointModule
+refreshPos	modules/RevealedPathModule.hpp	/^        virtual void refreshPos();$/;"	p	class:PathPointModule
+refreshPos	modules/RevealedPathModule.hpp	/^        virtual void refreshPos(){}$/;"	f	class:PathPoint
+refreshProjList	modules/DepthCamModule.cpp	/^void DepthCamModule::refreshProjList(const vector<ProjectorModule*> projs) {$/;"	f	class:DepthCamModule
+refreshProjList	modules/DepthCamModule.hpp	/^        void refreshProjList(const std::vector<ProjectorModule*> projs);$/;"	p	class:DepthCamModule
+refreshProjList	modules/SpaceModule.cpp	/^void SpaceModule::refreshProjList() {$/;"	f	class:SpaceModule
+refreshProjList	modules/SpaceModule.hpp	/^        void refreshProjList();$/;"	p	class:SpaceModule
+refreshWindows	modules/RevealedCutModule.cpp	/^void RevealedCutModule::refreshWindows() {$/;"	f	class:RevealedCutModule
+refreshWindows	modules/RevealedCutModule.hpp	/^        virtual void refreshWindows();$/;"	p	class:RevealedCutModule
+refreshWindowsCallback	modules/RevealedCutModule.hpp	/^        static void refreshWindowsCallback(Module* mod) {$/;"	f	class:RevealedCutModule
+registerGeom	Reveal.cpp	/^void Reveal::registerGeom(Geometry* geom) {$/;"	f	class:Reveal
+registerGeom	Reveal.hpp	/^        void registerGeom(Geometry* geom);$/;"	p	class:Reveal
+registerGeom	modules/SpaceModule.cpp	/^void SpaceModule::registerGeom(Geometry* geom) {$/;"	f	class:SpaceModule
+registerGeom	modules/SpaceModule.hpp	/^        void registerGeom(Geometry* geom);$/;"	p	class:SpaceModule
+registerModule	geoms/Geometry.cpp	/^void Geometry::registerModule(GeomModule* geom) {$/;"	f	class:Geometry
+registerModule	geoms/Geometry.hpp	/^        void registerModule(GeomModule*);$/;"	p	class:Geometry
+registerOutputDepthCam	Reveal.cpp	/^void Reveal::registerOutputDepthCam(DepthCamModule* cam) {$/;"	f	class:Reveal
+registerOutputDepthCam	Reveal.hpp	/^        void registerOutputDepthCam(DepthCamModule* cam);$/;"	p	class:Reveal
+registerOutputRevealed	Reveal.cpp	/^void Reveal::registerOutputRevealed(RevealedModule* rev) {$/;"	f	class:Reveal
+registerOutputRevealed	Reveal.hpp	/^        void registerOutputRevealed(RevealedModule* rev);$/;"	p	class:Reveal
+registerRevealed	Reveal.cpp	/^void Reveal::registerRevealed(RevealedModule* rev) {$/;"	f	class:Reveal
+registerRevealed	Reveal.hpp	/^        void registerRevealed(RevealedModule*);$/;"	p	class:Reveal
+releaseImage	modules/RevealedCutModule.cpp	/^void CutWindow::releaseImage() {$/;"	f	class:CutWindow
+releaseImage	modules/RevealedCutModule.hpp	/^        void releaseImage();$/;"	p	class:CutWindow
+removeCallback	modules/Module.hpp	/^        static void removeCallback(Module* mod) {$/;"	f	class:Module
+removeCam	modules/SpaceModule.cpp	/^void SpaceModule::removeCam(DepthCamModule* cam) {$/;"	f	class:SpaceModule
+removeCam	modules/SpaceModule.hpp	/^        void removeCam(DepthCamModule*);$/;"	p	class:SpaceModule
+removeChild	modules/GroupModule.cpp	/^void GroupModule::removeChild(Module* mod) {$/;"	f	class:GroupModule
+removeChild	modules/GroupModule.hpp	/^        virtual void removeChild(Module* mod);$/;"	p	class:GroupModule
+removeContextHandler	Reveal.cpp	/^void Reveal::removeContextHandler(ContextHandler* cont) {$/;"	f	class:Reveal
+removeContextHandler	Reveal.hpp	/^        void removeContextHandler(ContextHandler* cont);$/;"	p	class:Reveal
+removeDepthModule	modules/SpaceModule.cpp	/^void SpaceModule::removeDepthModule(DepthModule* mod) {$/;"	f	class:SpaceModule
+removeDepthModule	modules/SpaceModule.hpp	/^        void removeDepthModule(DepthModule*);$/;"	p	class:SpaceModule
+removeListener	modules/Attribute.cpp	/^void Attribute::removeListener(Listener* lis) {$/;"	f	class:Attribute
+removeListener	modules/Attribute.hpp	/^        void removeListener(Listener* lis);$/;"	p	class:Attribute
+removeModuleListObserver	Reveal.cpp	/^void Reveal::removeModuleListObserver(ModuleListObserver* obs) {$/;"	f	class:Reveal
+removeModuleListObserver	Reveal.hpp	/^        void removeModuleListObserver(ModuleListObserver* obs);$/;"	p	class:Reveal
+removePoint	modules/RevealedPathModule.cpp	/^void RevealedPathModule::removePoint() {$/;"	f	class:RevealedPathModule
+removePoint	modules/RevealedPathModule.hpp	/^        void removePoint();$/;"	p	class:RevealedPathModule
+removePointCallback	modules/RevealedPathModule.hpp	/^        static void removePointCallback(Module* mod) {$/;"	f	class:RevealedPathModule
+removeProj	modules/SpaceModule.cpp	/^void SpaceModule::removeProj(ProjectorModule* proj) {$/;"	f	class:SpaceModule
+removeProj	modules/SpaceModule.hpp	/^        void removeProj(ProjectorModule*);$/;"	p	class:SpaceModule
+removeUpdateObserver	Reveal.cpp	/^void Reveal::removeUpdateObserver(Module* upObs) {$/;"	f	class:Reveal
+removeUpdateObserver	Reveal.hpp	/^        void removeUpdateObserver(Module* upObs);$/;"	p	class:Reveal
+ressourcesCallback	Reveal.hpp	/^        static void ressourcesCallback(Module* mod, const std::string& f) {$/;"	f	class:Reveal
+revblobCallback	modules/RevealedModule.hpp	/^        static void revblobCallback(Module* mod,const std::vector<float>&vals){}$/;"	f	class:RevealedModule
+revcentCallback	modules/RevealedModule.hpp	/^        static void revcentCallback(Module* mod,const std::vector<float>&vals){}$/;"	f	class:RevealedModule
+revcolCallback	modules/RevealedModule.hpp	/^        static void revcolCallback(Module* mod,const std::vector<float>& vals){}$/;"	f	class:RevealedModule
+revealedByCallback	modules/Module.hpp	/^        static void revealedByCallback(Module* mod, $/;"	f	class:Module
+revextCallback	modules/RevealedModule.hpp	/^        static void revextCallback(Module* mod,const std::vector<float>&vals){}$/;"	f	class:RevealedModule
+revinsCallback	modules/RevealedModule.hpp	/^        static void revinsCallback(Module* mod,const std::vector<float>& vals){}$/;"	f	class:RevealedModule
+revnamCallback	modules/RevealedModule.hpp	/^        static void revnamCallback(Module* mod, $/;"	f	class:RevealedModule
+revsurCallback	modules/RevealedModule.hpp	/^        static void revsurCallback(Module* mod,const std::vector<float>& vals){}$/;"	f	class:RevealedModule
+rotationCallback	modules/Module.hpp	/^        static void rotationCallback(Module* mod, $/;"	f	class:Module
+rotationCallback	modules/SceneGroupModule.hpp	/^        static void rotationCallback(Module* mod, $/;"	f	class:SceneGroupModule
+run	Reveal.cpp	/^int Reveal::run() {$/;"	f	class:Reveal
+run	Reveal.hpp	/^        int run();$/;"	p	class:Reveal
+run	osc/OscManager.hpp	/^        int run();$/;"	p	class:OscManager
+s_markerAndTime	modules/DepthCamModule.hpp	/^struct s_markerAndTime{$/;"	s
+save	Reveal.cpp	/^void Reveal::save(const std::string& fileName) {$/;"	f	class:Reveal
+save	Reveal.hpp	/^        void save(const std::string& f);$/;"	p	class:Reveal
+save	modules/Attribute.cpp	/^void Attribute::save(xmlNodePtr parentNode) {$/;"	f	class:Attribute
+save	modules/Attribute.hpp	/^        void save(xmlNodePtr parentNode);$/;"	p	class:Attribute
+save	modules/GroupModule.cpp	/^xmlNodePtr GroupModule::save(xmlNodePtr parentNode) {$/;"	f	class:GroupModule
+save	modules/GroupModule.hpp	/^        virtual xmlNodePtr save(xmlNodePtr parentNode);$/;"	p	class:GroupModule
+save	modules/Listener.cpp	/^void Listener::save(xmlNodePtr parentNode) {$/;"	f	class:Listener
+save	modules/Listener.hpp	/^        virtual void save(xmlNodePtr parentNode);$/;"	p	class:Listener
+save	modules/Module.cpp	/^xmlNodePtr Module::save(xmlNodePtr parentNode) {$/;"	f	class:Module
+save	modules/Module.hpp	/^        virtual xmlNodePtr save(xmlNodePtr parentNode);$/;"	p	class:Module
+save	modules/RevealedPathModule.cpp	/^xmlNodePtr RevealedPathModule::save(xmlNodePtr parentNode) {$/;"	f	class:RevealedPathModule
+save	modules/RevealedPathModule.hpp	/^        virtual xmlNodePtr save(xmlNodePtr parentNode);$/;"	p	class:RevealedPathModule
+saveCallback	Reveal.hpp	/^        static void saveCallback(Module* mod, const std::string& f) {$/;"	f	class:Reveal
+savePnt	modules/RevealedPathModule.cpp	/^xmlNodePtr PathPoint::savePnt(xmlNodePtr parentNode) {$/;"	f	class:PathPoint
+savePnt	modules/RevealedPathModule.cpp	/^xmlNodePtr PathPointModule::savePnt(xmlNodePtr parentNode) {$/;"	f	class:PathPointModule
+savePnt	modules/RevealedPathModule.hpp	/^        virtual xmlNodePtr savePnt(xmlNodePtr parentNode);$/;"	p	class:PathPoint
+savePnt	modules/RevealedPathModule.hpp	/^        virtual xmlNodePtr savePnt(xmlNodePtr parentNode);$/;"	p	class:PathPointModule
+scaleCallback	modules/Module.hpp	/^        static void scaleCallback(Module* mod, $/;"	f	class:Module
+scaleCallback	modules/SceneGroupModule.hpp	/^        static void scaleCallback(Module* mod, $/;"	f	class:SceneGroupModule
+selPos	modules/RevealedCutModule.cpp	/^void RevealedCutModule::selPos(const int& posX, const int& posY) {$/;"	f	class:RevealedCutModule
+selPos	modules/RevealedCutModule.hpp	/^        void selPos(const int& posX, const int& posY);$/;"	p	class:RevealedCutModule
+selPosCallback	modules/RevealedCutModule.hpp	/^        static void selPosCallback(Module* mod, $/;"	f	class:RevealedCutModule
+selSize	modules/RevealedCutModule.cpp	/^void RevealedCutModule::selSize(const int& sizeX, const int& sizeY) {$/;"	f	class:RevealedCutModule
+selSize	modules/RevealedCutModule.hpp	/^        void selSize(const int& sizeX, const int& sizeY);$/;"	p	class:RevealedCutModule
+selSizeCallback	modules/RevealedCutModule.hpp	/^        static void selSizeCallback(Module* mod, $/;"	f	class:RevealedCutModule
+sendMessage	osc/OscManager.cpp	/^void OscManager::sendMessage(const string& id,$/;"	f	class:OscManager
+sendMessage	osc/OscManager.hpp	/^        void sendMessage(const std::string& id,$/;"	p	class:OscManager
+sendToAddr_	osc/oscPack/ip/posix/UdpSocket.cpp	/^	struct sockaddr_in sendToAddr_;$/;"	m	class:UdpSocket::Implementation	typeref:struct:UdpSocket::Implementation::sockaddr_in	file:
+sendToAddr_	osc/oscPack/ip/win32/UdpSocket.cpp	/^	struct sockaddr_in sendToAddr_;$/;"	m	class:UdpSocket::Implementation	typeref:struct:UdpSocket::Implementation::sockaddr_in	file:
+sendValuesToListeners	modules/Attribute.cpp	/^void Attribute::sendValuesToListeners(const int& lisID) {$/;"	f	class:Attribute
+sendValuesToListeners	modules/Attribute.hpp	/^        void sendValuesToListeners(const int& lisID=-1);$/;"	p	class:Attribute
+setAccessibility	modules/Attribute.hpp	/^        void setAccessibility(ACCESSIBILITY acc){m_accessibility=acc;}$/;"	f	class:Attribute
+setAction	modules/Attribute.hpp	/^        void setAction() { m_actionCallback(m_module);}$/;"	f	class:Attribute
+setActive	modules/PreviewModule.hpp	/^        inline void setActive(bool active) {m_active=active;}$/;"	f	class:PreviewModule
+setActive	modules/ProjectorModule.hpp	/^        inline void setActive(bool active) {m_active=active;}$/;"	f	class:ProjectorModule
+setAnimPlay	modules/RevealedModule.cpp	/^void RevealedModule::setAnimPlay(const bool& play) {$/;"	f	class:RevealedModule
+setAnimPlay	modules/RevealedModule.hpp	/^        virtual void setAnimPlay(const bool& play){m_playing=play;}$/;"	f	class:RevealedLayer
+setAnimPlay	modules/RevealedModule.hpp	/^        virtual void setAnimPlay(const bool&);$/;"	p	class:RevealedModule
+setAnimPos	modules/RevealedModule.cpp	/^void RevealedLayerAnim::setAnimPos(const float& pos) {$/;"	f	class:RevealedLayerAnim
+setAnimPos	modules/RevealedModule.cpp	/^void RevealedLayerVideo::setAnimPos(const float& pos) {$/;"	f	class:RevealedLayerVideo
+setAnimPos	modules/RevealedModule.cpp	/^void RevealedModule::setAnimPos(const float& pos) {$/;"	f	class:RevealedModule
+setAnimPos	modules/RevealedModule.hpp	/^        virtual void setAnimPos(const float& pos);$/;"	p	class:RevealedLayerAnim
+setAnimPos	modules/RevealedModule.hpp	/^        virtual void setAnimPos(const float& pos);$/;"	p	class:RevealedLayerVideo
+setAnimPos	modules/RevealedModule.hpp	/^        virtual void setAnimPos(const float& pos){}$/;"	f	class:RevealedLayer
+setAnimPos	modules/RevealedModule.hpp	/^        virtual void setAnimPos(const float&);$/;"	p	class:RevealedModule
+setAnimSpeed	modules/RevealedModule.cpp	/^void RevealedModule::setAnimSpeed(const float& speed) {$/;"	f	class:RevealedModule
+setAnimSpeed	modules/RevealedModule.hpp	/^        virtual void setAnimSpeed(const float& speed){m_speed=speed;}$/;"	f	class:RevealedLayer
+setAnimSpeed	modules/RevealedModule.hpp	/^        virtual void setAnimSpeed(const float&);$/;"	p	class:RevealedModule
+setAttribute	modules/Listener.hpp	/^        inline virtual void setAttribute(Attribute* att){m_attribute=att;}$/;"	f	class:Listener
+setAttribute	osc/OscListener.cpp	/^void OscListener::setAttribute(Attribute* att) { $/;"	f	class:OscListener
+setAttribute	osc/OscListener.hpp	/^        virtual void setAttribute(Attribute* att);$/;"	p	class:OscListener
+setBools	modules/Attribute.hpp	/^        void setBools(const std::vector<bool>& bools,$/;"	f	class:Attribute
+setCalib	modules/DepthCamModule.cpp	/^void DepthCamModule::setCalib(const int& c) {$/;"	f	class:DepthCamModule
+setCalib	modules/DepthCamModule.hpp	/^        void setCalib(const int&);$/;"	p	class:DepthCamModule
+setCalib	modules/ProjectorModule.cpp	/^void ProjectorModule::setCalib(const int& c) {$/;"	f	class:ProjectorModule
+setCalib	modules/ProjectorModule.hpp	/^        void setCalib(const int&);$/;"	p	class:ProjectorModule
+setCalibMarkerPosY	modules/DepthCamModule.cpp	/^void DepthCamModule::setCalibMarkerPosY(const int& y) {$/;"	f	class:DepthCamModule
+setCalibMarkerPosY	modules/DepthCamModule.hpp	/^        void setCalibMarkerPosY(const int&);$/;"	p	class:DepthCamModule
+setCalibMarkerRotX	modules/DepthCamModule.cpp	/^void DepthCamModule::setCalibMarkerRotX(const int& x) {$/;"	f	class:DepthCamModule
+setCalibMarkerRotX	modules/DepthCamModule.hpp	/^        void setCalibMarkerRotX(const int&);$/;"	p	class:DepthCamModule
+setCalibMarkerRotY	modules/DepthCamModule.cpp	/^void DepthCamModule::setCalibMarkerRotY(const int& y) {$/;"	f	class:DepthCamModule
+setCalibMarkerRotY	modules/DepthCamModule.hpp	/^        void setCalibMarkerRotY(const int&);$/;"	p	class:DepthCamModule
+setCaptureBackground	modules/DepthCamModule.cpp	/^void DepthCamModule::setCaptureBackground(const bool& cap) {$/;"	f	class:DepthCamModule
+setCaptureBackground	modules/DepthCamModule.hpp	/^        void setCaptureBackground(const bool& cap);$/;"	p	class:DepthCamModule
+setChildID	modules/Module.hpp	/^        void setChildID(const unsigned int& id){m_childID=id;}$/;"	f	class:Module
+setColor	modules/RevealedModule.cpp	/^void RevealedModule::setColor(const vector<float>& hsv) {$/;"	f	class:RevealedModule
+setColor	modules/RevealedModule.hpp	/^        virtual void setColor(const std::vector<float>&);$/;"	p	class:RevealedModule
+setColor	modules/RevealedTextModule.cpp	/^void RevealedTextModule::setColor(const vector<float>& hsv) {$/;"	f	class:RevealedTextModule
+setColor	modules/RevealedTextModule.hpp	/^        virtual void setColor(const std::vector<float>& hsv);$/;"	p	class:RevealedTextModule
+setContextHandlerID	modules/ContextHandler.hpp	/^        void setContextHandlerID(const int& id) {m_contextHandlerID=id;}$/;"	f	class:ContextHandler
+setContourThresh	modules/DepthCamModule.hpp	/^        inline void setContourThresh(float cont) {m_contourThreshold=cont;}$/;"	f	class:DepthCamModule
+setDepth	modules/Module.hpp	/^        inline void setDepth(const unsigned int& depth){m_depth=depth;}$/;"	f	class:Module
+setDepthID	modules/DepthModule.cpp	/^void DepthModule::setDepthID(const unsigned int& id) {$/;"	f	class:DepthModule
+setDepthID	modules/DepthModule.hpp	/^        void setDepthID(const unsigned int&);$/;"	p	class:DepthModule
+setDimensions	modules/ShapeModule.cpp	/^void ShapeModule::setDimensions(const float& x, const float& y,const float& z) {$/;"	f	class:ShapeModule
+setDimensions	modules/ShapeModule.hpp	/^        void setDimensions(const float&, const float&, const float&);$/;"	p	class:ShapeModule
+setEdges	modules/RevealedPathModule.cpp	/^void RevealedPathModule::setEdges(const int& e) {$/;"	f	class:RevealedPathModule
+setEdges	modules/RevealedPathModule.hpp	/^        void setEdges(const int& e);$/;"	p	class:RevealedPathModule
+setEyePosition	modules/PreviewModule.cpp	/^void PreviewModule::setEyePosition(const float& x, $/;"	f	class:PreviewModule
+setEyePosition	modules/PreviewModule.hpp	/^        void setEyePosition(const float& x, const float& y, const float& z);$/;"	p	class:PreviewModule
+setFile	modules/Attribute.hpp	/^        void setFile(const std::string& f,$/;"	f	class:Attribute
+setFilter	modules/DepthCamModule.hpp	/^        inline void setFilter(bool fil) {m_filter=fil;}$/;"	f	class:DepthCamModule
+setFloats	modules/Attribute.hpp	/^        void setFloats(const std::vector<float>& floats, $/;"	f	class:Attribute
+setFloatsIfChanged	modules/Attribute.hpp	/^        void setFloatsIfChanged(const std::vector<float>& floats) {$/;"	f	class:Attribute
+setFontSize	modules/RevealedTextModule.cpp	/^void RevealedTextModule::setFontSize(const int& size) {$/;"	f	class:RevealedTextModule
+setFontSize	modules/RevealedTextModule.hpp	/^        void setFontSize(const int& size);$/;"	p	class:RevealedTextModule
+setFullName	modules/Attribute.hpp	/^        inline void setFullName(const std::string& fn){m_fullName=fn;}$/;"	f	class:Attribute
+setGeomID	geoms/Geometry.hpp	/^        inline void setGeomID(const Reveal::GEOM_ID& id) {m_geomID=id;}$/;"	f	class:Geometry
+setGeomID	modules/GeomModule.hpp	/^        virtual void setGeomID(const unsigned int& id){m_geomID=id;}$/;"	f	class:GeomModule
+setGradientType	modules/RevealedModule.cpp	/^void RevealedModule::setGradientType(const std::string& type) {$/;"	f	class:RevealedModule
+setGradientType	modules/RevealedModule.hpp	/^        virtual void setGradientType(const std::string&);$/;"	p	class:RevealedModule
+setID	modules/Listener.hpp	/^        inline void setID(const int& id){m_listenerID=id;}$/;"	f	class:Listener
+setImageMarkersFolder	modules/DepthCamModule.cpp	/^void DepthCamModule::setImageMarkersFolder(const std::string& fol) {$/;"	f	class:DepthCamModule
+setImageMarkersFolder	modules/DepthCamModule.hpp	/^        virtual void setImageMarkersFolder(const std::string& f);$/;"	p	class:DepthCamModule
+setImgFolder	modules/DepthCamModule.hpp	/^        void setImgFolder(const std::string& fol){m_imgFolder=fol;}$/;"	f	class:ImageTracker
+setInside	modules/RevealedModule.cpp	/^void RevealedModule::setInside(const std::string& inside) {$/;"	f	class:RevealedModule
+setInside	modules/RevealedModule.hpp	/^        virtual void setInside(const std::string&);$/;"	p	class:RevealedModule
+setInsideAxes	modules/RevealedModule.cpp	/^void RevealedModule::setInsideAxes(const std::string& axes) {$/;"	f	class:RevealedModule
+setInsideAxes	modules/RevealedModule.hpp	/^        virtual void setInsideAxes(const std::string&);$/;"	p	class:RevealedModule
+setInts	modules/Attribute.hpp	/^        void setInts(const std::vector<int>& ints,$/;"	f	class:Attribute
+setLoadable	modules/Attribute.hpp	/^        void setLoadable(bool loadable){m_loadable=loadable;}$/;"	f	class:Attribute
+setLookAt	modules/PreviewModule.cpp	/^void PreviewModule::setLookAt(const float& x, $/;"	f	class:PreviewModule
+setLookAt	modules/PreviewModule.hpp	/^        void setLookAt(const float& x, const float& y, const float& z);$/;"	p	class:PreviewModule
+setMarkersDetectMeth	modules/DepthCamModule.cpp	/^void DepthCamModule::setMarkersDetectMeth(const std::string& val) {$/;"	f	class:DepthCamModule
+setMarkersDetectMeth	modules/DepthCamModule.hpp	/^        void setMarkersDetectMeth(const std::string& val);$/;"	p	class:DepthCamModule
+setMarkersDetection	modules/DepthCamModule.cpp	/^void DepthCamModule::setMarkersDetection(const string& val) {$/;"	f	class:DepthCamModule
+setMarkersDetection	modules/DepthCamModule.hpp	/^        void setMarkersDetection(const std::string& val);$/;"	p	class:DepthCamModule
+setMirrored	modules/ProjectorModule.hpp	/^        inline void setMirrored(bool m){m_mirrored=m;}$/;"	f	class:ProjectorModule
+setMode	modules/DepthCamModule.cpp	/^void DepthCamModule::setMode(const std::string& mode) {$/;"	f	class:DepthCamModule
+setMode	modules/DepthCamModule.hpp	/^        virtual void setMode(const std::string& mode);$/;"	p	class:DepthCamModule
+setModel	modules/ModelModule.cpp	/^void ModelModule::setModel(const std::string& fileName) {$/;"	f	class:ModelModule
+setModel	modules/ModelModule.hpp	/^        virtual void setModel(const std::string&);$/;"	p	class:ModelModule
+setModelMat	modules/Module.cpp	/^void Module::setModelMat(const glm::mat4& mat) { $/;"	f	class:Module
+setModelMat	modules/Module.hpp	/^        virtual void setModelMat(const glm::mat4& mat);$/;"	p	class:Module
+setModelMat	modules/ProjectorModule.cpp	/^void ProjectorModule::setModelMat(const glm::mat4& mat) {$/;"	f	class:ProjectorModule
+setModelMat	modules/ProjectorModule.hpp	/^        virtual void setModelMat(const glm::mat4& mat);$/;"	p	class:ProjectorModule
+setModuleListObsID	Reveal.hpp	/^        void setModuleListObsID(const unsigned int& id){m_moduleListObsID=id;}$/;"	f	class:ModuleListObserver
+setModuleName	modules/DepthCamModule.cpp	/^void DepthCamModule::setModuleName(const std::string& val) {$/;"	f	class:DepthCamModule
+setModuleName	modules/DepthCamModule.hpp	/^        void setModuleName(const std::string& val);$/;"	p	class:DepthCamModule
+setModuleName	modules/Module.hpp	/^        inline virtual void setModuleName(const std::string& val){setName(val);}$/;"	f	class:Module
+setModuleName	modules/ProjectorModule.cpp	/^void ProjectorModule::setModuleName(const string& name) {$/;"	f	class:ProjectorModule
+setModuleName	modules/ProjectorModule.hpp	/^        void setModuleName(const std::string&);$/;"	p	class:ProjectorModule
+setName	modules/Module.cpp	/^void Module::setName(const std::string& name) {$/;"	f	class:Module
+setName	modules/Module.hpp	/^        void setName(const std::string& val);$/;"	p	class:Module
+setName	modules/RevealedCutModule.hpp	/^        void setName(const std::string& name){m_name=name;}$/;"	f	class:CutWindow
+setParameters	modules/Listener.cpp	/^void Listener::setParameters(const vector<string>& params) { $/;"	f	class:Listener
+setParameters	modules/Listener.hpp	/^        virtual void setParameters(const std::vector<std::string>& par);$/;"	p	class:Listener
+setParameters	osc/OscListener.cpp	/^void OscListener::setParameters(const std::vector<std::string>& params) {$/;"	f	class:OscListener
+setParameters	osc/OscListener.hpp	/^        virtual void setParameters(const std::vector<std::string>& par);$/;"	p	class:OscListener
+setParent	modules/Module.hpp	/^        void setParent(GroupModule* groupmod){m_parent=groupmod;}$/;"	f	class:Module
+setParentMatrix	modules/Module.hpp	/^        inline void setParentMatrix(const glm::mat4& mat){m_parentMat=mat;} $/;"	f	class:Module
+setParentVisible	modules/GroupModule.cpp	/^void GroupModule::setParentVisible(bool pvis) {$/;"	f	class:GroupModule
+setParentVisible	modules/GroupModule.hpp	/^        virtual void setParentVisible(bool pvis);$/;"	p	class:GroupModule
+setParentVisible	modules/Module.hpp	/^        inline virtual void setParentVisible(bool pvis){m_parentVisible=pvis;}$/;"	f	class:Module
+setPatternBrightness	modules/ProjectorModule.cpp	/^void ProjectorModule::setPatternBrightness(const int& b) {$/;"	f	class:ProjectorModule
+setPatternBrightness	modules/ProjectorModule.hpp	/^        void setPatternBrightness(const int&);$/;"	p	class:ProjectorModule
+setPatternPositionX	modules/ProjectorModule.cpp	/^void ProjectorModule::setPatternPositionX(const int& x) {$/;"	f	class:ProjectorModule
+setPatternPositionX	modules/ProjectorModule.hpp	/^        void setPatternPositionX(const int&);$/;"	p	class:ProjectorModule
+setPatternPositionY	modules/ProjectorModule.cpp	/^void ProjectorModule::setPatternPositionY(const int& y) {$/;"	f	class:ProjectorModule
+setPatternPositionY	modules/ProjectorModule.hpp	/^        void setPatternPositionY(const int&);$/;"	p	class:ProjectorModule
+setPatternSquareWidth	modules/ProjectorModule.cpp	/^void ProjectorModule::setPatternSquareWidth(const int& w) {$/;"	f	class:ProjectorModule
+setPatternSquareWidth	modules/ProjectorModule.hpp	/^        void setPatternSquareWidth(const int&);$/;"	p	class:ProjectorModule
+setPatternThresh	modules/ProjectorModule.cpp	/^void ProjectorModule::setPatternThresh(const int& x) {$/;"	f	class:ProjectorModule
+setPatternThresh	modules/ProjectorModule.hpp	/^        void setPatternThresh(const int&);$/;"	p	class:ProjectorModule
+setPosition	modules/Module.cpp	/^void Module::setPosition(const float& posX, $/;"	f	class:Module
+setPosition	modules/Module.hpp	/^        virtual void setPosition(const float& posX, $/;"	p	class:Module
+setProjID	modules/ProjectorModule.hpp	/^        inline void setProjID(const int& id){m_projID=id;}$/;"	f	class:ProjectorModule
+setProjectionMatrix	modules/ProjectorModule.cpp	/^void ProjectorModule::setProjectionMatrix(const vector<float>& vals) {$/;"	f	class:ProjectorModule
+setProjectionMatrix	modules/ProjectorModule.hpp	/^        void setProjectionMatrix(const std::vector<float>& vals);$/;"	p	class:ProjectorModule
+setQuaternion	modules/Module.cpp	/^void Module::setQuaternion(const float& rotX, $/;"	f	class:Module
+setQuaternion	modules/Module.hpp	/^        virtual void setQuaternion(const float& rotX, $/;"	p	class:Module
+setRessourcesFolder	Reveal.cpp	/^void Reveal::setRessourcesFolder(const std::string& f) {$/;"	f	class:Reveal
+setRessourcesFolder	Reveal.hpp	/^        void setRessourcesFolder(const std::string& f);$/;"	p	class:Reveal
+setRevID	modules/RevealedModule.hpp	/^        inline void setRevID(const unsigned int& id) { $/;"	f	class:RevealedModule
+setRevealedBy	modules/Module.cpp	/^void Module::setRevealedBy(const std::string& by) {$/;"	f	class:Module
+setRevealedBy	modules/Module.hpp	/^        void setRevealedBy(const std::string& by);$/;"	p	class:Module
+setRotation	modules/Module.cpp	/^void Module::setRotation(const float& rotX, $/;"	f	class:Module
+setRotation	modules/Module.hpp	/^        virtual void setRotation(const float& rotX, $/;"	p	class:Module
+setScale	modules/Module.cpp	/^void Module::setScale(const float& scaX, $/;"	f	class:Module
+setScale	modules/Module.hpp	/^        virtual void setScale(const float& scaX, $/;"	p	class:Module
+setShape	modules/DepthShapeModule.cpp	/^void DepthShapeModule::setShape(const std::string& shape) {$/;"	f	class:DepthShapeModule
+setShape	modules/DepthShapeModule.hpp	/^        void setShape(const std::string& shape);$/;"	p	class:DepthShapeModule
+setShape	modules/RevealedShapeModule.cpp	/^void RevealedShapeModule::setShape(const std::string& shape) {$/;"	f	class:RevealedShapeModule
+setShape	modules/RevealedShapeModule.hpp	/^        void setShape(const std::string&);$/;"	p	class:RevealedShapeModule
+setShape	modules/ShapeModule.hpp	/^        virtual void setShape(const std::string&){}$/;"	f	class:ShapeModule
+setSpace	modules/DepthCamModule.cpp	/^void DepthCamModule::setSpace(SpaceModule* spa) {$/;"	f	class:DepthCamModule
+setSpace	modules/DepthCamModule.hpp	/^        virtual void setSpace(SpaceModule*);$/;"	p	class:DepthCamModule
+setSpace	modules/DepthMeshModule.cpp	/^void DepthMeshModule::setSpace(SpaceModule* space) {$/;"	f	class:DepthMeshModule
+setSpace	modules/DepthMeshModule.hpp	/^        virtual void setSpace(SpaceModule* space);$/;"	p	class:DepthMeshModule
+setSpace	modules/DepthModule.cpp	/^void DepthModule::setSpace(SpaceModule* space) { $/;"	f	class:DepthModule
+setSpace	modules/DepthModule.hpp	/^        virtual void setSpace(SpaceModule* space);$/;"	p	class:DepthModule
+setSpace	modules/DepthShapeModule.cpp	/^void DepthShapeModule::setSpace(SpaceModule* space) {$/;"	f	class:DepthShapeModule
+setSpace	modules/DepthShapeModule.hpp	/^        virtual void setSpace(SpaceModule* space);$/;"	p	class:DepthShapeModule
+setSpace	modules/ProjectorModule.cpp	/^void ProjectorModule::setSpace(SpaceModule* space) {$/;"	f	class:ProjectorModule
+setSpace	modules/ProjectorModule.hpp	/^        void setSpace(SpaceModule* space);$/;"	p	class:ProjectorModule
+setStrings	modules/Attribute.hpp	/^        void setStrings(const std::vector<std::string>& strings, $/;"	f	class:Attribute
+setStringsIfChanged	modules/Attribute.hpp	/^        void setStringsIfChanged(const std::vector<std::string>& strings) {$/;"	f	class:Attribute
+setSurface	modules/RevealedModule.cpp	/^void RevealedModule::setSurface(const std::string& surface) {$/;"	f	class:RevealedModule
+setSurface	modules/RevealedModule.hpp	/^        virtual void setSurface(const std::string&);$/;"	p	class:RevealedModule
+setSurfaceTexture	modules/RevealedModule.cpp	/^void RevealedModule::setSurfaceTexture(const std::string& f) {$/;"	f	class:RevealedModule
+setSurfaceTexture	modules/RevealedModule.hpp	/^        virtual void setSurfaceTexture(const std::string& f);$/;"	p	class:RevealedModule
+setSurfaceThickness	modules/RevealedModule.cpp	/^void RevealedModule::setSurfaceThickness(const float& surface) {$/;"	f	class:RevealedModule
+setSurfaceThickness	modules/RevealedModule.hpp	/^        virtual void setSurfaceThickness(const float&);$/;"	p	class:RevealedModule
+setText	modules/RevealedTextModule.cpp	/^void RevealedTextModule::setText(const std::string& text) {$/;"	f	class:RevealedTextModule
+setText	modules/RevealedTextModule.hpp	/^        void setText(const std::string& text);$/;"	p	class:RevealedTextModule
+setTexture	modules/RevealedModule.cpp	/^void RevealedModule::setTexture(const std::string& f) {$/;"	f	class:RevealedModule
+setTexture	modules/RevealedModule.hpp	/^        virtual void setTexture(const std::string& f);$/;"	p	class:RevealedModule
+setTextureLayersFolder	modules/RevealedModule.cpp	/^void RevealedModule::setTextureLayersFolder(const std::string& folder) {$/;"	f	class:RevealedModule
+setTextureLayersFolder	modules/RevealedModule.hpp	/^        virtual void setTextureLayersFolder(const std::string& f);$/;"	p	class:RevealedModule
+setTextureOffset	modules/RevealedModule.cpp	/^void RevealedModule::setTextureOffset(const float& x, $/;"	f	class:RevealedModule
+setTextureOffset	modules/RevealedModule.hpp	/^        virtual void setTextureOffset(const float& x, $/;"	p	class:RevealedModule
+setTextureScale	modules/RevealedModule.cpp	/^void RevealedModule::setTextureScale(const float& x, $/;"	f	class:RevealedModule
+setTextureScale	modules/RevealedModule.hpp	/^        virtual void setTextureScale(const float& x, $/;"	p	class:RevealedModule
+setThickness	modules/RevealedPathModule.cpp	/^void RevealedPathModule::setThickness(const float& t) {$/;"	f	class:RevealedPathModule
+setThickness	modules/RevealedPathModule.hpp	/^        void setThickness(const float& t);$/;"	p	class:RevealedPathModule
+setUpID	modules/Module.hpp	/^        inline void setUpID(const unsigned int& id){m_upID=id;}$/;"	f	class:Module
+setViewMatrix	modules/ProjectorModule.cpp	/^void ProjectorModule::setViewMatrix(const vector<float>& vals) {$/;"	f	class:ProjectorModule
+setViewMatrix	modules/ProjectorModule.hpp	/^        void setViewMatrix(const std::vector<float>& vals);$/;"	p	class:ProjectorModule
+setVisibilityMask	modules/Module.hpp	/^        inline void  setVisibilityMask(int mask){m_visibilityMask=mask;}$/;"	f	class:Module
+setVisible	modules/GroupModule.cpp	/^void GroupModule::setVisible(bool vis) {$/;"	f	class:GroupModule
+setVisible	modules/GroupModule.hpp	/^        virtual void setVisible(bool vis);$/;"	p	class:GroupModule
+setVisible	modules/Module.hpp	/^        inline virtual void setVisible(bool vis){m_visible=vis;}$/;"	f	class:Module
+setVisibleFrom	modules/Module.cpp	/^void Module::setVisibleFrom(const std::string& visibleFrom) {$/;"	f	class:Module
+setVisibleFrom	modules/Module.hpp	/^        void setVisibleFrom(const std::string& visibleFrom);$/;"	p	class:Module
+setVisibleFromList	modules/Module.cpp	/^void Module::setVisibleFromList(vector<string>& modVec) {$/;"	f	class:Module
+setVisibleFromList	modules/Module.hpp	/^        void setVisibleFromList(std::vector<std::string>& modVec);$/;"	p	class:Module
+setWindow	modules/RevealedCutModule.cpp	/^void RevealedCutModule::setWindow(const std::string& winName) {$/;"	f	class:RevealedCutModule
+setWindow	modules/RevealedCutModule.hpp	/^        void setWindow(const std::string& text);$/;"	p	class:RevealedCutModule
+setWindowDecoration	modules/ProjectorModule.cpp	/^void ProjectorModule::setWindowDecoration(bool d) {$/;"	f	class:ProjectorModule
+setWindowDecoration	modules/ProjectorModule.hpp	/^        void setWindowDecoration(bool d);$/;"	p	class:ProjectorModule
+setWindowDimensions	modules/ProjectorModule.cpp	/^void ProjectorModule::setWindowDimensions(const int& x, const int& y,$/;"	f	class:ProjectorModule
+setWindowDimensions	modules/ProjectorModule.hpp	/^        void setWindowDimensions(const int& x, const int& y, $/;"	p	class:ProjectorModule
+shapeCallback	modules/ShapeModule.hpp	/^        static void shapeCallback(Module* mod, $/;"	f	class:ShapeModule
+showAliveMarkers	modules/DepthCamModule.cpp	/^void DepthCamModule::showAliveMarkers() {$/;"	f	class:DepthCamModule
+showAliveMarkers	modules/DepthCamModule.hpp	/^        void showAliveMarkers();$/;"	p	class:DepthCamModule
+showListeners	gui/MainWindow.cpp	/^void MainWindow::showListeners() {$/;"	f	class:MainWindow
+showListeners	gui/MainWindow.hpp	/^        void showListeners();$/;"	p	class:MainWindow
+size	osc/oscPack/osc/OscTypes.h	/^    osc_bundle_element_size_t size;$/;"	m	struct:osc::Blob
+size	osc/ringbuffer.c	/^    size_t	size;$/;"	m	struct:__anon7	file:
+size	osc/ringbuffer.h	/^    size_t	size;$/;"	m	struct:__anon2
+sizePtr_	osc/oscPack/osc/OscReceivedElements.h	/^    const char *sizePtr_;$/;"	m	class:osc::ReceivedBundleElement
+size_	osc/oscPack/osc/OscReceivedElements.h	/^    osc_bundle_element_size_t size_;$/;"	m	class:osc::ReceivedPacket
+size_mask	osc/ringbuffer.c	/^    size_t	size_mask;$/;"	m	struct:__anon7	file:
+size_mask	osc/ringbuffer.h	/^    size_t	size_mask;$/;"	m	struct:__anon2
+socketListeners_	osc/oscPack/ip/posix/UdpSocket.cpp	/^	std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;$/;"	m	class:SocketReceiveMultiplexer::Implementation	file:
+socketListeners_	osc/oscPack/ip/win32/UdpSocket.cpp	/^	std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;$/;"	m	class:SocketReceiveMultiplexer::Implementation	file:
+socket_	osc/oscPack/ip/posix/UdpSocket.cpp	/^	int socket_;$/;"	m	class:UdpSocket::Implementation	file:
+socket_	osc/oscPack/ip/win32/UdpSocket.cpp	/^	SOCKET socket_;$/;"	m	class:UdpSocket::Implementation	file:
+socklen_t	osc/oscPack/ip/posix/UdpSocket.cpp	/^typedef ssize_t socklen_t;$/;"	t	file:
+socklen_t	osc/oscPack/ip/win32/UdpSocket.cpp	/^typedef int socklen_t;$/;"	t	file:
+statAction	gui/AttributeWidget.hpp	/^        static void statAction(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statAddListener	gui/AttributeWidget.hpp	/^        static void statAddListener(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statChecks	gui/AttributeWidget.hpp	/^        static void statChecks(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statChoices	gui/AttributeWidget.hpp	/^        static void statChoices(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statFileOpen	gui/AttributeWidget.hpp	/^        static void statFileOpen(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statFileSave	gui/AttributeWidget.hpp	/^        static void statFileSave(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statFloats	gui/AttributeWidget.hpp	/^        static void statFloats(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statFolderOpen	gui/AttributeWidget.hpp	/^        static void statFolderOpen(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statInts	gui/AttributeWidget.hpp	/^        static void statInts(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statParams	gui/ListenerWidget.hpp	/^        static void statParams(Fl_Widget* w, void* f){ $/;"	f	class:ListenerWidget
+statQuit	gui/MainWindow.hpp	/^        static void statQuit(Fl_Widget* w,void* f){ $/;"	f	class:MainWindow
+statRemove	gui/ListenerWidget.hpp	/^        static void statRemove(Fl_Widget* w, void* f){ $/;"	f	class:ListenerWidget
+statShowListeners	gui/AttributeWidget.hpp	/^        static void statShowListeners(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statStrings	gui/AttributeWidget.hpp	/^        static void statStrings(Fl_Widget* w, void* f){ $/;"	f	class:AttributeWidget
+statTree	gui/MainWindow.hpp	/^        static void statTree(Fl_Widget* w,void* f){ $/;"	f	class:MainWindow
+std	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^namespace std {$/;"	n	file:
+std	osc/oscPack/osc/OscPrintReceivedElements.cpp	/^namespace std {$/;"	n	file:
+stop	osc/OscManager.cpp	/^void OscManager::stop() {$/;"	f	class:OscManager
+stop	osc/OscManager.hpp	/^        void stop();$/;"	p	class:OscManager
+surfaceCallback	modules/RevealedModule.hpp	/^        static void surfaceCallback(Module* mod, $/;"	f	class:RevealedModule
+surfaceTextureCallback	modules/RevealedModule.hpp	/^        static void surfaceTextureCallback(Module* mod, const std::string& f) {$/;"	f	class:RevealedModule
+surfaceThicknessCallback	modules/RevealedModule.hpp	/^        static void surfaceThicknessCallback(Module* mod, $/;"	f	class:RevealedModule
+testDelete	Reveal.cpp	/^void Reveal::testDelete() {$/;"	f	class:Reveal
+testDelete	Reveal.hpp	/^        void testDelete();$/;"	p	class:Reveal
+tex	modules/ModelModule.hpp	/^            glm::vec2 tex;$/;"	m	struct:ModelModule::ModelVertex
+texSize	modules/RevealedModelModule.hpp	/^        float texSize;$/;"	m	class:RevealedModelModule
+textCallback	modules/RevealedTextModule.hpp	/^        static void textCallback(Module* mod, $/;"	f	class:RevealedTextModule
+textureCallback	modules/RevealedModule.hpp	/^        static void textureCallback(Module* mod, const std::string& f) {$/;"	f	class:RevealedModule
+textureLayersFolderCallback	modules/RevealedModule.hpp	/^        static void textureLayersFolderCallback(Module* mod, $/;"	f	class:RevealedModule
+textureOffsetCallback	modules/RevealedModule.hpp	/^        static void textureOffsetCallback(Module* mod, $/;"	f	class:RevealedModule
+textureScaleCallback	modules/RevealedModule.hpp	/^        static void textureScaleCallback(Module* mod, $/;"	f	class:RevealedModule
+thicknessCallback	modules/RevealedPathModule.hpp	/^        static void thicknessCallback(Module* mod, $/;"	f	class:RevealedPathModule
+timeLess	modules/DepthCamModule.hpp	/^    time_t timeLess;$/;"	m	struct:s_markerAndTime
+timeTag	osc/oscPack/osc/OscTypes.h	/^    uint64 timeTag;$/;"	m	struct:osc::BundleInitiator
+timeTag_	osc/oscPack/osc/OscReceivedElements.h	/^    const char *timeTag_;$/;"	m	class:osc::ReceivedBundle
+timerListeners_	osc/oscPack/ip/posix/UdpSocket.cpp	/^	std::vector< AttachedTimerListener > timerListeners_;$/;"	m	class:SocketReceiveMultiplexer::Implementation	file:
+timerListeners_	osc/oscPack/ip/win32/UdpSocket.cpp	/^	std::vector< AttachedTimerListener > timerListeners_;$/;"	m	class:SocketReceiveMultiplexer::Implementation	file:
+track	modules/DepthCamModule.cpp	/^void ArucoTracker::track(cv::Mat& img,$/;"	f	class:ArucoTracker
+track	modules/DepthCamModule.cpp	/^void ImageTracker::track(cv::Mat& img, $/;"	f	class:ImageTracker
+track	modules/DepthCamModule.hpp	/^        virtual void track(cv::Mat&,$/;"	p	class:Tracker
+track	modules/DepthCamModule.hpp	/^        void track(cv::Mat&, $/;"	p	class:ArucoTracker
+track	modules/DepthCamModule.hpp	/^        void track(cv::Mat&,$/;"	p	class:ImageTracker
+typeTagPtr_	osc/oscPack/osc/OscReceivedElements.h	/^	const char *typeTagPtr_;$/;"	m	class:osc::ReceivedMessageArgument
+typeTagsBegin_	osc/oscPack/osc/OscReceivedElements.h	/^	const char *typeTagsBegin_;$/;"	m	class:osc::ReceivedMessage
+typeTagsCurrent_	osc/oscPack/osc/OscOutboundPacketStream.h	/^    char *typeTagsCurrent_; \/\/ stored in reverse order$/;"	m	class:osc::OutboundPacketStream
+typeTagsEnd_	osc/oscPack/osc/OscReceivedElements.h	/^	const char *typeTagsEnd_;$/;"	m	class:osc::ReceivedMessage
+uint32	osc/oscPack/osc/OscTypes.h	/^typedef unsigned int uint32;$/;"	t	namespace:osc
+uint32	osc/oscPack/osc/OscTypes.h	/^typedef unsigned long uint32;$/;"	t	namespace:osc
+uint64	osc/oscPack/osc/OscTypes.h	/^typedef unsigned __int64 uint64;$/;"	t	namespace:osc
+unregisterGeom	Reveal.cpp	/^void Reveal::unregisterGeom(Geometry* geom) {$/;"	f	class:Reveal
+unregisterGeom	Reveal.hpp	/^        void unregisterGeom(Geometry* geom);$/;"	p	class:Reveal
+unregisterGeom	modules/SpaceModule.cpp	/^void SpaceModule::unregisterGeom(Geometry* geom) {$/;"	f	class:SpaceModule
+unregisterGeom	modules/SpaceModule.hpp	/^        void unregisterGeom(Geometry* geom);$/;"	p	class:SpaceModule
+unregisterModule	geoms/Geometry.cpp	/^void Geometry::unregisterModule(GeomModule* geom) {$/;"	f	class:Geometry
+unregisterModule	geoms/Geometry.hpp	/^        void unregisterModule(GeomModule*);$/;"	p	class:Geometry
+unregisterOutputDepthCam	Reveal.cpp	/^void Reveal::unregisterOutputDepthCam(DepthCamModule* cam) {$/;"	f	class:Reveal
+unregisterOutputDepthCam	Reveal.hpp	/^        void unregisterOutputDepthCam(DepthCamModule* cam);$/;"	p	class:Reveal
+unregisterOutputRevealed	Reveal.cpp	/^void Reveal::unregisterOutputRevealed(RevealedModule* rev) {$/;"	f	class:Reveal
+unregisterOutputRevealed	Reveal.hpp	/^        void unregisterOutputRevealed(RevealedModule* rev);$/;"	p	class:Reveal
+unregisterRevealed	Reveal.cpp	/^void Reveal::unregisterRevealed(RevealedModule* rev) {$/;"	f	class:Reveal
+unregisterRevealed	Reveal.hpp	/^        void unregisterRevealed(RevealedModule*);$/;"	p	class:Reveal
+update	Reveal.cpp	/^void Reveal::update() {$/;"	f	class:Reveal
+update	Reveal.hpp	/^        void update();$/;"	p	class:Reveal
+update	gui/GuiListener.cpp	/^void GuiListener::update(vector<float>& floatValues, $/;"	f	class:GuiListener
+update	gui/GuiListener.hpp	/^        virtual void update(std::vector<float>& floatValues, $/;"	p	class:GuiListener
+update	modules/DepthCamModule.cpp	/^void DepthCamModule::update(const int& timeDiffMs) {$/;"	f	class:DepthCamModule
+update	modules/DepthCamModule.hpp	/^        virtual void update(const int& timeDiffMs);$/;"	p	class:DepthCamModule
+update	modules/Listener.hpp	/^        virtual void update(std::vector<float>& floatValues, $/;"	p	class:Listener
+update	modules/Module.hpp	/^        virtual void update(const int& timeDiffMs){}$/;"	f	class:Module
+update	modules/RevealedCutModule.cpp	/^void RevealedCutModule::update(const int& timeDiffMs) {$/;"	f	class:RevealedCutModule
+update	modules/RevealedCutModule.hpp	/^        virtual void update(const int& timeDiffMs);$/;"	p	class:RevealedCutModule
+update	modules/RevealedModule.cpp	/^bool RevealedLayerAnim::update(const int& timeDiffMs, const int& depth, $/;"	f	class:RevealedLayerAnim
+update	modules/RevealedModule.cpp	/^bool RevealedLayerImage::update(const int& timeDiffMs, const int& depth, $/;"	f	class:RevealedLayerImage
+update	modules/RevealedModule.cpp	/^bool RevealedLayerVideo::update(const int& timeDiffMs, const int& depth, $/;"	f	class:RevealedLayerVideo
+update	modules/RevealedModule.cpp	/^void RevealedModule::update(const int& timeDiffMs) {$/;"	f	class:RevealedModule
+update	modules/RevealedModule.hpp	/^        virtual bool update(const int& timeDiffMs, const int& depth, $/;"	p	class:RevealedLayer
+update	modules/RevealedModule.hpp	/^        virtual bool update(const int& timeDiffMs, const int& depth, $/;"	p	class:RevealedLayerAnim
+update	modules/RevealedModule.hpp	/^        virtual bool update(const int& timeDiffMs, const int& depth, $/;"	p	class:RevealedLayerImage
+update	modules/RevealedModule.hpp	/^        virtual bool update(const int& timeDiffMs, const int& depth, $/;"	p	class:RevealedLayerVideo
+update	modules/RevealedModule.hpp	/^        virtual void update(const int& timeDiffMs);$/;"	p	class:RevealedModule
+update	modules/RevealedPathModule.cpp	/^void PathPointModule::update(vector<float>& floatValues,$/;"	f	class:PathPointModule
+update	modules/RevealedPathModule.hpp	/^        virtual void update(std::vector<float>& floatValues, $/;"	p	class:PathPointModule
+update	osc/OscListener.cpp	/^void OscListener::update(vector<float>& floatValues, $/;"	f	class:OscListener
+update	osc/OscListener.hpp	/^        virtual void update(std::vector<float>& floatValues, $/;"	p	class:OscListener
+update	osc/OscManager.cpp	/^void OscManager::update() {$/;"	f	class:OscManager
+update	osc/OscManager.hpp	/^        void update();$/;"	p	class:OscManager
+updateAttributeValues	gui/AttributeWidget.cpp	/^void AttributeWidget::updateAttributeValues(vector<float>& floatValues, $/;"	f	class:AttributeWidget
+updateAttributeValues	gui/AttributeWidget.hpp	/^        void updateAttributeValues(std::vector<float>& floatValues, $/;"	p	class:AttributeWidget
+updateCalibrationPattern	modules/ProjectorModule.cpp	/^void ProjectorModule::updateCalibrationPattern() {$/;"	f	class:ProjectorModule
+updateCalibrationPattern	modules/ProjectorModule.hpp	/^        void updateCalibrationPattern();$/;"	p	class:ProjectorModule
+updateDepthModules	modules/SpaceModule.cpp	/^void SpaceModule::updateDepthModules() {$/;"	f	class:SpaceModule
+updateDepthModules	modules/SpaceModule.hpp	/^        void updateDepthModules();$/;"	p	class:SpaceModule
+updateListenersVec	modules/Attribute.cpp	/^void Attribute::updateListenersVec() {$/;"	f	class:Attribute
+updateListenersVec	modules/Attribute.hpp	/^        void updateListenersVec();$/;"	p	class:Attribute
+updateModelMatrix	modules/DepthCamModule.cpp	/^void DepthCamModule::updateModelMatrix() {$/;"	f	class:DepthCamModule
+updateModelMatrix	modules/DepthCamModule.hpp	/^        virtual void updateModelMatrix();$/;"	p	class:DepthCamModule
+updateModelMatrix	modules/DepthGroupModule.cpp	/^void DepthGroupModule::updateModelMatrix() {$/;"	f	class:DepthGroupModule
+updateModelMatrix	modules/DepthGroupModule.hpp	/^        virtual void updateModelMatrix();$/;"	p	class:DepthGroupModule
+updateModelMatrix	modules/DepthMeshModule.cpp	/^void DepthMeshModule::updateModelMatrix() {$/;"	f	class:DepthMeshModule
+updateModelMatrix	modules/DepthMeshModule.hpp	/^        virtual void updateModelMatrix();$/;"	p	class:DepthMeshModule
+updateModelMatrix	modules/DepthShapeModule.cpp	/^void DepthShapeModule::updateModelMatrix() {$/;"	f	class:DepthShapeModule
+updateModelMatrix	modules/DepthShapeModule.hpp	/^        virtual void updateModelMatrix();$/;"	p	class:DepthShapeModule
+updateModelMatrix	modules/GroupModule.cpp	/^void GroupModule::updateModelMatrix() {$/;"	f	class:GroupModule
+updateModelMatrix	modules/GroupModule.hpp	/^        virtual void updateModelMatrix();$/;"	p	class:GroupModule
+updateModelMatrix	modules/ModelModule.cpp	/^void ModelModule::updateModelMatrix() {$/;"	f	class:ModelModule
+updateModelMatrix	modules/ModelModule.hpp	/^        virtual void updateModelMatrix();$/;"	p	class:ModelModule
+updateModelMatrix	modules/Module.cpp	/^void Module::updateModelMatrix() {$/;"	f	class:Module
+updateModelMatrix	modules/Module.hpp	/^        virtual void updateModelMatrix();$/;"	p	class:Module
+updateModelMatrix	modules/ProjectorModule.cpp	/^void ProjectorModule::updateModelMatrix() {$/;"	f	class:ProjectorModule
+updateModelMatrix	modules/ProjectorModule.hpp	/^        void updateModelMatrix();$/;"	p	class:ProjectorModule
+updateModelMatrix	modules/RevealedPathModule.cpp	/^void RevealedPathModule::updateModelMatrix() {$/;"	f	class:RevealedPathModule
+updateModelMatrix	modules/RevealedPathModule.hpp	/^        void updateModelMatrix();$/;"	p	class:RevealedPathModule
+updateModelMatrix	modules/ShapeModule.cpp	/^void ShapeModule::updateModelMatrix() {$/;"	f	class:ShapeModule
+updateModelMatrix	modules/ShapeModule.hpp	/^        virtual void updateModelMatrix();$/;"	p	class:ShapeModule
+updateModulesList	Reveal.hpp	/^        virtual void updateModulesList(const std::map<std::string, Module*>&)=0;$/;"	p	class:ModuleListObserver
+updateModulesList	modules/RevealedPathModule.cpp	/^void RevealedPathModule::updateModulesList(const map<string, Module*>& mods) {$/;"	f	class:RevealedPathModule
+updateModulesList	modules/RevealedPathModule.hpp	/^        virtual void updateModulesList(const std::map<std::string, Module*>&);$/;"	p	class:RevealedPathModule
+updateNet	osc/OscListener.cpp	/^void OscListener::updateNet() {$/;"	f	class:OscListener
+updateNet	osc/OscListener.hpp	/^        void updateNet();$/;"	p	class:OscListener
+updateOnce	modules/RevealedCutModule.cpp	/^void RevealedCutModule::updateOnce(bool upOn) {$/;"	f	class:RevealedCutModule
+updateOnce	modules/RevealedCutModule.hpp	/^        void updateOnce(bool);$/;"	p	class:RevealedCutModule
+updateOnceCallback	modules/RevealedCutModule.hpp	/^        static void updateOnceCallback(Module* mod, $/;"	f	class:RevealedCutModule
+updateRevealed	Reveal.cpp	/^void Reveal::updateRevealed() {$/;"	f	class:Reveal
+updateRevealed	Reveal.hpp	/^        void updateRevealed();$/;"	p	class:Reveal
+updateViewProjMatrix	modules/PreviewModule.cpp	/^void PreviewModule::updateViewProjMatrix() {$/;"	f	class:PreviewModule
+updateViewProjMatrix	modules/PreviewModule.hpp	/^        void updateViewProjMatrix();$/;"	p	class:PreviewModule
+updateViewProjMatrix	modules/ProjectorModule.cpp	/^void ProjectorModule::updateViewProjMatrix() {$/;"	f	class:ProjectorModule
+updateViewProjMatrix	modules/ProjectorModule.hpp	/^        void updateViewProjMatrix();$/;"	p	class:ProjectorModule
+updateVisibleFrom	modules/SpaceModule.hpp	/^        void updateVisibleFrom(std::vector<std::string>& modVec, $/;"	p	class:SpacesModule
+updateWindowDims	modules/ProjectorModule.cpp	/^void ProjectorModule::updateWindowDims() {$/;"	f	class:ProjectorModule
+updateWindowDims	modules/ProjectorModule.hpp	/^        void updateWindowDims();$/;"	p	class:ProjectorModule
+updateWindowPos	modules/ProjectorModule.cpp	/^void ProjectorModule::updateWindowPos(const int& x, const int& y) {$/;"	f	class:ProjectorModule
+updateWindowPos	modules/ProjectorModule.hpp	/^        void updateWindowPos(const int& x, const int& y);$/;"	p	class:ProjectorModule
+updateWindowSize	modules/ProjectorModule.cpp	/^void ProjectorModule::updateWindowSize(const int& w, const int& h) {$/;"	f	class:ProjectorModule
+updateWindowSize	modules/ProjectorModule.hpp	/^        void updateWindowSize(const int& w, const int& h);$/;"	p	class:ProjectorModule
+updateWindowsList	modules/RevealedCutModule.cpp	/^void CutWindowsManager::updateWindowsList() {$/;"	f	class:CutWindowsManager
+updateWindowsList	modules/RevealedCutModule.hpp	/^        void updateWindowsList();$/;"	p	class:CutWindowsManager
+uploadCallback	Reveal.hpp	/^        static void uploadCallback(Module* mod, $/;"	f	class:Reveal
+uploadRessource	Reveal.cpp	/^void Reveal::uploadRessource(const std::vector<std::string>& vf) {$/;"	f	class:Reveal
+uploadRessource	Reveal.hpp	/^        void uploadRessource(const std::vector<std::string>& vf);$/;"	p	class:Reveal
+value	osc/oscPack/osc/OscTypes.h	/^    const char* value;$/;"	m	struct:osc::Symbol
+value	osc/oscPack/osc/OscTypes.h	/^    uint32 value;$/;"	m	struct:osc::MidiMessage
+value	osc/oscPack/osc/OscTypes.h	/^    uint32 value;$/;"	m	struct:osc::RgbaColor
+value	osc/oscPack/osc/OscTypes.h	/^    uint64 value;$/;"	m	struct:osc::TimeTag
+value_	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedBundleElement value_;$/;"	m	class:osc::ReceivedBundleElementIterator
+value_	osc/oscPack/osc/OscReceivedElements.h	/^	ReceivedMessageArgument value_;$/;"	m	class:osc::ReceivedMessageArgumentIterator
+viewMatrixCallback	modules/ProjectorModule.hpp	/^        static void viewMatrixCallback(Module* mod, $/;"	f	class:ProjectorModule
+visibleCallback	modules/Module.hpp	/^        static void visibleCallback(Module* mod, $/;"	f	class:Module
+visibleCallback	modules/SceneGroupModule.hpp	/^        static void visibleCallback(Module* mod, $/;"	f	class:SceneGroupModule
+visibleFromCallback	modules/Module.hpp	/^        static void visibleFromCallback(Module* mod, $/;"	f	class:Module
+voronoiColor	modules/DepthCamModule.hpp	/^        cv::Scalar voronoiColor(cv::Mat mat, cv::Point2f pt);$/;"	p	class:DepthCamModule
+what	osc/oscPack/osc/OscException.h	/^    virtual const char* what() const throw() { return what_; }$/;"	f	class:osc::Exception
+what_	osc/oscPack/osc/OscException.h	/^    const char *what_;$/;"	m	class:osc::Exception
+windowCallback	modules/RevealedCutModule.hpp	/^        static void windowCallback(Module* mod, $/;"	f	class:RevealedCutModule
+windowDecorationCallback	modules/ProjectorModule.hpp	/^        static void windowDecorationCallback(Module* mod, $/;"	f	class:ProjectorModule
+windowDimensionsCallback	modules/ProjectorModule.hpp	/^        static void windowDimensionsCallback(Module* mod, $/;"	f	class:ProjectorModule
+windowPositionCallback	modules/ProjectorModule.hpp	/^        static void windowPositionCallback(GLFWwindow* win, int x, int y) {$/;"	f	class:ProjectorModule
+windowSizeCallback	modules/ProjectorModule.hpp	/^        static void windowSizeCallback(GLFWwindow* win, int w, int h) {$/;"	f	class:ProjectorModule
+winsockInitialized_	osc/oscPack/ip/win32/NetworkingUtils.cpp	/^static bool winsockInitialized_ = false;$/;"	v	file:
+write_ptr	osc/ringbuffer.c	/^    volatile size_t write_ptr;$/;"	m	struct:__anon7	file:
+write_ptr	osc/ringbuffer.h	/^    volatile size_t write_ptr;$/;"	m	struct:__anon2
+x	modules/DepthCamModule.hpp	/^    float x;$/;"	m	struct:s_markerAndTime
+y	modules/DepthCamModule.hpp	/^    float y;$/;"	m	struct:s_markerAndTime
+~ArucoTracker	modules/DepthCamModule.hpp	/^        ~ArucoTracker(){}$/;"	f	class:ArucoTracker
+~Attribute	modules/Attribute.cpp	/^Attribute::~Attribute() {$/;"	f	class:Attribute
+~Attribute	modules/Attribute.hpp	/^        ~Attribute();$/;"	p	class:Attribute
+~AttributeWidget	gui/AttributeWidget.cpp	/^AttributeWidget::~AttributeWidget() {$/;"	f	class:AttributeWidget
+~AttributeWidget	gui/AttributeWidget.hpp	/^        virtual ~AttributeWidget();$/;"	p	class:AttributeWidget
+~BoxGeometry	geoms/BoxGeometry.cpp	/^BoxGeometry::~BoxGeometry() {}$/;"	f	class:BoxGeometry
+~BoxGeometry	geoms/BoxGeometry.hpp	/^        virtual ~BoxGeometry();$/;"	p	class:BoxGeometry
+~CamGeometry	geoms/CamGeometry.cpp	/^CamGeometry::~CamGeometry() {}$/;"	f	class:CamGeometry
+~CamGeometry	geoms/CamGeometry.hpp	/^        virtual ~CamGeometry();$/;"	p	class:CamGeometry
+~ConeGeometry	geoms/ConeGeometry.cpp	/^ConeGeometry::~ConeGeometry() {}$/;"	f	class:ConeGeometry
+~ConeGeometry	geoms/ConeGeometry.hpp	/^        virtual ~ConeGeometry();$/;"	p	class:ConeGeometry
+~CutWindow	modules/RevealedCutModule.hpp	/^        ~CutWindow();$/;"	p	class:CutWindow
+~CutWindowsManager	modules/RevealedCutModule.cpp	/^CutWindowsManager::~CutWindowsManager() {$/;"	f	class:CutWindowsManager
+~CutWindowsManager	modules/RevealedCutModule.hpp	/^        ~CutWindowsManager();$/;"	p	class:CutWindowsManager
+~DepthCamModule	modules/DepthCamModule.cpp	/^DepthCamModule::~DepthCamModule() {$/;"	f	class:DepthCamModule
+~DepthCamModule	modules/DepthCamModule.hpp	/^        virtual ~DepthCamModule();$/;"	p	class:DepthCamModule
+~DepthGroupModule	modules/DepthGroupModule.cpp	/^DepthGroupModule::~DepthGroupModule() {$/;"	f	class:DepthGroupModule
+~DepthGroupModule	modules/DepthGroupModule.hpp	/^        virtual ~DepthGroupModule();$/;"	p	class:DepthGroupModule
+~DepthMeshModule	modules/DepthMeshModule.cpp	/^DepthMeshModule::~DepthMeshModule() {$/;"	f	class:DepthMeshModule
+~DepthMeshModule	modules/DepthMeshModule.hpp	/^        virtual ~DepthMeshModule();$/;"	p	class:DepthMeshModule
+~DepthModule	modules/DepthModule.cpp	/^DepthModule::~DepthModule() {}$/;"	f	class:DepthModule
+~DepthModule	modules/DepthModule.hpp	/^        virtual ~DepthModule();$/;"	p	class:DepthModule
+~DepthShapeModule	modules/DepthShapeModule.cpp	/^DepthShapeModule::~DepthShapeModule() {$/;"	f	class:DepthShapeModule
+~DepthShapeModule	modules/DepthShapeModule.hpp	/^        virtual ~DepthShapeModule();$/;"	p	class:DepthShapeModule
+~Exception	osc/oscPack/osc/OscException.h	/^    virtual ~Exception() throw() {}$/;"	f	class:osc::Exception
+~GeomModule	modules/GeomModule.cpp	/^GeomModule::~GeomModule() {}$/;"	f	class:GeomModule
+~GeomModule	modules/GeomModule.hpp	/^        virtual ~GeomModule();$/;"	p	class:GeomModule
+~Geometry	geoms/Geometry.cpp	/^Geometry::~Geometry() {}$/;"	f	class:Geometry
+~Geometry	geoms/Geometry.hpp	/^        virtual ~Geometry();$/;"	p	class:Geometry
+~GroupModule	modules/GroupModule.cpp	/^GroupModule::~GroupModule() {}$/;"	f	class:GroupModule
+~GroupModule	modules/GroupModule.hpp	/^        virtual ~GroupModule();$/;"	p	class:GroupModule
+~GuiListener	gui/GuiListener.hpp	/^        virtual ~GuiListener(){}$/;"	f	class:GuiListener
+~ImageTracker	modules/DepthCamModule.hpp	/^        ~ImageTracker(){}$/;"	f	class:ImageTracker
+~Implementation	osc/oscPack/ip/posix/UdpSocket.cpp	/^	~Implementation()$/;"	f	class:UdpSocket::Implementation
+~Implementation	osc/oscPack/ip/posix/UdpSocket.cpp	/^    ~Implementation()$/;"	f	class:SocketReceiveMultiplexer::Implementation
+~Implementation	osc/oscPack/ip/win32/UdpSocket.cpp	/^	~Implementation()$/;"	f	class:UdpSocket::Implementation
+~Implementation	osc/oscPack/ip/win32/UdpSocket.cpp	/^    ~Implementation()$/;"	f	class:SocketReceiveMultiplexer::Implementation
+~Listener	modules/Listener.hpp	/^        virtual ~Listener(){}$/;"	f	class:Listener
+~ListenerWidget	gui/ListenerWidget.hpp	/^        virtual ~ListenerWidget() {}$/;"	f	class:ListenerWidget
+~MainWindow	gui/MainWindow.cpp	/^MainWindow::~MainWindow() {$/;"	f	class:MainWindow
+~MainWindow	gui/MainWindow.hpp	/^        ~MainWindow();$/;"	p	class:MainWindow
+~ModelModule	modules/ModelModule.cpp	/^ModelModule::~ModelModule() {}$/;"	f	class:ModelModule
+~ModelModule	modules/ModelModule.hpp	/^        virtual ~ModelModule();$/;"	p	class:ModelModule
+~Module	modules/Module.cpp	/^Module::~Module() { $/;"	f	class:Module
+~Module	modules/Module.hpp	/^        virtual ~Module();$/;"	p	class:Module
+~ModuleListObserver	Reveal.hpp	/^        virtual ~ModuleListObserver(){}$/;"	f	class:ModuleListObserver
+~ModuleWidget	gui/ModuleWidget.hpp	/^        virtual ~ModuleWidget() {}$/;"	f	class:ModuleWidget
+~NetworkInitializer	osc/oscPack/ip/NetworkingUtils.h	/^    ~NetworkInitializer();$/;"	p	class:NetworkInitializer
+~NetworkInitializer	osc/oscPack/ip/posix/NetworkingUtils.cpp	/^NetworkInitializer::~NetworkInitializer() {}$/;"	f	class:NetworkInitializer
+~NetworkInitializer	osc/oscPack/ip/win32/NetworkingUtils.cpp	/^NetworkInitializer::~NetworkInitializer()$/;"	f	class:NetworkInitializer
+~OscListener	osc/OscListener.hpp	/^        virtual ~OscListener(){}$/;"	f	class:OscListener
+~OscManager	osc/OscManager.cpp	/^OscManager::~OscManager() {}$/;"	f	class:OscManager
+~OscManager	osc/OscManager.hpp	/^        ~OscManager();$/;"	p	class:OscManager
+~OutboundPacketStream	osc/oscPack/osc/OscOutboundPacketStream.cpp	/^OutboundPacketStream::~OutboundPacketStream()$/;"	f	class:osc::OutboundPacketStream
+~OutboundPacketStream	osc/oscPack/osc/OscOutboundPacketStream.h	/^	~OutboundPacketStream();$/;"	p	class:osc::OutboundPacketStream
+~PacketListener	osc/oscPack/ip/PacketListener.h	/^    virtual ~PacketListener() {}$/;"	f	class:PacketListener
+~PathPointModule	modules/RevealedPathModule.cpp	/^PathPointModule::~PathPointModule() {$/;"	f	class:PathPointModule
+~PathPointModule	modules/RevealedPathModule.hpp	/^        ~PathPointModule();$/;"	p	class:PathPointModule
+~PreviewModule	modules/PreviewModule.cpp	/^PreviewModule::~PreviewModule() {}$/;"	f	class:PreviewModule
+~PreviewModule	modules/PreviewModule.hpp	/^        virtual ~PreviewModule();$/;"	p	class:PreviewModule
+~ProjectorModule	modules/ProjectorModule.cpp	/^ProjectorModule::~ProjectorModule() {}$/;"	f	class:ProjectorModule
+~ProjectorModule	modules/ProjectorModule.hpp	/^        virtual ~ProjectorModule();$/;"	p	class:ProjectorModule
+~QuadGeometry	geoms/QuadGeometry.cpp	/^QuadGeometry::~QuadGeometry() {}$/;"	f	class:QuadGeometry
+~QuadGeometry	geoms/QuadGeometry.hpp	/^        virtual ~QuadGeometry();$/;"	p	class:QuadGeometry
+~Reveal	Reveal.cpp	/^Reveal::~Reveal(){}$/;"	f	class:Reveal
+~Reveal	Reveal.hpp	/^        ~Reveal();$/;"	p	class:Reveal
+~RevealedCutModule	modules/RevealedCutModule.cpp	/^RevealedCutModule::~RevealedCutModule() {$/;"	f	class:RevealedCutModule
+~RevealedCutModule	modules/RevealedCutModule.hpp	/^        virtual ~RevealedCutModule();$/;"	p	class:RevealedCutModule
+~RevealedLayer	modules/RevealedModule.hpp	/^        virtual ~RevealedLayer(){}$/;"	f	class:RevealedLayer
+~RevealedModelModule	modules/RevealedModelModule.cpp	/^RevealedModelModule::~RevealedModelModule() {$/;"	f	class:RevealedModelModule
+~RevealedModelModule	modules/RevealedModelModule.hpp	/^        virtual ~RevealedModelModule();$/;"	p	class:RevealedModelModule
+~RevealedModule	modules/RevealedModule.cpp	/^RevealedModule::~RevealedModule() {}$/;"	f	class:RevealedModule
+~RevealedModule	modules/RevealedModule.hpp	/^        virtual ~RevealedModule();$/;"	p	class:RevealedModule
+~RevealedPathModule	modules/RevealedPathModule.cpp	/^RevealedPathModule::~RevealedPathModule() {$/;"	f	class:RevealedPathModule
+~RevealedPathModule	modules/RevealedPathModule.hpp	/^        virtual ~RevealedPathModule();$/;"	p	class:RevealedPathModule
+~RevealedShapeModule	modules/RevealedShapeModule.cpp	/^RevealedShapeModule::~RevealedShapeModule() {$/;"	f	class:RevealedShapeModule
+~RevealedShapeModule	modules/RevealedShapeModule.hpp	/^        virtual ~RevealedShapeModule();$/;"	p	class:RevealedShapeModule
+~RevealedTextModule	modules/RevealedTextModule.cpp	/^RevealedTextModule::~RevealedTextModule() {$/;"	f	class:RevealedTextModule
+~RevealedTextModule	modules/RevealedTextModule.hpp	/^        virtual ~RevealedTextModule();$/;"	p	class:RevealedTextModule
+~RootSceneGroupModule	modules/RootSceneGroupModule.hpp	/^        virtual ~RootSceneGroupModule(){}$/;"	f	class:RootSceneGroupModule
+~SceneGroupModule	modules/SceneGroupModule.hpp	/^        virtual ~SceneGroupModule(){}$/;"	f	class:SceneGroupModule
+~ShapeModule	modules/ShapeModule.cpp	/^ShapeModule::~ShapeModule() {}$/;"	f	class:ShapeModule
+~ShapeModule	modules/ShapeModule.hpp	/^        virtual ~ShapeModule();$/;"	p	class:ShapeModule
+~SocketReceiveMultiplexer	osc/oscPack/ip/UdpSocket.h	/^    ~SocketReceiveMultiplexer();$/;"	p	class:SocketReceiveMultiplexer
+~SocketReceiveMultiplexer	osc/oscPack/ip/posix/UdpSocket.cpp	/^SocketReceiveMultiplexer::~SocketReceiveMultiplexer()$/;"	f	class:SocketReceiveMultiplexer
+~SocketReceiveMultiplexer	osc/oscPack/ip/win32/UdpSocket.cpp	/^SocketReceiveMultiplexer::~SocketReceiveMultiplexer()$/;"	f	class:SocketReceiveMultiplexer
+~SpaceModule	modules/SpaceModule.cpp	/^SpaceModule::~SpaceModule() {}$/;"	f	class:SpaceModule
+~SpaceModule	modules/SpaceModule.hpp	/^        virtual ~SpaceModule();$/;"	p	class:SpaceModule
+~SphereGeometry	geoms/SphereGeometry.cpp	/^SphereGeometry::~SphereGeometry() {}$/;"	f	class:SphereGeometry
+~SphereGeometry	geoms/SphereGeometry.hpp	/^        virtual ~SphereGeometry();$/;"	p	class:SphereGeometry
+~TimerListener	osc/oscPack/ip/TimerListener.h	/^    virtual ~TimerListener() {}$/;"	f	class:TimerListener
+~Tracker	modules/DepthCamModule.hpp	/^        virtual ~Tracker(){}$/;"	f	class:Tracker
+~TubeGeometry	geoms/TubeGeometry.cpp	/^TubeGeometry::~TubeGeometry() {}$/;"	f	class:TubeGeometry
+~TubeGeometry	geoms/TubeGeometry.hpp	/^        virtual ~TubeGeometry();$/;"	p	class:TubeGeometry
+~UdpListeningReceiveSocket	osc/oscPack/ip/UdpSocket.h	/^    ~UdpListeningReceiveSocket()$/;"	f	class:UdpListeningReceiveSocket
+~UdpSocket	osc/oscPack/ip/UdpSocket.h	/^	virtual ~UdpSocket();$/;"	p	class:UdpSocket
+~UdpSocket	osc/oscPack/ip/posix/UdpSocket.cpp	/^UdpSocket::~UdpSocket()$/;"	f	class:UdpSocket
+~UdpSocket	osc/oscPack/ip/win32/UdpSocket.cpp	/^UdpSocket::~UdpSocket()$/;"	f	class:UdpSocket
diff --git a/src/utils/create_marker.cpp b/src/utils/create_marker.cpp
new file mode 100644
index 0000000..4053742
--- /dev/null
+++ b/src/utils/create_marker.cpp
@@ -0,0 +1,96 @@
+/*
+By downloading, copying, installing or using the software you agree to this
+license. If you do not agree to this license, do not download, install,
+copy or use the software.
+
+                          License Agreement
+               For Open Source Computer Vision Library
+                       (3-clause BSD License)
+
+Copyright (C) 2013, OpenCV Foundation, all rights reserved.
+Third party copyrights are property of their respective owners.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  * Neither the names of the copyright holders nor the names of the contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+
+This software is provided by the copyright holders and contributors "as is" and
+any express or implied warranties, including, but not limited to, the implied
+warranties of merchantability and fitness for a particular purpose are
+disclaimed. In no event shall copyright holders or contributors be liable for
+any direct, indirect, incidental, special, exemplary, or consequential damages
+(including, but not limited to, procurement of substitute goods or services;
+loss of use, data, or profits; or business interruption) however caused
+and on any theory of liability, whether in contract, strict liability,
+or tort (including negligence or otherwise) arising in any way out of
+the use of this software, even if advised of the possibility of such damage.
+*/
+
+
+#include <opencv2/highgui.hpp>
+#include <opencv2/aruco.hpp>
+
+using namespace cv;
+
+namespace {
+const char* about = "Create an ArUco marker image";
+const char* keys  =
+        "{@outfile |<none> | Output image }"
+        "{d        |       | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2,"
+        "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, "
+        "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12,"
+        "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}"
+        "{id       |       | Marker id in the dictionary }"
+        "{ms       | 200   | Marker size in pixels }"
+        "{bb       | 1     | Number of bits in marker borders }"
+        "{si       | false | show generated image }";
+}
+
+
+int main(int argc, char *argv[]) {
+    CommandLineParser parser(argc, argv, keys);
+    parser.about(about);
+
+    if(argc < 4) {
+        parser.printMessage();
+        return 0;
+    }
+
+    int dictionaryId = parser.get<int>("d");
+    int markerId = parser.get<int>("id");
+    int borderBits = parser.get<int>("bb");
+    int markerSize = parser.get<int>("ms");
+    bool showImage = parser.get<bool>("si");
+
+    String out = parser.get<String>(0);
+
+    if(!parser.check()) {
+        parser.printErrors();
+        return 0;
+    }
+
+    Ptr<aruco::Dictionary> dictionary =
+        aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
+
+    Mat markerImg;
+    aruco::drawMarker(dictionary, markerId, markerSize, markerImg, borderBits);
+
+    if(showImage) {
+        imshow("marker", markerImg);
+        waitKey(0);
+    }
+
+    imwrite(out, markerImg);
+
+    return 0;
+}
diff --git a/waf b/waf
new file mode 100755
index 0000000..ba9ee0b
--- /dev/null
+++ b/waf
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+# encoding: latin-1
+# Thomas Nagy, 2005-2018
+#
+"""
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+"""
+
+import os, sys, inspect
+
+VERSION="2.0.20"
+REVISION="36f5354d605298f6a89c09e0c7ef6c1d"
+GIT="f1d78d12462b1fddda21584dedc83a1d269f0970"
+INSTALL=''
+C1='#2'
+C2='#,'
+C3='#%'
+cwd = os.getcwd()
+join = os.path.join
+
+
+WAF='waf'
+def b(x):
+	return x
+if sys.hexversion>0x300000f:
+	WAF='waf3'
+	def b(x):
+		return x.encode()
+
+def err(m):
+	print(('\033[91mError: %s\033[0m' % m))
+	sys.exit(1)
+
+def unpack_wafdir(dir, src):
+	f = open(src,'rb')
+	c = 'corrupt archive (%d)'
+	while 1:
+		line = f.readline()
+		if not line: err('run waf-light from a folder containing waflib')
+		if line == b('#==>\n'):
+			txt = f.readline()
+			if not txt: err(c % 1)
+			if f.readline() != b('#<==\n'): err(c % 2)
+			break
+	if not txt: err(c % 3)
+	txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')).replace(b(C3), b('\x00'))
+
+	import shutil, tarfile
+	try: shutil.rmtree(dir)
+	except OSError: pass
+	try:
+		for x in ('Tools', 'extras'):
+			os.makedirs(join(dir, 'waflib', x))
+	except OSError:
+		err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir)
+
+	os.chdir(dir)
+	tmp = 't.bz2'
+	t = open(tmp,'wb')
+	try: t.write(txt)
+	finally: t.close()
+
+	try:
+		t = tarfile.open(tmp)
+	except:
+		try:
+			os.system('bunzip2 t.bz2')
+			t = tarfile.open('t')
+			tmp = 't'
+		except:
+			os.chdir(cwd)
+			try: shutil.rmtree(dir)
+			except OSError: pass
+			err("Waf cannot be unpacked, check that bzip2 support is present")
+
+	try:
+		for x in t: t.extract(x)
+	finally:
+		t.close()
+
+	for x in ('Tools', 'extras'):
+		os.chmod(join('waflib',x), 493)
+
+	if sys.hexversion<0x300000f:
+		sys.path = [join(dir, 'waflib')] + sys.path
+		import fixpy2
+		fixpy2.fixdir(dir)
+
+	os.remove(tmp)
+	os.chdir(cwd)
+
+	try: dir = unicode(dir, 'mbcs')
+	except: pass
+	try:
+		from ctypes import windll
+		windll.kernel32.SetFileAttributesW(dir, 2)
+	except:
+		pass
+
+def test(dir):
+	try:
+		os.stat(join(dir, 'waflib'))
+		return os.path.abspath(dir)
+	except OSError:
+		pass
+
+def find_lib():
+	src = os.path.abspath(inspect.getfile(inspect.getmodule(err)))
+	base, name = os.path.split(src)
+
+	#devs use $WAFDIR
+	w=test(os.environ.get('WAFDIR', ''))
+	if w: return w
+
+	#waf-light
+	if name.endswith('waf-light'):
+		w = test(base)
+		if w: return w
+		for dir in sys.path:
+			if test(dir):
+				return dir
+		err('waf-light requires waflib -> export WAFDIR=/folder')
+
+	dirname = '%s-%s-%s' % (WAF, VERSION, REVISION)
+	for i in (INSTALL,'/usr','/usr/local','/opt'):
+		w = test(i + '/lib/' + dirname)
+		if w: return w
+
+	#waf-local
+	dir = join(base, (sys.platform != 'win32' and '.' or '') + dirname)
+	w = test(dir)
+	if w: return w
+
+	#unpack
+	unpack_wafdir(dir, src)
+	return dir
+
+wafdir = find_lib()
+sys.path.insert(0, wafdir)
+
+if __name__ == '__main__':
+
+	from waflib import Scripting
+	Scripting.waf_entry_point(cwd, VERSION, wafdir)
+
+#==>
+#BZh91AY&SY:DvE]����DP�����������m�(¬#%0�E0m�b��z`p#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%��_O^m��f���w���e*hi�vӵ}�;X�ݫ���ͲKW�ݳ}�ݶ��tw+������{\3�f���=��<RQ�n�w�x[��N�pq{�l׽�����A����-�6��h�d�44m�}{�n��A���;��0;��ޮm���#%#%��;#%�z:p�AG�PvmͰtiN冝͠v��w3Kkj#%Q��W:��}����i�̀�T�6�5���T�R(���q	E$B�QA�:j(zҕVm:��CϾ������^�훖e�̪�*Tm�uĮ�wc�s۝ɭ�#%Y�������v�l�*�������v�{����{�}�������Svz�|��7�8�n^��F��Eg��@��P��5�����t�=���w���74ðiJ�x��fl�ȩ'{���@TT#2U$��(��T��˝�vޝ��z�>�m�i���;�Z��l����:�s��#2w�ٛ�;y�hW���������o�W��=}㶯�p��#2h#2���so����\�_X�<�����v�9���l�wۇ���m�m$����[�����r�>�w|�]�jSL���Y�@_a��c�l���j��n�r�:|�R�nݕ`�����n�l�����ݙ˭���{.�}����}r�=��i朝꺹���#%=�=^oO^�����hL:�ED�URKB����w@n!&e�v��o�{�.����1,gvl�m�]���U9ө���d��{ٚ4 ��m��x#%ݎ�#%#%o���W.'w�ﳻ���]����U׻<f��]6��-Ce�g^�{���lUQ��ڜ�7ێ��f�/����kx*��J�4��n�����x�e{(z�맷�iَo����f��n���l^8���w����ӻ��>;�/r�ݻ��}�hlƀ}�z����Z��[nwA���y�Η���9���Yש�v{@6z�#2�}w�i^��t����p:��h�.0�i�o^�O�����u��Z���a{����|޵�+�C�{��A��u����yֻa�.� �:s޻˻���kyҀ�C����#%#��Wn���g��R��@���������wW��ݝ���6�ê�W5�˷p7wH�E˝�ZnΩ5ݷOw�����㩛=w��%�+�Q�ǫ_W�x�Ϟӹ��O|Bك&�����ټ���:�f�z������u����ݶ�����7}K�x3淍�i�#%� h#%��#,	�C&��!�#2<����#%�jSj{E6���!&Aa4�EO4��i��hژ�h#%#%#%#%#%#%�DAh	�MLL�j3T�'�O�L��jz���44~�# �#%#%#%$�JH�F�4	���mO"����i�#%hP#%ѡ��#%#%h#%#%#%D��#% #%�SЙM&F�&#,Bb�#%#%#%#%$�Dh#%�M@%?$=Q�I���<P#%�#%�#%�����U�q���UW*��ݿ����ѕ>5Zu!J$�",!2D�"#%H#%���A�?O��������.��Wb��L�âԬ����.Cy�5��fR��>g�R���� 7a��3�l#%��t��guD�D�7+O�W4]\=cl�0���I��b��9k��l����[~�(�AR R1B@��(Ȃ1�)"��#%�#2p���P��9`I(��C"��9E,DF�#%HD��"��E �@*��#%�#%rBfL����CL�d@M$Rj6�35�25)F�Sm&‰��4����TlњK&�#D�B�R&Қ	#%6�KbʛF���-�(JYiM-�!e�6h&�31�I�F�d�#,)�E	��%a��-#Jm�l�m6��VѦbK�3!4D�2ɶ�m4�Ԕl����Z�l͔��&b(*"�i���E2(�6�B��#h��h��B��IS�*"#2��`؄!A"$��Ȍ�6�L�ib �ٚ$LR��3 ����H���1�k&�ƋL*E�,�$h�SLbJL�2�4d�ѓ#2��"QI�#2lh�,E2��E3��Hf�I�hfl�&�$���X$���DIi(���*!$J4H�`��!���F(L����3cF���ԑ$�"қ HD�d� $Ŗe��%e26"f�ȊQ�#0L�i�!R�f��Y �M#,�DjVK$lQ(�&E4�MH�f�Ɠ��RK(�j4��mM4Q5�,��YŒ�"h&�H�3	�J��be ��I���#�He��l�*fj�Q�RؔD̆�S�FlhP����(�Rd�d�lc%M#S4X�I#2L�#2YY��V"0DQ%&��4̂��Q����E��)IM��Ɍ��B�$b�e$)E���LI&��4��"E#,#`LF4*4�"m����Bi2�E�"d,ȂSd�1J"�L���66�X�K&2��-��)d1���aA�,j,�%F"Ԧ�#2-L4$̤�d���"�hҘ��BY2�%V��тe	��2��QI3""����h��FP�YSf��2��Q�#2)��4�F����;k���a�͢�lVƶ*6L�4�R��44����F�5Y���c(�)��$["���-��(Ĥ��ڊBѓL&��,,jAL��&L�6��eZF��(El�dU*�J�Sf�c3VƋ"+d�+"T�)����R��"�#@d�mE�k,Ii���*��Z2TUd�J6��TT�F�M2Fر�X�F�-X�I�T�	E �4c!i�iZ[lh�bk�H���-j��e��Be3R�MT�HD�iH��Vm�R�J����XV����RșKSSF�-�%2��,���![,�	��D��b�4��!��-�T%��KQY&�6L�J,�&��l�#,"+,�E1��J�l�4AE��$&Fm6�F6��S��cE%bHɨ,F$6Bh$���D�ȥ,�j���24i1��3d��Z2E�Q��fRIF@ѐ�1e5��a��#�d��$Ya#22Z(h,R�4h�)S))e+0�X�4Y#bԋQ�6kFh���JRl4�KfRZ�FBL�1�i��%IRe#2*SLl���%)��f4�M��h��4Ҍ���dF�3D��$�(��*�F� k4�%14���Z-�Tj5b��Fe��a��B��#c�أ`KAY�Ő̢#,����K)*dE�mƨ�h�2�QAb�	5&��0�,#�(mch4��d(�D�T�-F��#)[dT���4�",�"��-J)�D�6%2�Dj���E�%Fх1f�[&Jŵ��%e6Ȗɱ�4J�S �TX@�lll�l�$�b6��I� ՙ0h!Q�6f��SX�2�k24�4�QAQD�jJŲ�X�1h�F�IZ�-,�m�Z-QV2�m&�D�6Ƥ��"�"����R#��$�h����m���d։�R-�Dlld���U4�Fѱ��-�3J!,�V%��b�*6�6�*)JҌ�B3HAeF�IQ��řREi+bɶRehѬCLZ)1�hն�j�"eB�bJ#$4hئ�mL1�m�l[b�5mֲ�T��[)d�SSl��&��4eDh��IE�Y�5&f�*"�#2�1$�I2##���[E�m�����'�4�e&o7�E�g�5�a(�jNW�������{�*���e�h4i}GD��bmc�����#,H�d���2'���,�q:dPCo�՝���"P`�tq�K႒A��{�~��kD��UH�_�0��u��J���/e�+(U"/��a�{���J��q���q�΅s�P���٫��9'|��j�%��N(m��b#�5�f�I­D)#1�$v�l��1�#,�Ѣ:8Ǝ�'y�!1�r�OJ�Kƹg;�_�����3����j��M^,�2�ٍ.e�)���D��lK]���1�c3�(��λP��ܲ3znh�l�AL^,0����q��۲�����{nf��g��s_&��<r��}�R[�R~_�u�����ޙ��ulE�#2m#2E���J��hI���.c`cCby��< �x��ː?�0�B��(aB!�ұ^'���ٹ�����RSo״1�#%�� ֭n�,3ۼ��w���,���m���$�؞�%�X{��G�O5�����ܹ�7Z�a�Y���u�L���a��ɖ"3lÖ7UU�	뺐�˗D#%��m9��q�k�s��"0ޥ]s{��5]r���nQҹs%u�$�s#��^6�Wu�w��u�+��O{����43�leƉ�e�#2�(�D�~�F4��K��ٙ#,("W�4Rn�M0Z�@G���d���К�	)p3ƾ�@�:?-7�ly�27DU�;���6 �����/m��I���Z�QB����,�>�)�ruj�oQ��#,��i�aCG/���5 �y�u혬�?�|YH)ɨ�>~��9�|��ݭӓ_J�,�x�r��<��־K����#,��̤l�j�蟺������8���T�)b#��}��:��&���,�H_�Z��m<�_s(W�O��,���j[�-��E�6(����2b���_����~n�$7�m�Z�&#2�*��N��P�-#2�A�@��*�{iX<�Z�W�;(��8��QQF��MF�S$?���b��c!�+Ƃ�+����;3DR5A)�AX��o�0���bSQI��ܮ�uV�i%"��@X�'+��&D�)J���墶/]���W�)VJ��ܱh��-׻����E	�~����{�tu�lj6M�g�o�K}���>��a���o�`4��E��h;q�5C�2��bf��V}�&A�5����(dk&�}]�|_:9j罗���"˜,5m��)J����D��C���hzQ���QL��UiN�-wլ�����Х�²���������S�E#2l�QMZD1�>��2Z~��Gv�Ŷ-5m�e��„S���D+�b��N�<�kH](��#2<*�o�/΂�����6ŇD�	�˽�2��q������z�r�W~`c� su�$ߜR��#,Xe�xY`E#%F#�,b4��]���w��M�W)�����/��}�Gy��c��-SL��Ơ���84�������n~(�=,��s���z 5�I4#,�ɕ�!�7���\�crF��D��a�e� �#,�n#��_�M�cR鰁G�.]��Q�LR1���9�©ԧJ�#2˜�(��>ԥS�?_;珛�H�d��~�?]��Gĺ�c��i��ۖ����Ɣ���M�����Z����lL�C��mJ-��9Rr3T��H݋Ŕ/C�H��a�ygL1��N�8�r��\�~�^u{��x��\H�p�6熴zm�*�'ک�1��a�?>��*�F�������Z�4�&�Q��.�S2�k��6��x�uq�C�6:D}_&��#ZN�]��ed��#F��T׾�l�Kj��λaш�p?,�0#+��G��)�9�4�=Fj/nvfg����=�u��8Ծ�(S���z^�$#m���Z�<����kO�3�–j�0V�(G}���#,����֫����#[�m�=@�.�.5�����r��u�m������ţ\��]}6��y��!$�"���=yR���`�M�a�~LѸn��7|��L���(H�	�orj��]�۫��eU�(��q���c�T����	@^�ǡh��ӻ��+�kn5��T^�cm�Ŷ�H�q�����������TJNm��N��S#Y����6CTEM���'���家��RK*�ɐ�*V�_kB�#2#,����u뺟Cq����kHL�(S#,��~-UKTW����&|��n����[O���x꒾梾�b[y'Š�Q�#2(��3��A?����-��O��r��L�ϩ�\�(/�r�H���6���ઽ���e� �z�`@bX+Ä�;\}�e2��`I�i�^PO�-n􆙟�X#�~���\m���ϕmr}i���#,D��V��K�*^�L���7��u����Xv�i�	��:;��ߊ�&�������(���3q����c�##2Nr�k��nS繣�tuO�~��$_��抠�s߾4?�Zu>�v.��^1F�-�W���mv�#2c��i��M��v��]}<�{s��� ����2���	�TS�2�띜]�0�;�C���if�DMk�?A�P�0/�#V����Ϛ������-���%�x^��DES#2�����UHx3s0)S�J�:�x�J��ط<o.���fHg�+Cm��꩷�<��#,tz�8�5�`B�������u�(��`��n2_��fR�Db��:q�����������,P�:����e(+vteFW=u�����ƶ& �:F���c�~0Bi�y*���'���]L�u����g�e���6i�wd~4�����,��v�"�G��c�����gd$���rkh���z���^��;����[(/��c#��M��*�]]Ǜš�T�4Fz+j+g1U 1�!Q��Y�>�P�*�#,ʢ2,S�\&�X�@j�9ԡ�#%�j������M�4O|��ւ�$������p^C��T�a�#���ڇ�3�ç�?N6�N������E��K�)'.:��o�1���>>!�?�?c�7�n&��+5�ʎ6Pe��7Ωf����y��-�_5�vʍ�G��/>S��=�:%o.6�oχ1����q�׾%��µo�De��|3ZξWX1��Ǘ���z���s�]�('�Ҏayz��q�+��L�G�k�|��g��+0=�`�MF0T٧ܠĂ&�w"��}�ֳg��i�T���F��_?��Q�,mo�m�ѣ���ž%�C{���ܭvჿ�R�f�(YUG\��J��A�}������Y������tj@K��G����9*��1�Z�c�eC��]3�!�j���j+�3�Dh��TT��O*e8T!�_׉% ���9D�9өu뢇��2m�u�V��FzP�L^o�c��28mDzX��-��8���<+��f�J��������q�ú_W#,�$�Uh�c���1;����x�< ��փܛ��E''Ni<�X�D}S�*��q��l�S�y	�@iso�Hm2L�M���d{�M�yb�Z�0P�W�j^��_f#J<Y�*1b,�.���*�',cgUI�c��1���T��*2��b�lX�, x�Y��G������b��Y,H����S&B����SR��*���2N��V�o�;2���(7C��v�����3�1.�m����+�Qe�yB>�~�m}6�XŇ��T�P���ݘǒ7�b�n��b�#��C7mD��?���V]6k)0�iFM�����A`�DY�O^�;�+�8W��l���X6�ɠn���`+���P�Gk�~Y斪}�͘�䖖ǘgjϜ�r�PLoQa6���S��q 6@,|7�����ӳ��v@�흒�����-��G:�{��H~��!�pL�F#(KB���*c*kma�n*���Q��N�L�^ph�&�����'�ӦK<�q֡����'�4V�D�O	f8Fl���U����l�O�D�T&AN�7?�hA�0�ψf���k=�u�B�L������5����s�_���-"Q�D�@��v�=`�6�{m����Ѱ�9��VN#,��A�􄣧O�kM3���2<�j��5�[*Y�"��Pʍf���ј�-]�=.�@�DfjJ�%U��#y#%�m���){��r)q�u��Yy��j�X�	kLF�o��w������c�����x���lI>2��\�#���{�S�#%b�mꋀ��z�G?����Q��)�@Pve�����/��F���z(T 9h�����_��ܣ<Ti>}+_T�y�'4��)�Nq%울�(�8��L��7���	����*󷺢;y�T�6k����a�uuBC5�<��3�o��f�}���i��͔0;����kv��2C8�����e���-�m7Cl�Ŭ���pNm~��ҍ�*se�ܙL3��8�|���n�#%������}F0��#%����'E<���Ѝ�`4��*�a�}�?^���ʍ#,0q��m�|42eo�m���>�U�˦.��d�}&ݪ�%�c��B��=��<����w?�Eң�F-U��ȳܠD�����޴�,���(�i���5#,VG����$���Z�>ˬ;q�������x��Ҩ���d��8�����p'y:�G;��x��rO$��0�XY+iB�q�ɽ��������Ɛ�������-�4�D�����.[��J :��W��j4.�y�&�iu���|Lh��_s�r2N��÷���aÌ4S���Ɖ��V��{�6@�`�ҏ4�1��������,�<:A-tl�@�N�,��MCJ�/,�8���w�����:]޳Ue�*�-':&º�{v{h��r*����J<�o���!a�p�:x�e��;�l����Q��({��˵m�"�;<i#%����j"�(I�g(N�X�ص�+u���(}�;M�N���PY��vf�EG��䂎�mn/>75�]��Z2�_��[7E�Dy�[�ڊ#2�(Es���:h;E�l݂ˎ�Æu��$��K��F�V`�R6��9�X}ͻB�����-�R�A���#%$Q�k���G��B7��r���)��9�|y|0e6{�������͢�>(�:�����K��BBū*`��#,�[�;���>�#,�)#�@��U~yܐ�f�H�H��TE��l�Q4����q�N\���v��#L�l�܃B�T`�)6�4<V:w�wA�&�訜�`6_H���eG-/������iW����f��Qް)^tq�����ON�ף��틀�r��4�s�ex}�Jv��ְK�z>�5a;���kΣ?]r���E�ځrQ�\���Ǡ0x�v��k8#%��a�xe��?-�3��܏z��zM)�CKv����Qc�L��r9TbO|ӦQ/���k��D[鷏�3z3�+@�4�C��1`�Å1� ���,�Q�[��e�U�"p#2�A�X����sk6�P�#%�f����Ư]���X8C��Aݼj��mk���S���2��߻�_�b5��c�n��Ff�8%_������o�;2�����//G){�#I��.W��Y��e�=	z�=v�(q̍�;���XU~D8��Y�<xp��6p�#%	�ݤ$�A7���p	@	@H��K�5�k��9����]UG�ZY"E6I#��o*9�/�Q�?Ju��k�m-�6�<>-^__���׬m@'�(��*�z�|G��_٫[�l1�1��6C��;�7���Pq9�0DR #%����_�s��O"N{�~����{q�u�P��6�!�#2"#,�Mq�#%�YG�p�j���f�	neEXQ��.c�mظp��·�$����2(�A�J���~��G� )�"���/Tj� �9�%�]~g7u:A��`�#%A�o������r�0�	�Fj�Y.@�*"K�=�X��3	��'�Rgb#���Uz��F5��^1��D����&c#%%;#%1��o��sʰ���?�Ra����~�ᦳ>�����O�f'͏�b��*�bF߹��	<�]����R�ᱵL�Y|S�܆(H�>�ul<��^~�_�	2X�H;��#%X�kȵxz˦���.x��9�}:����@a��2�ٿ6�4����j]���:;����>���;?v`0�)���f���m���(�P}���Q�+��~7�w����(=��co>{:�1g����_���f� ��0�;��J������ҳ&P��_�����z�XɲQP�=��Ǘ�uߢp�d�~}���gS�w�>�XB�<�I�M�mG���ub���Oz���}�'^͡c��7B��W��f�r�\�pw�_`����E�T�֓q֞����ii5$D�?��ٜ�[�+Y�,2#^�e4���V@�f붼8�P,�9UaGm���%��	���@�7k��"�%y�z�x������2�J��P��z�H�����͘�PaLYIJ�7MC�*���⮈����*�cP��߯Vs�s������$���j�����s��.a'���c��Ɂ00��Sf����Ւ`zkl�ES�±al�����B�c��_F�g��,[3Žq1?&�HuH��M��X����ϛ��)��>��ܘ�#,a��O�#,ֽr�G(z� mԜ��0����Tu���D�#,���^vU(�(7��q�TZ���d���q@!U�	��w�z;�/�7�x��X��� �!!�#�6��u�;(JH��on���|Y5�C������wJ��2s#,V�U�Af��L��R#%bM|3���C�:������V��#%�tn�В�����6�R2����&���k*�(c�~�ͽ��ƄNI�w�SnqM�L�Yj�#%���#,$��^��3����nq�6%U4Ѳ������0Dj��#,��|��.��İ:�xM֝��RI|�c��紳*�.7�%^tB:���z���3�|��ФF�Q����j�]5e�%.�T���q����3+8Z�ͥ=����VGDw�VIB�w��q�H�:���W��#,�}_O��,v8��#)&�#,�~��.$�ڡM���j�Q���  ���5���p�v��ۅm}M��s��AB)2MB���L ����;=��l���ïe��P�#2�h�"#_	�z����3��2&�B�х5�6��ܦ2,,���|ز�R�"�Q��Y�y`A��+��:�4�{��Z�����͊ktҟ�00�yk�W�f»�c*DXEY'�cLmX�p���]��6/g����	� I��ա!"D-;��p!�}��Gȸ�7�Qor��q#,ِ/���3�G �e��A���	b@1@00��#%��!���)Ƶ��"]!��hhRv�*>�����@z���Q�NU�H���ڭ$�ԥ���*r��-,P�G�����;.�sw�=.�w��L3�0ɞ�j����1��s��D��μ�r����(ݽ��!H��>����^k��R�;#2(=x�q���#Ig�x�4�hV�KD"e��͜�=Iȼ�]7>�=x��)���ѽS�ېݝp�tt'皋��:TP�Q����C3�(ҁ���#,Plu�ŋ��kq��̱�ƈp��#1s��B�s�n��C�g,[���#2]�P3y �Q�'���	c�z��cv��!#�V:;�ͽ�:y���G�6He��;>F�����pIm�����O8�,�}YE�y{^�I�fxO�pL��G����?q���DYP���5`!/�2�^�@�{��OZ�c�\ff��W=��=Mn���k��!?"�;�A8��x���=�#2͖2],P�z��w�e������h���r�Q�������=��ÿM4��6����^�Ѹ�.`b��#Bm��!I �5LUaL`�ѕF�g���0iP���"�H`b#%�:���[�5ϗ�}q&���k1��F�H�v�������q�(��$�t���c�+��,�e�7�#e��R�R�xš}��q�d��b.6Lj/��77j^&���*R˱�!}9�!�8TT)�h7�xɐ��#2x!���1BD����}�5���%��CSZ�\#,nVٮ~=��˴.��)ݡA�H���;U��M�S��h��_I�KN��W��'��е�[l3�]y��a��3^}�³��x�5��8;x�Έ�2S+���Ѧ��䩋^h�3�'Ff����cu��T74�6L�V�B�hx��T&�ɇ��d�5PeA��[0�aX�@���H�̈3#%�Z\��,qbBf�Y`@�#24`�����i���K���ؾ]���#2H(l�SF*K�t��W�W������"�X�2ѷ�J6ҭ#,��i�������U0�b�l��IL�P0�#2B!	0	3�����n�v3;������ź�~�`+Ef,Uq0�X3J���Z(�5`�|]�mH!��U#؀W�)|����@z�DK@�v�v �[F	��l�'��7��w�tD�ქ�{c^#	D�#,�ߣP�\{������7`��-���Hz���<���B�A������;�V��H3���m7P!fG�*]%�m���)b�K�oS������r���ș��WZ�8�c@�|���:_i%�I�l���T�`��=��ٿU��BB�_�h1�Fx^9Ko��9ø>�s��4�Q�����'ML�'#,&���H��vԝ� i;|��[����a�#���<u��csݗM��@j�����I$�����m�j��?H���p@i�f�Yy#,m	�RQ��(00�Z���.��a��p{���a�}�TJ��u<�G����Ejܡ����ֈ�%�#d�{O�9��@��(���4���#u���ep�*8'mJ��U'����M�w�r��������^tN���~�-�%#%�#,�2!�Gy;ɫ"+ ѧJf� zR�Y%�2�h����:��6�R(�H��y�*I��[����MH��+J��v�#2��j�7�lB��mEhұdt(�h�1bfZT�q�����;�F��Ǧa�A��!�b�K�#,��}�^�טq�%Zl�v�g��#2Bc5h#,��e35ҷͩ�#�pPҸF��.����4vM�s�ď����r��\d��\l�^�&��ʑtG�G-9�3O�G�S(����^V3��w�I3��"�]e�w#,r�u��˽N������p#f���z܈�ע��#�#,�]C��k�ޣ�����z�)aH����n�V��r�uƟ�&G���C%9ȳ�q���C��jm�}�(P�r���E)"ԅ5��vyrn.#,lGHR囋�E�}�e㺇<��g�~m�q#֧i�>NcUGE��ۏ�m�dǐ&#,<� a0NϊsfEۉ����b-M������4�Y,Ħܨ҇Z�EX4��E\�O7�A�,��@�GnP�:�O�cJ��:7Zf6O+�&�H-�v��e���.�����1�yc@����f��3���U�R�n11���jDd �~^R��*�����q}/l�t��:��'��V�C�#27��r�2�����c�T��f#,��B�Z��:�3�'V;��X ��ʴmz���xۍ�Ϥ>�^�N��]#ӑ��Ks8f:�F�!�y��Sh�iN�8��E����t�F�m�Z-�m�i!��D=hh����U��a#2]��ʝ�C��0�w�m�y�f֡����+Pj��i�+�	�6�l&������z�xi#%� %#%&�.e�%n�tX{s�U�?so��p@~(M���kk�����B��u.�u(p�MѠ�bh3�����p�t���Af�����R�9'�"��Q�;�9�<6�r����j�#2j+�ۋ�~�N�j���3bJ�V#2&�� ��D�'[�.d�����Y%���y����'�TWfB�����(&es�y�ù�C�b�t�.K�4w�H���1Yw�|>��]�#,�P��|����/յ�+,��7=�u�]:��x�����}�}S��0���<�ͧ����:+]�� �~�`"1��|Z�{�Ԭ���$#��H��`�w��z4I�K��w[��z:������6��1e��1�TW����1A��~��<%�(�h��C���)Te���W�8��Sn���[-I[r��}�ů�P�M�#%&/��ڲ�I������O 	Ί	@�	K�w��t+�=���x����tdz�+�ǂ~,�bLO혩R*���g���E3jK&�1�*X�_��bh�b�뗣��E�w:�Ү[���%#2���>Sp�������	���L#2���?�,���]Zm�`bP��}�y��j񠋛w][�W-‚y��ؚ��򿿟��j���Qr�h����J@��ϧ��N��O����ŽY��)���k[�F��맟���Ž�J:3#�'$!���A�AVD6ޒF��-W�kW��(��a�����C�p�����M���K0��5@�T�%�M+����G���8��?�U;pW��	q�ۜ����-X}Q�_�?���Ջ���3K�uc�B��	s��ճ�����Z�#,���;`"�nx�iepz8y�.'#%����B�C��h#2V�-9�[�]�hl��!���$<곸�p�P��p�#2Z�AU��\o���O揀J�#2(���&��T#8z��c� y���eo��?���N�&*�{Q?:�6���Ҋ�B���&�`�?�ٷ?��¡@�0Rq�A�#|����t�j��y�A�]�~��o����?O�+��_'$Ο耴9m?���2��#,s�w����<��r���t��q��� n�O�l�m9�����w+��ϽG@R-�`���"�:D&H�:�����Ԭ��b�G���L��D�Omп��G�=��7���,k���=~x��˴�r�n��>(��I�R6���u~��io#2�a��{ ��g�g��N2�-YS���rC�(#2����>0���FoZR�%ZX|i�����`���Z�|I")�X�#,���;C��}4��4�Pd�:/��p.Q���~9�i#,xR_	�Ź��H�y(�>����9���?Q��O�3�ϥc�'��У�0,i��a���w�<w	�H�T����O�3r��$s#��Ξ~��#%ؽ�Y�X7�D�N�$�o��������3�ӊ���"���q��|m�X���n�?$�5;�p��j*����B�''5=M����THO�eCޡ�R�3M������٩u���J�B�}l��?���~V�&-��1!1�!	k� �P>2H�Dh��)���:�So��G�gH��'m�����Z]�#,��\�)�bI��|��Q\F�Z �� �Hl}zM=~0�9�[�����ݵ�#�<#,,����F��A9�į�X��TCi���Z�V3X�����~n�\��"�>#%>r�:kMO;\�ŝv}�r��wvO;�xr�?�F�F�����7�C���.0��	)�.A	~��p�x���?��<ӯ]�7��[dä<������������/�~������yu�U����:}T�Rk���,�b?5}m���W��#O�cIKk���\����["�������#���}�?E�{����~ߎ\��!k����~8ED�U���?]�R��>n���&��#28�pboٟ�C��v诹ZSy��j��G���k�����m�y�垟������e�E��2wg�S��=<����N�q�x=���	!������}�� s$���?�n�utc����e����ߏ���9��!-2���Ɉ��l���u�����q�{^�1����z<�f���v�_5i����#,��Ւrã�������g�R=o��ٷLn�����倶��CΕn�օ�.�j�K@,m������5���m�@�ȥ(�}��J�y4�a����M4F��0����F%�.lA�>2.s���?��9�Q������'q�r��||9a����wk&�c��b%��p�ڮ�������١��Pà��k'w����4���Y��UqI|:��zx��D���Xi�k�1����k|G#�ef��u��{�7�b��]�9��!6���������G�{�|����q�q;�5��ÿlm�Cj*�����z<����K�Z��l-�;���J�p����H`~���RC%���^e��TV��i���'USV�o�tv�[��:Dr����m��E߹D�W�s�WϿW��t�/m���؞_����z}���״��1���Ю�]�z/�ǵ�����i��s�0�/f�����.!A�:�}�^9��va��W��u0٦K�[Gͯ��g�a����'T��3���_���w^2lS��7�|���~���ў�p�C"�%#%���8W���U��g񭝟U��nx'��������=�6V�PL��;�9��5���Tz5���Њ<��,�s�t#,�M.�+�SS���r��Cbt���������Q�u���=�9�wY��寮-��������~����_�6�����Т��t�z���ի�A����~��ʞ~���_�����m����}��	}��f���;n��=O�w}��>��ˌA�έ�-]�&��<�.�H����A�Ph����r�<~/�}���]����=��#�y�����.[�Sl��3˾�;#%���n�#%P����$��a�X�:۳��#2u[��W7#,#���ջ����F�Q�Ҝ9����l��n0�|�:�>�:S���A��/�-#2@���G6� {���OĖ�x�y8�nP�V�Q�������c��ڂ�#2`�ə��+����Ժ�%7���Ɇvy������׈�o?O�����_��]�>k;��G'~��ɒ�G�;i�(��O���"���y<P��Tc���1}�^�7�>=|�:��#["I�XTS�� s6�#%c��NL�_E�UI{0�Z��W!�%	� ��G��b�Qq��G4�I�B'#���Xκ#2`�&��dž��ǵ���ݞxS��~.�qJ�ڥH��`�i}v�����8�-�.j8��^����fp$�:�	yän�>����i�垟�����������L8��M{�X<�c���E;A���`�|�ZQÜ�2q�ǃ]kX+GtO��6��r�����|��ֲ���Q9\��ܵ��l,m�K�P���������������j�Ӈ!<y���{�\�%��x��4��d�k���$$�vYg�Գp$��[Ƭ�$�ӝ�	k�)nAu�A�Ѭ]�[y�8Q�X�qx��4y�{Ɵ�Q��G����s��ē!�HBJN�(Q#�s�����}�Ǚ������f�^�vM�ե���|Y��H�<G��H �,~]�������m�ÏH�|Z<Pۥl��#,�e*�����S�$�Iǜ�w�� �(��BM�4�|����:@����ϣ��_]U��÷��O�iR9v���[�N��y�&L��,|��a���.v�w��8����x��`#�a�/S��>����y���WC���g7���c��n��w�=`��ڒNݯ��>���;���F!�c˕�9�?K�g�$��~���G�f��o����:T�W�#���TO��T�,�$x�;��:�d����+�0�#%Q�{Ll/��1V�������6�C'��?�-Ff\�ږ7a+,��DpaS�zTcZ�F�A��H��MJ*Q&��#,cqa ��(8�#2*"�O߻Si6���8kMjD���	������-����Aȱ�a�ILA�"hhn�)"�4�[VW�c��'�#,Ss��d�!�IUP����|ѱ���J����h�i�'�~��oG|��,�1����wH�V��xMf@z�k�ahf�䮢�ש�N�,;#,�.E�L��%.��|7����?�?U��G#%����QMF2DH��@��b��i7�1�lXT�Q&F�CV��6ƛf�J�Tꪀ�-m���f��q�����噧?�4_�'���I��F���i|8Z4Ϭ�f�c9��n���g�}�o���f���W^�����%��[?7�����1�za�ϯ�<qM☧w��p}���c�����p׈�c����4�����eVMq�eo��9��5�0���#20�}�(�H�Aá�au��y�=߫�_�W�N�_yD� �+��\#%p�j�m��8m:�|��xY�G^p��xYu������s�쯓�������k���^#2�ԷS�?Ž�wF�.��n�:��M?B&��g�iK &��� �B�(�~^���֋���N�����Nv�&���1[��-�D��P�9+��V#2�a"X�#2%� �wL�Ŧ�F �6En���^�z�z��U��*zr(�5�� F)X�`2(�-p��#,����g�F�#��UZ��ڌ���Z�ʅ�؄`�$��M��x3��v�%r(*`�2�shف�X�;]g6��%4#,�c�!��bY�0̳�Qi�#N㣩e-�g��8o�)(�ւ#%�#24�����ˍ�aWZ�w��i���D��D�P�S������Q!4�?���Z�ī�NB(�EsEQU֙Q�u�JF1����t~	V�	�|��AI$�9�%!����y-	�E�d�c=.�ý]Q��Fh2�_�;�:�9������x��_�;�h��QON�ׯ��D����v��	�S���(}�f����j���q�h��4;����f���#2�޼&t��2�|�MO��ݹ���ه�Ǭ/}����6DDN�E랺qo^Z�3����pYe��&�~?��s|��P�������0�a�H.FW�)�A~����^�SR8�y���P��6 Ҿ�Ap:\#2�$�eUV��G�Gp���č�'��x�����8��?������|���a��=s�>ښ���g�����1<�Ta@�:�q�;��π��}k���5�ۨ,�fɝ��%��C����΅�����f�#,�\��S]�y$�$%��ק^���ab���;�>B#`���?��<KD��p�Y��ʨ��U��VR62B8��+�K����O�e�y��yte�(�7b��U������������O�~_��i[�Ϸ�凃�ֲ`�(!$�%`�g�\�z�2"�c�E��Eh�	��i�KC�����ۦ�R6�k��OZ�,[�W2�a�jVi�V��EXf�aF�y#�=�fhPi12��X_4MZ^%����L�{���#�[h�>٩����X,�m����#,߰��h�5`�yT�eLzDm,ݹ��#2��$d]_#%˒�tG5h|j��oV�a#,j��nD�MN���T#2J lXdL1a�4Kl�#,��Gr�3�t��p��I���X6�jn��eɶ�*�<���Փ&C�;���^h�EQXaű�����x�d�4�Q'�A�j��)��o����6L(:qQY!.h��z��R�#%�(APE�wn���p����w��S�HG�ߣ��$�#2Ze2C����8�0[Ʉ��P��J����鏰����2�q�Bݎt�z8mG�6��z�>��*��W-~�:S���0�p�m��k<�����bŅ�UO�J� `ӌ�w�r+�DjGH�����Ҍi�O�|t�Ud�N�G�#"D���f�65[�D�-���J�t�;������p�ﴱG��zt(qPGc�E{�/F�4��R�h�D�*t6���c����6��U��D*r�����vk���5���$<�BPXY�[`�!���5o����_]�}~a��ys@xy���'^�vZ�C$��/_��{����y�/PdVn�l��ɠ�rҴ�uF:;H3�+�`� ��˜�PJ()��!��8���s�#.��@��im���);B�.�����R7x266~clyUE#Pm�]�B�9"X�<(��Мk]7��f`q�M���%�Z8&eXP��XJe@���0߅+#%hf��FR��PC��!�YJ(K�Lė6J�3�%���FHp,7q����ςj �]d�#tt�p�Ѡ+4�غՍ&3�6uvh.>����h�4�#2ƙԡ�3$c#k���&E���v�`j0t�E&Y#FS%|�Vn�~����^��+�O��E���6�0���[���j;�:���'>*S�V4�^�:r=d���C`M�\}�v�|�E�d+� w��-x@�UTwC�$'w�5�HK��ƛo�m��h�b�9r�S��^@/$T�Dj�m�Y.��#ԋ��#,Kq��ΟS6���]�y�}�f�nM�*�Kq�{��Z$�-�<��;�HUP��s=��m�(#,���f�{xm�E��M��b����4ӓI�D)��0�8�R()�#2����5Fv�(_�B�/�c��b�XR#,���n���|J#/���j�˅	�֥��C���7�p(�����F�D�d"3]�(أ��#�pk�}��-���ێ6��@·d���1�����gm�p�5������y�Q�boyN�>�t�A�m�&�#,�X�)��n�TR�O,YL����F:Ƶ���-#%��]ڗP���*�:��*��yZ���eTp��JJG���ʻN��s���pq2[�[`��;���F��2�iJ-��8�M�k]+���(5���#2#�ࣣ#`إ�q��ӽ��mGQ�gud�bY+£s���o-��o�ȥ�#2�O��X��#,����.:1�]"�c�"tb����3�93�eL����k1�f�t��f,�1�+���&5�Sa���rI�6A(�%��h��v���:�0lr���NZA<�kRhdA�����2�=�+^]�~����!'}��J�,yv� c�Z��9��z����2ƃ�7�����9S!mD���;����[i��\Q���=��'�#*�}y�յᯡ����q9��"���'�aMm�M?"���w����]x�ޡn�,��������<�XM|an���!ԥ���Al��K�;Ɩ����)�F��P6��,��-�e�4��e.�ᵗ�����~n�k{`Z�V���(��~������2e�	�$#,{F�(qCv)5��P��UD/��aX���O�I#���3�+�/��u]k]V�ӰB|'�6��r����l�����"��Ҥ��|â-I��Y��D��\�`%dn�;l��B�#,gPc�B._}�Ҥ�z)�$��᫲i�^���)f�]y1��W#4�*�����-���ѡ��ꢧ���tm��Q���S3u#,:y�,�ۀ-��8Q��ug2`��#,1�(zoZU�ެM#E�����wey��y����1v�ۂ�O'�g�yBt�ټ�2Ҝ!5%M����`��3�ʄ��1GQ���!�N���+����0��$�����-F��t�‘���1����n��Y�zY�B5����98�(vA��3ij/��Q���7v�i�'�8u��.���þ��}ƞ�!4�#2*��d2M@*�_�K\p_{�ԍ�,W�,y���?B>z��`׫�x���$@���a@�������Y�3����E�r�ظ��>���\��>]���2�倹�iߩ�S�Kē,M�@����@H�QH�ڢ�	�A�K�M�!u���mg�����m�����)�>!e(D*e�l���`�#%'���߁��5l����dw��A�<7�F#HX(�#%���ysd;�­qQ����Vw�ДpUBLAsv����K�Ez�?��+!ܠX�t��/dDF@�󀓱�;O-�d�1�N9Kɏ�֪��xήQv����hJ?W">Y"�d�p{�#2���l��8�{`�B�����tf�o���ؔ�*�.���� [��5��.,	MK�x���ɘ�|�7_<��o�l�RU�%�eː�L�?���`��1l<��EjX+���kN<���q�LJ�Ϯ�I�b%���0�&��1C���I�5Vʵ��9���:`�#��l�L:ߕ�m6�®�j'ɺn#%��}'���][gɐ�b�Q�,�tv��L莓¥��h�,�LT&����ɀ��k0�7+��4̪�ȣ��C���{��%}}a{��M��A� <�	�MM�-e�q�I��G����טVb��M�䆇'd(uNl/�B�d	�f�M��י���f�Mt����m�F�P����i򎳎�1}�CMM<�Ԥk>u��1���a��x��zS�N榈����W�����Mvڟ��;╏#27�4�1��~<�c5�q��^���n��M2s�=��]�'?����f�(~ ]Nc�B9�~Q86���72{��[�u���Y4����bG6‚�H��cƒ�fseXuaz�>x�L:-	@~�གྷ̈�?_צ���"�!4�~ks6��#*g-���M�/\Fd-��F`��q#22����BƂ>?#<i"A#,��/q/C��_�� k�ڛC���;���OWw�Zz�`y�.n�ڡ-���'�W�b_�v1��'��u�v�ˣC�7ٓ�4��O��e���#,6��7�x�3LuGY��>S��!����jan��f���08�"�@�@��R>\}[���������c�r��XZ.�,�����#Ώfi?#��G��D��������=`��@�����#2�o�ㇿg�enk�kP4�����4�g>^����:��v�$N�ׄ�J:����C1���a�qPLEs���\�5���C���dψ��AZʊ�.0[��nq���F�a���χ��Q���j:9�9l#�H%�n+���ȩ�A�f�~���{NT�0 ����V�&��g|�͋@�)է)O��b�H��g���}�b^j~8y$*�W��V��7ڲ�����ф���r��g��s5;�Guµ9#�����S���#ܩ�1�ȱf\l���.u���_J�k��8w�a&�J/O�K3b^oB��:^��Y'��� m"��;ڵ3���s��Ǚ#,[����oυU"ۑ��̝[~�ڋ�&�*�M.�`�V����*��$�'3���gDPрe��˽(C��;o۩�6�����Њ#,�"#2*�V��#�����R3�����6��|)�8����7տQ���e��#$��XJljU���c:=\ֻ��KtϜ�7��jmcԮȶ��d#,wgk]����z(Վ����\V��Ӹ���L6�$�E)}�'��}'n�cg6|$ P��M�SAͽ���B�w!b�^�����(|��ѤS��b������*y9N��_�ǑFo%�*��a�g������_=�Ro�V��έ�	P�[�+�8Q��h����|�8���_�gcc����X�*�Q�o�H�G�d�P3�4�3#2.IDg_�#2��ۏ~!�ʨ��s›=T�h�q?�˥��	~�m��i����l���J�{��̘d�싽��e��%����^�QF%�i�!0�P�8�ލ}�s^G	a�Z{x]#e���-�,T�e���-�6H�~��m��2&�O��xr6��['�3��껶��c}H|�%�x;�N+wD�!#J�AcFQ	 bSS›�p?DC&7(e�㎛�VܰdQ�<�����)�C�����<!]:C���X,�d�K��듧ZE��t�Z�#At�F:�eӇ͚�H6Ҷ|���ļkg�X3s�S�������tc�����#�{�|O�;�r���!&�tv|�j{#%�`����WԒ�"q��5X�-������$[�ѝ ��a���"G��Q�f��v:��`u�#'<u��*=�$�5�UgO�t��V�-��c��iH�kt����zZ�'W�]�p�‰z�ƚnD�c�F������sT�f��W#2�/�9=jѴS�e���I���k��@���b뛣��X��Lm�'�z:;`��t)�E<PX�]R�רe��|����(��7��9��Vܕ;b�_k���3�VMq�����u�<�v��Ůխ^�^Q�_���^WƫW��GEVf��!�y0����>6s��L.��bi#,�Ud��Ϗj1�Y���X�>Ǽ9�F��"��+���}o�ϒ^��o|*��™�ZY$'�����Hd �����].\�L��7���/q�X4Vت�چ-.� ���ًE�R�t�}��yeQ��[C�����^`~�`J�RS*;-SʤR9�J����宜�#���FNvש��VC)�� (B#%�pڶ_����.���_M~a$���m,E��[��׬ˉ�d�M<���Rڸ6�u��ZV�iT�#23X����W(�]��Ju����(+Cϋ;�����k0�+ž'bS<���w2n�<vSK��9#{���f�Y�t�?X����T�Q�j?���o]yѵ夶��g�iQ����z^}�̹�m��c���4�"R��Nmݕ/�I�nd'��/aC+fP�R�ǃi/eۥ���=�����'���w��{�������3ж�aQ��n���g��'��t569��S7ήxz�^,9��`k�[��#,�[r�At�j�<�������es;�R��T2)����L�h������#2G]Ɏ6�Q��k����4��C=bM��o��������d��Gf�[�w�z���u���/�2�7L�;���?�+jZ�ȳ�࢏�����髰�Ⱥ]\T:�Zm�>}J,+��o���H�nC�,{Ϋ�Me�q��ot��g�A��9�q�{}�*�ݧ�˦x�c��ei.�J�р�TX�V3yM�#2F7>˞�a{�m�{(�Q�9ڲ��7K*_j��:/a P���P�N�_#������6�m�O��5�����z�z�ƨ�cU��]t�H�K�W/���V-��!y�����Q{�,��i�.x�<\	�Ҡ@�&�j�QI��;21�1��*��|wΈ��u��d��W)�'@������ݝq�J�I��r�L�`�a������?˷�Y�9��[�#2����0;ͷ	�N݄lR�j��NYX0+ZV6A-�IW{�V���G�)څ"$u�Ɖ++⭴��'�d�-d�-�-~�axƫa�z�6D7�m.\T�PH����LĒ�U�C�nV�h��{Y*ݮ�9j�9L,��,#���7�Z1V~<k��\o�LdZ�ZC�_8ي���Jn]�Qd������0�����1�X����17��P���B�s�#,.��a�ͿX������5�L�=�ǘ��b#,.��~˟d/3���w�P�R���`�965��Zk��š���B�q6BL�X�u���zg������?1M���+��g�#,��#E�-��_+g�.�;� ���I��ó�J��Y�'_�$՜�;^ޜzX���Pw١�˷��,?�P����‹ӯt�q�8=�����_�?5b�1�z���L�Y����)��Vy�-U�~��v�C#2��%PoYZ�Q�NN�������,�U�(Q@�o�������)�{%�[(�^��]c-M�zB�"H!��^6CU^`��H5�1���d@�:#,?$t�Y<^��.ݞ뮭�P/Xs�s?�!�N#,��i���9/���1㉬M�7���^�V�V�@V���79Ν[�Fp#2��N�dGN����i{ƥ8S�Lz���m�X�q�����3��bW�w!��yi��J#1�L�a�W选��V}H�AӜGq�Y��t&��5�;��8�.�7M�2�WU/p&��\b27�_9_���B��D�o�	��z��6W�oe�V��(�K���JUo뢋B��χ��8#,Tp��q v�������u��`55Bv@ipx�#2�y�k�����{���2BB�I���I��=�M�[��S��ꯦM�a#�M������偎�����c*/W��j�;gRԔFͱs})�Y�����m�1#즫Y�X�|���)�c�#2LxN�%�W�B����=�Y�T��[��13yFG{S�6:e#%�}�+ˀ�|2�oi�KJ��1ӓ�i\7�l��Q��8������Ua�H�A�ɰ����)������$��h>r4MG*�����t��@r����\�����-���і��9�|�(l�X��G:\C�j��ͿX��Ϟ�f�ơI�sWD�/�#,��{����4�JPntœUM��t8,�lױ�Ѱ����*k9DD�#2T2����q�в�#2����k1~6�#,6	����qt}����[D4j4�%�����u�fv*P��VDuj�%�}��ㄖ�\{��)�x��,�p�1�8AY�{A��Bx�h�<���{�n���N.�X�.�5��4t��6�պ�h���]7�w>(���!*��{�b��婹j��yF��u�, �Skĝ��.�wNT��5�������úRs̗�W���uZЊɰ_nQ��A�;\�V�v��g�Z�`��r{x���G�#2W��F"�\�Y�w;(]����!T����{c�&[�oH��ڏoj�{s��X5��r����H<BssZa啸{�%�m��3¶[��Ņ�D�`�֪A���ov��0�����H�p��)t���(w��Q���I�*^<���Q�0P�UA#2ѣc�wv��8%x.L���n����FD�oV��W!t�,�t��eJ����aA�~�l�͏�K,3����'�����dv�F�Yf���<x�>������R?�*��@^2].\�}����%c�S\i�������e�#%�w.�mM�B���6�֢s�ҽKRBa�֚���Rb�B���7vB�'�샚;s]���cG�����8M�7K�I򅛳}4i�C�H����t��N�X#2S�z�3fY�R�$&_}��|ȜwÔa�K�%tX��g		��%��\U�{�jj���j�^72O]���;�ci!"`}��\��x�0�팺)��rRF��U�,q�o"�\N�S��l��3F�۔o0B1C���OTy�Q��t�w���m.�O�w7��ڎh*�f������As����}5��M���ۡ�֣�+�Ω��`�-�|n�I�Ŷ�@[���2�����P��T����<��{�R��G2{E,�vN�E�Ϛj��P/%]&��nݮ�P�;��[��/�ոF��q�5��Z:ad*�u���ۿE�<3��6$���t�cQ\\<j�\�.����x#,��͊����EOW�A�'Sh;޽!O���q%��\���Y�4_�ܮ�ޤ�	w�H#2*�-��B�7O~�"Bdp����#,�^�)��4m�Κ�K�v������z~��r����>Hا��[�%6iʟ��~�.se���3�0�{#%�>Vt$�mh�/ɛT"y�����r`��C���`�k����;@�0A�G���1�mъc���C6yv��=��S��@� �v���#2?��r)Ń�{��#,�"��dn#2���s��I�3����aӃ�������,�{`���A�#2/,	(�%�+z�u�[��:mP��G~楲%�sB4$��'�Ū:�G]��8q}.��B0�E�h0��g0%�[9HW����;��;��t�i����pV2pv�|]x-���Oge�bG���6J7�r�*�J����1�9]<�%����);/���؂�Q�5���5��Փj��C�(�=��2�6$vY���%�*� Ě�i=߆���������a�=������H\�i��8XL�QP���/�sۤ�z�kӾ!�5��Ҝ��gq�#%{���z�.�[v ���l���0��#,U�b�u�	�	�o�F%̊ZZ�4{�.�:7w�x �A��vǔ��#%��#2��ONʆ�KE�m�߳����H��C���� �v�N�S�nA��R�����y�ڼ��7�Hg��EZ�'�v�l�*�vح�I���O$_*:*a�:��ե���� j˰[��C�}�咊�����G�^$�����Y�sC��#%sL���u�G'6���$��<����|����!������@�_�`�u���4�7��$�����cc���!n�XbQ�f���@�#2�鰄0Y�=-�|�^f8F��{����</��}~��w��y��	�JZW�˘��#%��֠؟��Z+��`�5�9��P��V�v����4������b�Y��g�xTWƮ��]����o��ʇ�"�T�(�~�_�FĤZ�l��Ԃ�{4'"%�!D�J�e�~��0(#2��qx��"|���x0�"Л���b�b�j�mm_�_u�،.�M��9&�'���3)ڳ�g.�G�O6dj�`�<�W.�����Qa�>�F����(��{�ﰑ��<?$C�9�vZ(�mWr����*�*��F�P�-��&��Qg��E(69[�D#23h[�$׹�(�]>Nt�"rNK(����z��K�d�n*�Ŗ@��G�E�uo�^�������0nCq��.��̟����B�=w�c�H�5# 6����6.֐��3��\�#%�|�#|��#2B�[�4��#2��"z#,:q�,�!�c&d�?W�T�=���H�.�Dh���G�O�0��0"#%�>����KN���@ *�2�(�F����K����ī�ตhA�lK�:�r^����쳏�t\e����gr�Tg��d��e��:�!匔,�������&���oa�\�ߟrv �@@�P��E3�Ӻ��?4�C��R���7C������ C�֤�BJ@׮���#%�+7ag81�ʼn���Xt�I��Hn]I0!�aT67a0�G��#%�h�����M1��{b��2!�do����d�t�a?���	�}��͝�}c<h�>���n~�V:��B����C������v��|3K{�C>h����&A�Ľ�+"��]��ez9l��B~�9�:8B_�驕����]�{UP ���e��`�ڻ�i/H�7#,l.Oj��:���AgE��ܰ���߳�J�'���ܟ`/��g�wG=�P#q�Z@�5� ?ҝ�b����<A~�H'��ݏ���jҊ���e�ϯ�����}tM�1���FQǧ�����̪��Z�C�I�)@�jVTԿF�s�f�4E�{QO5p���̑�dd$�UL�c#2H�{�'�	��i��8cm�S(k3�8{��HV#,��|N�6E��I�0�t:�Q�3J'K�g(H%�E7�GtD�8����Iא��^G��@PL!ػ�s��)�#2�vE��n׷eQ�Ey2! ����݆W<�1��J�`Qf�YA�7M��u0*"%l+a僿#%(1A&�Ç]�;�h��rr^�{��$#2g���t����P�O#2B��T*���7L�C�7��#�5��h�'ˑ��ؔe3�{��~�C�"a!�$����z��ޱ�=H���8�3h�+�#,�� l "��Z����i�'W�1e0û���@�"���ӊWW@U=E����WbB3(��e�6�&��u�F��	P��c��������ɉ<��٣���렃�L`�<�8���OguK�A�#?���	�%������-ۤ&��������^�<a��-@&�9���SnepN�W�/Y�����yA�ٜ�w"��0�mzg]%�$%s6J�H�@�^V.�Dwg��R<�,I�a�����uZ������O��-q�~aN���~��r��W�iJ`89z�Q�@���-�&w�oĪ���k7��b��P��I"(�cb�r-��h|�#%GcNN��3Oh4����*H-���t,�?o�ns��^��8�R&C�1�37O�Yj����绣D���-8}r!e��g:`�d��uՙ�`�QP+&ؗ��`KH��6��C�Aݝ���Q"�<�/pp~�{ܻa�;p�x���I���k��jXى�t%�k�����ߖ�!���_��u�d��	vL1���,F<JҐQ5<Ƴ��%~�� \:m��z?MQ����a�Kˑ����y�߃��OK�u�.-���?Eo3�	�$��#,���h�B3g�#,��?(Pq#29d�7�ĵB*@!�&`(ouG��#9�$�9�>U�m�(��3-��/+�	Qh�s�rP#�sݘ\�%���q{;��z|��*��E8�i��qIIh�	B+���<�C�)^�`��a�qߋ��FR���8BB#2�\E&e.�����ZO4�qp��[@(FB�x3�\@H��y�.����ޣ`;kj�ι?;��ƥX���[so��{�I#,&���������u��/f��2<��͸#%�m���?��*$~��Ҵ�Q3�GCy�����۬œ:ї��Qќ΋Hw*������`�&�x������{ZR�|#2=�q�<��*��p���z�&���H#�s[9����Ԕ�dē�Xo�R���m�����]FS��6)8xL��7/>s��aѱ��G�O��T5������?.���\��3c�{		���[�[G�/y�bB�T�o>��d��t�E���|6��^�\I@d��Q6GX��F�t����"�͜8E֎v���cΓ�^�z�"S9��s�ྪ��YR�҃[�&Mn�*I�mRt�-����#[��4Օv[7��'�~��K�O�����ͪ2kM@���y��5[z���yn_o��@[Z��!�&(GbL##%�m1���҂V�_F��m�?��2_P|ƝT�9�3�j�I�Ȁ#� ˼���s"c5�x��{?(l{��ݥ�7�:{s3��������v�ۤȜh�RqG=�#21��RP�*lҋI���;���W�:c	��k�;����,p�k����7��=k��z{�.�m�#,��ro̟���-���|S�ϙ���ċ:21�N���MT�ћ�U�%=h��Ĕ�y���k��-�������u�"�JV�ݿ:v�^y�y��5���?��/��ڦ�����Yu��*��2����Q�B����χ�i�:�PUT��#%����'W��)Ù�<<R�?�������0��z[��}�x�2��kod�(#%�>�7���$�y����'��/���A���B�AW��崤z@���g5ʮr��8�gv�M��?3#2!���!x/��^��嶹�Ջ�պY�p�:1����u��؟:��/>>�b�5NP���G�˯��f�__KW@���*����J�!�q��TSl�c�f�V��y΢W�>4��U��5��"�����K�����e�=�ֽ��z�=`��������ݿ�Yh6�G��:�#2*_L�I�����Nb�����ꊂ��"i(GW��_r���Y�Eu�I$���Z������8?���ݏ����TJ/�fr�?k���_����<#�=,d�W����A�����}�C��'`Yr�a�ցl�t2Tj J�;T�t�Y��������[b�,��"�Z\,7@��.!f#%�[e,쏦#2�2�)����$��r��F�Ad�Ps(h�ʂf:�X_���6ƪP#dԔi�]��c2����,�a�D����)K5@(ȃA����-A��!B�=��?%_�T��n��C�R�x���	E�U., `FzU��������1@���A�W� ��3P��ܬ�.9X��2!�������vW����s��l"w����6f)k�}���E�և��X�gQ�HJ�QO��=����\�9�gMoӆr#%I�1�4�^�n�ϡ#�������~�R&�(��`<�$dāL�Eͺ��J1�V��7����>��ɪAI-2�'-�GZ��]��5�}z���:�*��p���️�u��=д�+�Y�G�&͊���F!�S�:8i�5;<�@�FI4�?Q�$7@�f������ǝS��Q��@y7g�z�6�/U]�^`����N�ޮ�l�>q�!��h��Z�B�s?D(��J���A�`!P��hP.� �d�#%�Onvx��;���4T,�Yd�iR�i� �"���zι9*����*���5�'��<���!������#%��lCV�,��f�u�!{�*"bcaԐ�HE�{K"��Y2��<p۷}EOY�vh5&�c$!Q8�(��)�:5�����P	[�rH1T�ä�;h�ld�hf�ݵYpp�\Dq#%���l(h=d#2%�Z$�ْR�ʹ�	�HQ����M�6`hL��w=>s�~,���x;5�So	+!�	9�՝q#[��`i���#�D�<d!'�<��{��D,;�Y�su��%��n���+#'�Zu�b�x�Iܞ��Y�{;YQ#%�,j�����Zƭ�u�d��V�m\�&�r���z�%�^M�c���**�0X�^����ef��ț�r�������m%#,�OJj^�4�x�t}د~����r�ԵR͎�<M�;:��D��Ϲ7���q��#2:5��P��ñ�Z�T�x�t3�|�nH����ZM�h����Hb:�d�:�cV#2�r�ï ���u6���r�U�ȥX��ɣ@ǪK��T���$�2�x�IIk�P���(S���Z��O��-��<Jfٛ+�\0nxE��:�ZpA�74(�(cm�����k{����׸ر��{˥]�[�Z���S��Y�w��q��}�vo.�x�HL��w|m����6��!Ւ�<��2�� �2�x�8箇]���1��g4c<�e�7d6�$2��o˗T�_5���=V�7��$�9���Ř�%�yRZQ#j�RKD� c���׷�rԡ�t��u:��cH���)c#%4{8ƒ�G�F��ƛ����H�i� ,�Ј��꣥Y�&�j��ȡ6�A�o.9�;fF[�u�ܱX�a�Rs�'o�:�H�zq�F���Ϛ��������G����Ǒ<}�(�$(*�F1`ԁR\���=yy��U�ҒX��nc/]������e0.�UR�U�Ј�X��`�υ��K?=U�����}O�l^�Wh�FAP�P3�hO'ԩ�WҤ�$C6E�3�87Xd]�#2��m�2c usc��;��_r'����#����f��,�	�;�Ηm0T&�S+���a8G�?64�1r��/xw՛#,y�f���#�_jL�2r"n�2TS��a0�F�/.�d�`J%�6�E@�fT���<���j��#%�3�:h�5Q����VbX�D����ӭB��#,.�r��0�}"�6\q�6���n���$[`P�M��xσ��Fm`r� P!9�P�L>��;��^�Y5ˤ��㑒6N��Ԯ�4H���,	yT)A�s���۸��ל�2��0�n��cy��o4v�;;��t�9�_l�����O�Nj�e<j�Q`x�dom�QU����;�Hs��H�����P�a�e�ɘ�P"�^ӊO#23�/s\�3��'j�o w�>Y�vJC�Jc��j���d�RAɿj��֘�'�=2gBkV.(�;����Kc�Ldq=F8�G((0UE��dQe#2��:�k�.?�i�k������U����m�{����fm4��s��h/l��{�,y��s�����Z桧��oc�0rt3�,4�	�&ۘ:cU:��ٛ�B��(���!y�m�t����6��O���ﵟu��7�&�`�Fkz�f���X�%��_�0��N�:���:!Hi�������M���*�Z�h~ݔ1!�$H�e�:��n������s�����5c�_����<4���d�nU������HP�1���!�|6<Li�(S�K<>B���+9������·�����C�S@��J wE�צ�-QX��"��#,-Ȗ��uوb�ȁu��)`~㶙%���T9�l�����#2�ƀn�x!�=t��+�4�q�#,vg��~W�_#,��x�)ĝۉ'�-��s+���p��ϱ���#2�_#%��q5��)S��L�6�������hQ�r��(�B!�]�7N�$in��OE��k�'Z.a���êB�v�䫨֖���j�eE��n�&�&Scy����6����{�]�6@��4w�3t����%lG��e��$�9��mv x�a;����*Ƚ����m�f����|���<�xT'U+924�C��N��� �@��=�_��Ⱥ�Qz�w�"���@�#2x�þ���~�j��yRę��c��t�v#%6#~�,��2bJ��pZR����l� ��>��?/v|JO٩i����=����L=h#2�AQ;%��∔��#%���#%?/�6��`��Q�g�`���JР��Q4Z�+q�������4̨�;�߯���#%L�#%M�e���.<h��y#%'f1�)Ϋ2j���� �T�������N؃���$�?����p�|�ݢ{:�_�e%A7�~8�-����߷��1gQ7�2P��q�[`]a�o>��D�%�e��	V�� E_����?k#2AQ�#2CD\���#2�O��]���#,���N^;��mYmΉa��c?��#2C~�		I:���u�^�Ǜ����4��3!������I���;z�^xm�Ve�*�����/�������������o��R��M��ұ��YAτTW��ߥ��,(�+��py�ZG~�C�xDB����#%)�vyg�w�Z��izQ�y����}�37G�h����W7�D��}_`H��%Q#2�7���>�='�0G8��ۍ�����i�ޒQ*���@qg��w����q�l�S�e��tׁ��^,Q�/�(2#"�����؍����x߁�����{�3p����RJ��A�>�{@%ʍ@{�Mtܞ�Ѿ��'�25���Yg���~�g���/uD�|B_pt�mWAu��]#�v#,B�54Ҩ1*:��D����ܗ����M�#%����=z7���#2DIg���]����}z�|��#%K�R��dݛ��|I7f����a��{xb��)���޾�mz|�F�&y]<"z$4�,(���;��О���j��:�>�o�g��Ou��R����ǎ�}�6ƀ�`BF S"P�/�l����~�^}~��LLN�윿mwc�:�We��i"�G�tO{�j2i�9������gF�D8��&إ��BE�&�?��ϳ��ƪ�[�Í��N`Pbtj�²�NN�ӳ�]�#,�y�[��D�旄a�4f8�zϧ�X7@j�tg�~�������o����İ�$���+�/�cⵐ����Y�d!#2*�=��x�0�#%��V6�b|Tf#2W�fg��m��Jz��������<�@�^�D+�wh_%}��.�~R}>��!$!g]��������.�?9�3��#���R�#%�zCʹ��3���<�O�AM�\�����GV�(���y�(@���,�{���}�w�~��������=��|nh�g4�V��	�=��3>�q�]�l��2��:'���Y+�i��O����[���D������RH��Q�\��#%�D���#% |5�X���6<D3�^�8����S4T�Oі�x��D@#`~�\�:�#��A���u(�hZ��Q��|=;wi���6'��@�خ������3�D}��)l~o���-%JUA�~5\h�P&���R݌�l�#,�������1�}���n�� ڟ$�m��QR�<��#2�{�Y�(�H�$�+"�O	��H����	#2Y�tc�^��<q����wc�y�o~u����	�p8��m[����sF�����gem[a�#2���3�f��S��u�>E�NB���&jB�p������aW��ey�c��"4�k�Ϗ�Vr�/��wc�#% �a�%<j�=���ש�$���Ϸ�Ny��#,z��>����U�P�Tav8���d3�ͪ�^[64^�S�s�R��Ԏ���y�\����W��k�6�?�x�M�v�0�¨r"�j�zz��C��+�~?��#%�����+]�\4z�F����	X�怞�s_ӻ�_��n�D2���z>����l�/Fz�Y�k�#,��B p���?�9�&��`���^#2#%��|J'��o��<���.O��t9I�C�@>%sϪ�Z>7��RE[k�g��9�nL�W�]��03��{!�뵋���X��5��(Ȩ��f5�tB�Ba�I�Ւ:�s�K=����^}L�r�W��<���*�_����A�FL��>`�j)Fy\􋗇���w�oq���1�Qq;��5U^)�\�ec7�)3��S+�Ph�u��c��j!%����)$y����O����+�ڳ����`̢�KCH�!ѥ�ZkV<�ֽ���z��l�hu��A��_%Sw6�����q&S"*ޙ;�c��oƍ��]*����o}���e;x�@<���G���#,��E�|9�{�Y>�q5�!r�	�܂^�������m7kh�U�[����D�M69�`�Q�k"�zJ�%̠IR�Ty`����,y�FP�L*3(#,��tG�(�+�}����z;�A^[��0M�ǿ�*waF��7�#%��h�}lɤ����Z�89�=�>$f���/���/ǹ�.��M����*�I��^=vr������,��MY|�W�D���ߵ�`횘:2����)pe7idv�ʽ�F�U�Zn�W�V�5�`#,_+��]�	&��$�6ƽS�r��M�:\Y�Hs��dxX-f�|ҎQ�w�vB��ϖ�Pg3�w[̂®�ޝ�w�gFc�'��3�zgm����z�1;�!���_��K�H��Mq޳��:��1��Ҳ���)���R��q�v��j�Ƶ��ņ�v����[40��8J�d�V��N������Du����h�O���o����l�y���!̷����0�M�Ӏ��u�@_v��Ԫ�X�#,�ٟ��G��>E��;��<+��ڞ��TSj�Ԥ��t���ƭ�S�9Q>���ῴ�����Ûӯ�4qON��4�)�D�_��E���<�5�N��7���}uKfs=}�؊z�_C��|h�mseT��J�?d?&���֖u]g��c��Q7n�62jLK�g䉎�˱����u�Cm��zË�8���>S���N��Bt(��N碌΄�e�.�h�EN���t[��Е�=���g6����v����t��x�N͇$�����������9��xIE���J"���L���C�k�LrPG;AC�?��>/9���)k��� ����#2�;9�EMIڱz��+�~��d0z����O��ɢ�;)p����|����&��=Q�ح�9�3f��c,��4S�64k�/��:��"���:t����Ã�t�G���X�M�/�]�S��J|�;�%�m��˯�#2Ϗ�97$�/��)��vs�z΁��<�vÉ[񇚵�xb1�(���n���>�f��"-?k$�Wj�!֍�܍|��ML���)�x��zg嶾t�~;pD��;��+�o���*#2��drm~v�n?��&�5�J�~�?X���vxd�~ԹbQ�k�i�p��VW����˟Cl,��!�hP��|��Ǧd񨟓0w�i��w�s!�<G��b�ܯ��a�N8�5�@���2eH㡙h�' 	��Kw�ݏ��.�t�ȋ��}�|.�����5�����ۏQzm�z1G�?ښ�A#�Dy��-�}f}����B�i�HB8����Ж_�W�.Y�5n�{n��|}��\B��!��[:Q�80���˰�OVdN��n�0�}L��5c2|u�m>ѐ�ޱ�����*5Ի�5hd��!^ ��z�r�;8�m"����[�˦.I�<;h�#2�Q.AQ�����xoZ�MS�QB0���Fpqu&÷��m�gۚ1�9���ߞ�m�H�?@��EӼ�?>��w�Q:)�$�/Ky�i6�+u�kJ�����E�B����Ɖ��P��zŢ۝!���m�����iK��e�Ax�"�d`��($�R}#2yw:De�q Dl�MʨZ D]�*�D�CE���c���cҞVO���z�����cp��UʏU�@��,ZV#�%�(��='��g/l?>ϝ���E8ꦡ���Ѷ��8�n��P�4�=��<�x9MI�B�QI�lV)i6�u��c��^�~�|��׾���vu_Y�>LԞh� ox�}�\٭B�1�1.6� �0  .��hlS"���cR(�?�1Go#2����@LC�Qx�#%r�@��M�v��6|Ni�!O_�P5}��X8>Q�#2���dguAX�|���\iW�����/�fx��Y��p�f(U�:�y���C���4^�5�EE�E�#%�Ltg���z��Y�\?�;_��"�{^�#%qP�:�c��=F�E���X6~��Ha�dk�q@Ow'q���j�	�����s���pȤX�)?i#%��H}�<����7Ԣ����$���/kE��~ڴ��=w3?��E�x����uW�`��]'�$(o��i�G��4�/��+�x��ڱ?�/�p����M ��1R05+�)��;u%�o= '�Ο��M]�C��Z�q��K^�#�p�=Cgb���������v�A�H��GGH`�ӤxE�:�W>pZg(����SW�H�*Q/�G�oʃ�u����DƮaj�b(�U ��!��i�D��+h���@���㟟oOEܨ-c�?����/����#%��N}��� 4��E�8,��\K#2S���������z���7	�Zu۬xd�J{�$FC�S���ċh�;��l�uq�[g�g��i�v� ����ρp�tA��V�#�t���?8N5\���7�M{�σv/3��8�5A��\줝��^�-zc�������̨��C���(H��HMPef1��A��{�W��\���@X��\�%AC�_���5���F���Q�<0��,�̠�/R�(1�,A�ָ_!}���'�|�1nCs2#2�#%�EM�r I#1;�5M9�ˢ��&k)��Eџ;���!�]�?�9#%[	���Ě��P)M�1�@��D�������9]V������_	��4���<��XG��暉+����{���Ke(ֽ#2���0�Q,O��I�=���`᜛����n��?N,��>�9��P��p�M3l����Rw>L�)�p�8���`wc����H}yA@�ǎ9jW$��O����*jW�����Ʌm��y��C����(�*N���#�h���4����yޥ�I��#%�m�h��޵@q��g��6#%�3T�J#��\�U#,>���I�zە�^�n;�� {$Pk���>n:�k�B�E�����9B����Y�� ���<tG��/�i�	�?���H���g�֥||���G�B�J�҉�Ue��*��)(�Z�����O��^�o���1�x\��� b�Z�a�<r?��0��’����7ܣ�%��i8`�O���;������ۘ����W<T�0L��|�м�Wɿ�x��9m�~}[Χ����ݦ�ŕ��YƏ�"4o�m���u��6/��p�����Z�i+	�:������NC���Zck��;��.��`��BW]��z��4+�̧q��$B1�H�(Q���}X�`}R�s��l���f�j5��yv*�ܧ��� 0�gb]�<�8Sw��yD1�-#,�@f�B���)H���n���۝��ߺ){؆����}i��≙6��{-�KsǕw��\'�q����F�nd�n<�i���Y��1��o0i���xt��/����44!	4�ߪ#����C�f�E���}.�ȵu�`�[Yڞ�Z��`vi�A�2�<�ɨ�Z]&r���[=�}s�U���]���i��[�a\ӈ�?��z4�{0%)��������#)LR�U�fzgt��1����qZK	��_���%����I��	WD�w�:Y}�����L��uDu�h{��I���l��WX��#%�Z	k�1{,3V�#���#2���`��-���L��7�yP���t@��Qר��l�\��|�=C��}�9�&K��}��DJ)6�}�p݌,)@%XMv���^��Y5?v�Na�|�F��a��+�F��{�d��~6�`�[�,�R�2�j�P+ik�Q���V^�s���>�����~�nZ�>i?'�k|�9��E#,8���v�'Hn�s�����֝�&���S<�xt�m̏�j�\B-�B�s���:��?	cS=�S��w�N���q��Շ�zv��~�6�����X�)�#����Z��e����}�#2�tDZ#,��WCl�S�W���g =0���+�A7�)�������o�RZ�3��#%�`���]��!hi������^�E�T]r�p�#��}:z����9@�Խ͠{��@+���i(s�#Fn�4��<՟�V�*� ��)�ifK�^�w'�ͪ�RJ���*�a�!5�����`�Y��x�,KQDJ0#2�y��	�#�785�aڏ$�P�I�e�#%�-�O'W�f���ۗE��B*��o��p�_���[�5Q��A���w�y�����- 2�TQ4�U��.�$���a��� ����L�rd���']�"��tځ׼&��d0�JDp㭼^9e!$82�#,f����4�Y��{lA�2a��j:�;%㖣�C��Wv�7g���G�0��`�AS0�;{�UR&��nF��YK�p��8���k#,�h�����lz]�}�B��x��k$��y����`lA���d�:�p�l��#,&s\]�S��x�h�մx������3� �� 9�<��9�Œ�:1��#=R��v�w^��_��1�m3�=;�K�x�9���%d��j%A���LS#%��dTL��P/"r�=�)���zL��Gv�'�t|5����m'^֩qXfB�P�ҡ�Vfnޡ�%21m��.ȶ�6�qv�I�|�_��2G�OJ�;S��}�6�f��g��'\��t8F�i��Ac:#�d�hɪ"�5e��8��:�"��55�:��ӿ�NN���ܻW$�r����|\�a��"}�����Rvm�O�W_|C_��x�dK}V�c*�c�B����y-Ų��I�ˡ��ꊞ9��;�=o��7/Ԩ�u�4��Z^���x%�����E��Db��=�"��fW�h�efKՠm!��U,"8^�.�5����-� �p���dE��ն+�L�Ǻ��v�xu��*	#,��+{X� �H���"����A=ݣ��u!���`BP��F����X�{���>�����u���V=�QE��Ns��V�-h�#,D@|�i�A������B�"��"S'Eg7��ё�m�xhh�Nf�Cc��#,h@��/��6N�j��r"V˩��|�ص�ۖް���"::�b6ů}����(���_9�\�3V��Z���辴�+A��u#,����a���oR-�uH7o�d���YVL��ٲ��mw:�h2Q���x��=�(D��+y�puK�D��!v#+�6RV�#,��'I@��m#%�9��GN�cnb�Ki�H=�b#%�n�A)��إkNv�yÅ��N`���&�8y��I(����	��,[�t��!�߭'ܫ� �d<��֑���D��-Jw���l��"������hd�:\4�nE�э�'ɹg� ^x�$Ƹ�bR�p���ԎG�5���2�x�꺉�pQ~�pw�#�^�iP�M�h���YAlD�X�,;^���>O*/o���Ɯ�#2Ej�#,p�C	��<)Mg��p�xE�Ú�f�ب�#%<*&���A@n~~~��<8�,�[ l#2ȷ�"{�vʊ�Sǯ��ڼ.Z�Jj��|?��[�]Mt�o���K���i>�Ǣr��.`	M���ճ�����=ߓ@������~���#%�(�� �'�-���>VJتi�x�I#22���}\#21�P�Dt�ݔ(�8�'��ET�#,�����Aw�5-�Z���O��V��9�f���#%|'۹yyB�#,՝�N'�e:�͟���_��޾\߀���y��=�e�?�o��?D-#,යY��Mf��ԉ�)Ǐ��#2$ר6l,��×�������������Ǘ� ����pl�U;#2�8�DA��!#2�⇱}��#%�3���@���� O�~�(R��,���	z�rJ��y$T�I���S���%Բ�w��W�?����xv#bQ`���(�X��+B`vj����Kyg�������v�v��������������ގc�˟b0���x��A3Caڗ �:�]۸�xn4����rk���8�*ɟ�Lc�T%x��)F#2��eف-uTy�|�;��`x��G�{�ڝ�����_H������}�q��j�G��GlV�_��RȾ!��"v	�,���/r�����i���i�m�.��#%r5�5#,rN���lnf���/1փ��"	��������]M�����	~����U�����_9�Y�B���o@0	|J���q�rI�L�+������"8��(#%�YB�����p����?����r��kmd#,���P�6}|ڇ�T�` 3�����n����$	A�T�����%��y��bƵ%$��?�o!|��e�1����a�<B�#,������\�6M���h!f	K���0�e#w��#%���Hm5����E8���0i�-Eb��#%ͤ16Z��'�P8nʐ��/��� ���φ�*�ܴ=����A����{���t�m�	�h��M#,���%�1������;���6EA��#,�1u�D�BA��À��{�\k�iJ0!d���͐��.d'%{�#,�c���b��6�V9'T��+a(-��7���$�I�W���#������o��e�HՄ�<��!���M�H�����61L��r���p>9 O�#%@#2��]k"M~�ڎw�겿�ߚ���l�vFl}&�??���R���Fv�7aב��`o��f$=#У#����'#2�0E�#,%A�r��J"�kmb���!p���+$�~Y�yv�#’��w��@{%W��SQ_���[vQǪ|��<�ɑ�:0�Y��������k��uA,���;�q�6=�&@Sj[�Dy�>��Y:�Z�� "1,�N�RQ�fK�#2�#,��d���x����"#,?�#2�[p�����4�*	*�D�	u�s�mos�!֦�t���e�S�E�͕�&됑��x���6�4���[y���B�}!(�<r�]**�e�9�UU5��>Ri��c�#%����:��?�{�������#,�2C!8:�Z7;�3e#,�s�gL�ؖm���,]�)��o�3���г��W��ue�G���ש����r;T��#2,���mX�տ�\����6˯���^�G�F1�}wUz�#,���I2p~�@�ߨ<� �20��>_��t�� b{��Bm#2gSS�a��،����0U���k���.�h:��Pd03�f�E}�>��J�R��11���sYe�sC��>�QË��7����lh4~��6��D�����Q���B!���!5�>��O���hl�_����A����֦�r}�sA�����##,�˜���+B�ð2@�@u<w��#%j#2'��=�:_}��JT�����󊼋�&B�x	.���t)��cP�� �)#���3S9�335"�`�����+�#,Mc,�,}�*����g����$�ᛨ���B员�s�i �:CC<���Al#,SA#,���	��#%j'�?����ğς�X��@9@�W��!Uڵ��W����c+��p�]=z�I�)2�۶I���`���Xj���\�nwd���nc)�%u���5�z֡S�l�H��O��m#,S���,��)�f�u�I&j�Mb�2�SRZZ�i�j欵��ޙY��u�.���aG��ך�j�45�覙�]a��1Վ�A��PJL���g~�t�F���mE�}mm�_�>;^V�r0O��L����MW%�?ӣ�ɺUb�3w��{��������ҍH	�;B��+�j�O���WH�g�]�JK�k�][�C��ڟb>�N4��BC�!��Ж�`n�M�5t��F�i;��v��v���.�2pD�v"���Jw�["t*�Ֆk	" �-��G�L���{q��ln;��j�8��V؍$I)���2��2�(��<z�MU���5��_.z�̿��19l=1IAJ~��u:����/Cߒ�D�oY���|���t应�۹7�I$I2@��~Z��nԦ�E.50 j�m����8���,��>����ю���dc_dD�v�����~��Q�������h$���	��nG��M��@#bHS>��ө��d���*�%)H�)�#,�M�#%��L�D�qf#2�#%^�֖T/%(4��*&G��mϓ\CsJ��h������'�����,B��7C�LR����Y���N��7ͽ�Al�%݃#,p�C���6�9�f��D�B?aqg鳆8}t9�#% O�=~PY6���y	\�x]��[p$ ��|�a2�'��I����a-�z�RϢ��*%��Q<�r0}�,�Q=}k���Or;@q����z��Ya^�f ����SA��\�;_x}�s��XƜ������;�CeS�]�`�~p=�͞	�����=❤T���;�����$�d�k�<�H"�N���w�a��рlz=F���+Pg#%s��Jm%O�m�����ootC�X,�HE�b�}��M~AgZ��t�w�'�Ƞg��������7;���Z�>`t����7�;8��������/�r��B�c��}�}�_��`��\�ε}���ZP�@�Aɲ|�"n�#�pWo}�h���!��\`)��U��.*�c�} ���P�X��t���#%�|�J��"�}}��dvj5s�B��r�%~��	ͫ�hj�ӕ�ȅ�̽��1�C"�lҤ.O#,�@�/�׽���r���T���j ���0�1��Ǹ���S$��<xuXC�s�8郋��,Xz�Ϙ��8�S���GT��v�^�x<��>�%Y�U��ң�%�� �?\�mUM(�8lk#2���~Z�٤�Β�tj>?%0�15Q�$��T��uz����2цb�X�#mh�7��;ޢ�&���֛:rs"��U�?���3�AdV@�u�iNIZϿ����T�(�/��w���oAv(�T�߄����{����։�4�4�7�=�;w�Y|�{�������Kh��)�Sj�E�x�����ﺿF^���|��8�Xq{��E��%�����3#%�"hrO�*(�(W��#,��o#,,A��Y�i�b��mJ���j�f�����?Ծo��'�>�<�09�⁚S�^����J�d�[��UVԑ�*�#2?�L���w���!��(T��C���x۰�����#,�n��$cU HD�@b>jx�#�/ɒ.a.pX֨�W���(��N����z��6�0ҿO;�ɶƟ~r����F>z����c��=�)J�#2G���fg�+@����n8&YBt�o#,����~ͽ6��q$�K^�cEZ��:F?�h��Xf���0ޢ޴�q���s+P#%m$�uT-�#,C���#,T�`H���f�T�7dShɈ"�2\.�%� ��E�F*A�J*�"9����ϒ#2#%H:&�!��k�;�������%�X����S:���A5��:�@@�H;I"�Wچ�����M��zu%����v#AfR!����^��S������FiV}��3�������oS����S��#,��F�L�#7˼��(�*�+����#,�	�+-����J�(��Z�,P��)����|?N���3M�����A�};�`%��:{�� ~�@%�I�"�s}~o4a�ؑ�4��a���M���i��B�K F#"0�P��%�8T�C�!�tR��}(⥅���R���;+Ó�xBJ<�:/;3���[��i^C�#2@գw�ܟ�}�RN5�7��n:P�����Q�@��m(����ɤ���z3��;m��m�9��"�2@���B�h0�(�=���vv����QY���縒'�7KK��((��骰S�#%�<lBO2J�Pvy��S��}wO�?¢B�M����~M�{*T?�	!��6}�ЫKL�oL�a���0��_�qd�d�G���|����˳Z��A�u�e�/	!E�S�7�>|h�>�	�#�G<�:�#�Y9!|��j�<�#,���eBV�G�#2�o����*KH��ٷZ<���C$"4�����%,~�(�	!�I�C��0�����@�t�$$xˍ)�B0���o%h��þ Ȭ�b����z��W�@����١��gq#���#,g�Uq�|���#,רK!������,���B��{OVg�0vb��(�! 9)Uh�<�x�p��O�œ��o���"���;T�%`1Ec�2 9��&K�p��q'P�&1\�e �E �*�)p�H}N4���_0���ëKe��%��ZE)`�\\���`��fn�X�A��@����#,s�Ӗ��f�y�#%��z���<�!R����Y.	S#2	���=�,���^�=cاXu�`pz�m�S��������d��S�9YRx`�d9`1N�#%����]DPI(3B�����Zw|��o%7y�}|�S�ުM�Of � #2�� M=X�o���%�,'	�;1`���+$^Dy�ϴ��|*Ȝ� ��V�t�� �b�^�ݤ�lI���LF$M��(�/]z��ps�k�v?��?�T�t�#l�1绸UgP=`��*�I�d�Q]�TZS�R���l��/�p� ����R������������V���=��Wy������ȝ�),�I�U��k!��Lβ@p�(;��Yt�b'TVA�p���괂T<-�B{>̮��e����9 �p]�-���h��z����EM`�x'3{q�b#6�$�!	l	#�F��Kq>P���y�ww�'RznA���� �Y�TKH�s��'3�۰�5#�J	B;����}{r�TrJO0��B��u��S(7�b���F#2Ґw��I�୾�kd#2)r��}�����y2#%~�}ݞ�?�ii���2B�5���-���Ze���������#,R��&7�o���h��Jp$�+�_�G��B�N������1q�?������Oʀ���V�4f?���`���W����-Š[� ��N�wB��B8Tr��K\H��yF��#%]H+.��jР��4Ù����2#,��a��:B�l���~e��gY�b	p,��T����w�*�oF`>�ʆ�?�+&|"H��ȏ��{ì�/rm^I��ܙw����L���6#,~gY���VmA�����^��z�]�*��	�/�̯E�gت�$��dO�¼���;���-�M�B���`�4�vX,�d�"�[4��G#%ra�hh�����=�Y���<��Y#%#2����6���yۨx��[i�/�h�!���[w����u�7�]��m�B2΋N;���b�\��lDi�د�����~��R�(CX{��7���^�B��VƚK]����E{�Z���%���a�ݨ���s$��f����{��Os]V��oC秶��34�@]>id��N��>�����#%k�a5/��g��<	�6��8��_~¡!&�$�t�p!�����E/o��GSq�:-������DŽ��c�k���*���&ˑ�~��U�A��?q�,Z�t��v�=����X�#,�"�C4N�6��J�alU6�	d��c.��@Md�[���9���݋��|�*��B�zN$D~aq��Mb��<߭�(j��G<��#2k΀�Q�ڎ�����|�Ӎ���R�����<|?�6�?f�O� ��o��5�>����9@W=K�!݄�?#ڋs�˷�Q�^p���G�SY������#%���O���k�J��&��8V����7�	Z���I��x��*1�B�O����P�@Y#%"X �,']Y#,YRܠ:���?l:�����b.�wU�$pG��>�~K���MXkB"i^[]��ҵ#,|�I-���\���9��.�"A�xm���+0؞�8=3L�b<�DA��7�#%�J����._8������_�"�����#,9��e	���6�Ň�h$��\���:�l�R��n�F�^'yK�����6�����&i��jO#�/hq9"�T"�#2+�Aᩅ����q�������?��f�jB�f~��*B��c�aj1���[������@U���Rc'���W&]k�	�g����f�P����h#{�[`;.�n@?��B��;HSz8��,�%:������?���ٛ $AfW�Xl^���t��g�l;OZ��X�$��|�J��d��Ӯr�X/�i�vg6��o��w��[�F/��Z�q�|�A�Ih�[H�N53]���!�cB��|s�V������`��O�����l����J�.#%M	Ī-����m�*��������@�vG���D#��5��c��N?_B���O��a������kEQ����`n�(@��f���*��>�>V~�� �#%@#,c�)��(v�c���2�!$���߮b^��U��a�;qg�r����C��QfF[�����@����/=?m����}�c�O�!�9�0O��ӫQ�#�w�2��I��?�v`�#2t�q#%��s[���&��,�.]�{�י6ɾ�#%d��*6<}����8��6�5�{Ȯ[#,��_�c7Y�$���l�j|���j1O�׍yG����h����2Ysxl"��Χlł�;8�\��#2o��K��^#,�l�9<)d��E��ڥ��TM�0�#%�A�cA�e�ǁ�=��)�1V6D=�)=�b.�w�N��5�LUl(?�w��B�<9��@���Q�To�����Q��T�th��gc�Hm�Q�O�Q#%r�rz��p !�|��ͱK��U#2���3 ���@�Ƈ{�o����9����zeڊp��7>H��h����L#2r6_����u]C8����(M��T*���>�~u��Һ�9�͈Y t����V	�q���`1��:`��o,0���>Ү*(��X(�>��G��X2h۔lՖ۷�F���Q���PAʽ7Uos��c(�|��~�����[T?��1�	=!dy��E7O�x��D���7�Q����D������J�9��W6W�^!#%me~W�9��E��0{}#,%{�U:V^��B4���:���Mս�;O	KM]~r�G7�j�PƱ/k��;tN��~g����e��10(7Vl��-*���5��r���J������y�ى7�ԝg#���������ԱBt:ȲX�e��TI:ճ�멜F#2��vg#,t<�%��#%�ҏ~�3�0h\�B@3��:-0��W��</�f��o5-{;u��Q�Iqvs�ÂG�f�?r������n8�x�����7	�tw7v�b{ �"L�L�2�6e��C��*�>#,��ރ���’��*f���WM#�h�y'-zjn꽕�m�)�Q�0Gy�-���m�PE!���*ж�~��+���봘[���@"@"��y>1�~izr���#Qf[;I�Z�2�d�9��\"�����D>i9�����D����'���7�Pu�}V3I��I��H�tO��������=�7���s��P��Y�0����N�����>k<�ó���-x��5UX��08�.�P�5{^,���F������1u<_����U<�� y���bi}{��ن��i�XO�5�(��Պ1���ޠ��NjП��Wl)oz����;".����v���m���?���=u��ը�]�����G������{�Jl�.Wz�f�>�OBb!3�:�+��Wl/p��D#2�5�~��G�dt�g��p�1׻�`�æ=�)���~�!��ǝo�q+#,��I�����Ƚ��1أ�I�P�� B5���\��a�лv�L�d��d^��e�ys��1�z<����;%���L̄����$T��<ύ�rt7�>xX�E|�t�ɴK˷�E�SC����G��Nެ��98�0�R!Ny�٫(�F�z	*���(�F�z��Z2U"�6�3��nq���蘫�o�!�b֙&���`��9G�$d#�B"�!�窧�{#%�1G2�w�d@�O�����>O����ϯ�����!hR��w�8_����v�4�����*���������49��#%�^wB�}�u�iDL�AĵI�v}��������|���<SXi�K�����oMUU��OS�`�&c#,�q@tٷ8@�v���m��M���;t�#2.���Di�$�H���蜡�W'P���6<Jj�F�ث��L��uͤ#%�6ף�u���񇜆Ol���:�!7-�ﰺ��K5��q��қr#2����'��x#%xá��y��#,1����#,(�Ȓ����L�M�=�c#2fbK����4�0����kn�cr7,%��rg���^ӧ'P.�k-������	Bs<�o�J���w��sC@,,���h��e�;�.>����'��Q��k��|e�k���FD7r�#ʞiU�P�h�\#,�l�0����_�g�)T"j�H�:�.��L0a��a��5� �X���@��(���"�p����=�fѥw�cvq��q3X��E�6��;���ֽ�ݦtH#�b����:�ګ%@�;����M{�����>g��l|JŐ}��v���#2u��ɬ�������ܟ������C����ު�3�gv�u#%iĨb����M��B��H�ѳ��Z�ƣm•�6ɖ�Q�A����\eŽ���A��!#%�J��!�U/&E�������fh6��7������:o:#����t�D���(}�RO��C�j�۳m��C����<���	ݱ�����o{X���B���#��@���.݌��U���n�����Y��*Ip5��ԧ"�1�V��C���"`�Õ���U��m��R�.���'�I�r�i#2���c|�%A��I��Z8#%�hc�q԰�xF$�h�ݐ`8��FE�T�����4ƃi�4TRϰ�4p� Ǐ������q���,�"^#%35��#,�n1ɰ�`��0�- hI��b�$�gn����.���v�)2>��wn�s�]��:#,o�oO��+�ª��M�CAM�wY2!���vR�CQ�s���fRPm^�e'k�}�w����b�N:�#q�^+ڽ�:�O$<<D/S�����L%��N����0���0;���&h�7Z�u�o*S�,�-������!�u�	�/9�)�ĝ��ms3X��Ba�m�H|M�4"qr���KM���7C��'w�<�Q'�ow o�ǃ��Mjf[,��X��W�A�Y���, �Dd�6k�R#G����f�@��n�|���_w�ݨϫhp,�g`6z���a��#%	(9���p�o������HC}�XDD�2D;O�����ۮ���&)>�Y��9����QP^^"S�bm�Gѻ��r1�^��W#%�?��0�u��&sZw�,A"����#,�!�.N=���Ȟ�>#%����sэ`���#2Mw���	��g6Ӌd�hv��c#2�8��(�B���^»bhlw����,I�M��k�	@i#�vŏK�F�2}��3c#2L7{I��#,�!ea���Jd���@GCԫ1��<��o~ŢTB�#,�^�6���'��=Q�>g��w�M�A���8m'��&e�kNW�@Y�N�Q#%ÑAR��ῂ����]�^0�Z��� mE��[�n�JQ78fM���`���M��%��ù.���a���y"��w'����i8YΠw�͍#,91)77,x�p�6dYӻ��Գ��;5�f|���iQV�R@�����|+	c�¬����7iw�F^�4B,s���	�2]�چ�(lwHAd��T�87�IC9y�e�EbJB�vo.S�d{N��ccL9TjEn$���2<I��M��|���N�k)�i	Q��­T�J�(�3ה9h��\�@ �+��53�!��ĩ�����̱�cYVe��J��3�K�궵��#2@��]q��T�\���F(,�X0zH��W��R��Z~�-�MY^l�nl#%��!�x����Ź���F���V#�t��2�FU8�RT�K�=k9��p�.�D晝y�]�!��6LϕP(�yf��0�53�r�әZ�|�Z��q��ݚ���	����"�z��۷2P�A�'gϸR]�,�(IuK,Z�&Kb�Ҽv>�E��e�鑫<ܭHԢ�#Pb�,��%�/�4�kfsi�N$|qc��|�s<ꩱZ�L�]]x==a��rHv��4R��-m�`������B�s�'QQV�#2�!��Ԫm�<"����}28`�������^z�IA��#s���"���TP�s3#2p�s��7��������Uq���˯<�O�xm��E#%�����������-{u���i�č��v,�y0��h�Ba����n���#,��JB@G/��o�Jl�tkRkh��$&@�h���6ǖ\�X���6ָi�|#2D��nZC��(�/C�!�ə��ƪ������Bp����LBq6��<_�P„,���#%9�y�k#2\!)�6��@�0%&d�����(���T�]�>#2`H��A�����b<B�#,#,�E�F<#%�%���E�	�38a���Cq�t�#��#kkϲ#,���&6�E�F�#,Y��)t���z1�M)1�Z�TJ7%@�wӉ�$�gg����&�,��i�ȳ��X{O����9�$��o#,!���D�Cs#,���5�)a��x�T�P�sC� �C<"�m4�I#,�qɁ�p�#,f�M�QC��䏘��C2D�*M&i��(���xi1�9��֯P׹��Hͻ[�ˆ�39��5�����&�VsC�#,TA�k�);�5^��-����ܾ��7+�,A��d`���f���F!��\y�L��8�1Y�3U�vG��\�k���ku�r5��y����c�gGgr5��Hl^��R�eɺ��N��p�<]�r(E��4��y�F�Tb��I|�`���˦9��`���$��1���s�u'����6�1UEn��>�.����*&ͩ��5%�W�p�Փ�y�?#,\����i#,C���	n�E���seY$�L�#,���(#2	?wZ7d}����m�k�2K��)��W��*e�f[C4���3R�ˍ��mS�2��bѱ����Ô�9�E�>��l�J����ZD���x�2|a����Ӫ�2?�b2,ó�|W�ǫ��pedt�t��_��rBn�oofz�y�AJ�R~��M�d���bѢa�� #,��6C����>(Q6��o!�UJJ�P�#2!`ʑ�>�kӊyw�+�#2G~�0s���z�Ї�~ɖa���N+QY-ܻƔA#%h���� M���mj~Z���R�fl�Fu��l���?7���%P�� Cî��E��i�����iJMR�d�)��PHB?�Ai#	y	O#,�A(��("�<|�MW��U�n7��M~�˽�\�bج�R�x�]i��T��PK3^����А�{#%��I		)kخ3�%v����rA�T#2�j-"���#%���N#,���V�;��|�V_�U�;�$#�Y�z���IOH��5�����3.�D� ��h�@9����B"@��|�\�����*X4GZ�#,ʛá�x�{i#,�`E! �@�f�}At̬el�[�4h��xt����\fwV.�2�4�ԩ�#,ʁ�H��H]�I�X3�鄍�����"�#,}��yJ�ҏf�]��v�S�@�N]T_㘬;��������;<��X�H$���3�%�_��\$͕>*8#%N�Ġ��p5oMw��� ��#2�>{W��\�FG~�`6竖��?�E�]Y�"�`�@�M�S'��+�Ҭm\�U-%�J�mo`d;��;`��؈��� "�"(�#%Ȁ��q~a�������p��=N2Q�aB6��E�����Ī�������0�"�p�v�D4-^Y��W��2�ɚ��k�R�L[�ݼzm��M�nk�(�ݠ����-��y��.n���wW7,��ݣ�_.�j��K@�$R������Heg�_D� �&�#,um�+�v�78#%Ot����6̱��Xu�����c������s�̝�i\���';�sPq�B�>��r=��^��3�z��{�b�_��$||��_7�Mt��&�Gˮ_��WN��ٍ�G[�s>aP��+����ҭt��l�-;�@����U*V��cO�Y�M3���}28���g�����r݀	�����U8����_�K�GW��.#W�%٠p.@�f��Ġ��Sy�d�A��Y�JP��n�M�#2iaIq���b�bD2끰v��-����+U����b�x0S�v���M�w�ⷔ�M��HMޏ3]���~_(��,6�5�8*���`�w��BK�/x]�gf�I	g�sC��E�W�<7�߫�^�����s4ꗫR�5m�&������ĩ�gB˝���\s��U����rLK۹�f���Q(�:�TOa�A_��̢�R�QI�������h��Q֢lOU&�^ޓ��U�H�4#,h���afjVD$}*���e+�Rt���I"n,ד��"�#,��h ]O��ͥ����3���Y�Y��]QWP�@���徶���/l!AK#)�Q�-�<���%HR����'֊���h-�J�[%�V4�eTb�YYmX�m��J�֒��ʍ6f#%$H��,����??W5Ĵ����d����7���9D*��2=~�>�L	��@��u���3�r�}�n��`M���nd(`<46:��#,C#�@oB>�C`*�"�����`��e:d�gZ�(�}բ?LR*��D3�'r�hd��H�t��M�#,%��hkI��/�ҲfI��s�r�w���*(�w*R�Z(�x�՘N{�up�&�ݨ$[j]8l�J�*ʽ�m�s��<��*#,YA�*F#%	R��Du��LHT H�p�zg��"�A��2N�!HCZ��͹�W5�L�R�QT���[HSQE'ٙ���h!���&��8@�#% HAdA�N�Uԣ���>}��z���ŹSM�20��w�@3 ����y�w�v) ��#%�H�}!C���C����/��~����O��U8>s��O�`,���;<x�,SP#T%��D#%-$�:����A��VD|�m�}�iӧ+.���B�P�P�?�(��$&ϷM.��[?��>Te4g\dKA~�S�mz��-V��D�)N���N\�f���ē�R+���A#,�Zb����i�1픉�;+.����:�u��@�>���CU8/��G�j{�IS�I�fQ��T�����zI�k�l�(2�h�5��M�O4�>]gO*;B�q@l�i8"lHf�I�BP�Md��G����~�i�v$���S��}������_�w����(w�~��7�M��G�U+�m����~���am�0~�%#��i�S���X����*�@���MA K��Pg4@��C�>>�#,�{�����5:�"�u!��v�#,�y�#2Q6ٔ�ҙ����c�L(�g���c'v��d��:Ӎ1��=c��Q©ƿǛ����mt��I[�A6X�k��*#2�.���XRka\��rnjh�X#%�FOqIQP���yQ�#%�ϼE�4>��6u�9�b����$!f9�?L��!A�)���ҍDAA�#2���Wޫ��8�l}�wv��(��HB'OO�h��P�+�4	׷�|gg�.|��3�������żԗ�tc\����8xȊ~_������р|:��)Ub�Y��@Ӑ8�,�������j�W�@�������ɻ���ڡ�A�C�*�n��⮴�,��ش^�r��2T��.W	��.	�J{V�=ne�^s�w7��D���y+�����B�[k�zD��1�?�M��}�wL(��*�Gw����t�]�N�u���Üq���1в�f��[d�F%�;p�g���]��zl]�؈��y�EE0�7�~6ٮ2.H����#2���7yl�s��y6��m\9�7�`�WpS�c��Ʀ���S���PV;V��E�#�Ö�#,jw��h�R	{(�Z"����^��[57K��l��0(�4|>��u����X���1�C\����^��c�7>����Š��z�����)=t&~a�|�N�*{L0#%BV�%Q�D���R�/��x����ӣ�Z����ұ�W�<��'�=��z&��+��"x�G^�}�56#2�zJ��#2Y�"����Ϝ0b�7�P�����F��#cˣ�8����k��f��\���˾���!~��7zx�9d$#,gx�U�j�6/]f_��wѸ�۫u�oh���ؖ$�G5�n����;Zл�\n�#,�+�p@8i��}H@�m1���l�pnX���{(ͦ��Na}"�C�Pd��^DZ��,AF�����$L�9�4��O��~+"0F;4�ZU7T'�����p1�=h�)G�#,�L�Aa�1�z�&��t�ר�wN�:cn��SQ1�0U���KH�Gm��N�B���;�1��oG��1,�.Ž�Ϻ&�\��I��G�q�'��է���|8���h��(r��}�N�T{榤m���"<�$I�����IS�;�	)=Y�����F��0��&�aŐ?�׳h�FE5}\2�u�^��H/�u���ݓZ�(�~�����	�[>#,D�p����:������%����N��l�\�*�Kk���廚dar�Q��V8�`�IM�%.ӗsw2#��l�5�#,��� 6��V GF��#,�-#,Mb���2�m�_�;����ģc#2l�ؘҳ���i����3ζ�g�W�ܟ���R��R�ATm%�U��2k6߆�𫮓�c���#%* �1�A|C�y$	&���!���{��خ�}yl)i�AaL�v� �%�y�ё���q����S�P��#2f�D㪵m�a�Ԣ���:a]���%�۬�e~�V���za���n5��V:���M5q�ym� ���L�������]<3�wZ5\�W�KD"D�H�#,F�$n:��B#2RD(4-*,)E�a�I�[E3#%���>����0B�^��_\�ƃn�Xڊѫ�X�DR`l�I֘�"b��[�z뀼���ם|�[T�M�5������x�$�&��(��`S'\DPij�M���D�-n�D�|�iK�6���ͽ�b)"D�ݎ!\57��������-fvc)��m���C!DgrB4� �'���#|�utF����b�������f���3~#,:�1�*�!s�����;����DB���͐�T{����B��O���b�'����F̆���H�z�B$Y��:1���WI\�b���w�����5���� >Bq��}9?���Ns��zk3լ;�~��{��'@�/K�ׁ��t) �"v�j7��[�W�%��xE��r�\�\�(�թ��q>�i ����t�3������3��v�,#,gb��N�&RI6/�>η�5�Z�Ȁ�0�쀂�᠄�]�e���46�ԫuA��_�J@�"����h]�,,�:!�x7	f�j2B��+N��� (�� �H���\��gÃ>4Dg��1 ��$pٖ�z��!PU�4����AM`�`���u�˱�ʒ#2Q���2B7��Eu0��D�y�Z�'�[x3#,Bg	�c$)i/� �h!�qJb`b(�j!��[|����yu��%ԥ�-�_�9��<v�#%�4�p?dH��6���q86��;��Q���"�������4uh�m>|����of����B<;�:����>b.K#"�����R��C��{˙w�r1]�g��q>�9#%��'8\KX6Uo������$�dXÕpͯw����G�.K���np셇.�q�]�WY"�\���8�X��,��g�B&I�E�U#,���?Ȑ1P=J�R5��y�(�:�Kd<���*Y:�I�0�h�#%o�싻����Y}<��	� π,�`LQ�L�x)�`�jn��'��Qj#�%���N�^AиT�,�'�JU��P��\�T����b�LcC@!��V%�J�1bN~�"(��SW�;�H�@4�L]qB$w�Ύ}!��W�EI��6b���;Sk�b�ZFt$#lh�я��0��i��G�����b�6���Pʳ����kA�!I�x�#%�O���BB33	���e�!7u%q֪�|3:�3��cC}Χ#,��#ξ��ml6�Qǧ,��2K�@�ߓh�b�D�B�Ř���<0�9#%�;�����OU>4L�B�h�W���(���$1��������,d�U����ly#9#2����^�F=����R(��C���8�p����鞍m�i��pMy�-A����؈@���	�B�X��l�HALy�Jj6��X�#2b*#%Ƒ��x�l��FS��#,cot�,{)ٍ�0X���7#k�ͅt�W&�ZI�?��k��q��xK5jH^�g�&�K�b&�T�"�ĉ1e�4�f�nH޽.��\y'��	���3G\m�-u�vG;		S����b,mg�?l�:���ed�Ƭ�dR����Lھk[�v�)��r�[(��!�@�c�j��\U7�.J�Q�j�GR��O�|�ph��q�#2�\�ȮQ3%�9��#,�̦�HV���j4(��m0�$�Q	�L	6l�11��B����5�ir�������d�'D%TR��a-&D)�i4�JZ���#,Kbȃ�Cv��V��3+wF���d�.۹���9�ML��5#���#|���[�A����u��_k�aߏ#���)��ԅ���9]	i]d�!r��l���0sA(j\8$~�@6��e�f�C#2��ݝ[�cqj6�fdQr2�)Q"�E5	v��!���v‘��o�#2Z�>v���h�ca7�&s:���2�s=�3�2���6�z�dMuS�\���bR1��+n[���f]��6����k�>)4+.b�$������e��6�᩟/'��q�َ�~d�sO�ٿM�K�sj���w@�2�#��ٜ�Ho���d�X���7@�NC��r[=d��q�N�,���l#%S��q����'$}#2ר�v4P���t�#2 >A�X��Z#%�c>�m) �,,�57���#%�K�iQмMW�#��h�&�#2�M#2�^]0T������D#%�P$��,d5fh#.�b@�)@�`�"!�9�`M�S%#,��7���&&��Y�T�&�Tﰪu�,�o�������٬?�tg�[j����M�9��j�7����=�a�H��IL�����{�����%\��F�iT�S+֦����a=p�@��Ӳ�x�<��+_��IJ����<[q�Z6�׊�\ڶƵ�ڹ���Ū��t���m���g����_��#2)��:I�m�z��L�p�L�}:��0݃��g�'��4�־���IA)�2��i�d������f��;�0���TM5(d���(�,k߷(d֓ID�V�#2d��3$fTPĥC��#i,��LRJK(a�	��QiQ��&S�4c&J��*BeA�����Tf �A�m1�% ��4��S�&�g���e/�!#,�m�`�����U}Lavc_�2#���8�vp�Q�Tr}�+��gX&���d�x.��q�S(h�����j\	�0���]N���ލI��(=K�6�	��M�K�6�x��Y�R��ؗnk��c{8�h_���&�7<��m��$��7�%�Bs-�g�ڒq���v׻#�؛l1�#*��*Bk`{��־�����,Lcf�dl�J�E�m2���,<�gLJN��#,��o*ŀ���(=v����ϼ�'*��s�0��,�1IL�#�1!�#,��W>��/�W#,������$0'q�G�����zz��"'���s�Ff.%Q��k�Ƨ�i(6k/��r�;�>�/Sr�%���܏��P����c=�J��F�Hb ؕ$I#%�ڙ1�����H�fQ�v�~})��|f��OH�:̢Q��O��lc��J��w�nk�w��<���;Y���Ph��#!�kI����U$��}<�ὧ�e{H����*t*.#2mf�9��t(G�|�Cll����t��9�#Xc~M��;t��>ɇ<G����p�$��,nm_&�ɂ��2������~W�c.[�"^7L��<1YC�u-�4�'�ѯ	thcd��g�� ����OS��k��ÙxIJ��q�fi<��4�#,C�q���:�6����Ui���Wu�T(@1�k��3�"�T���x[nfe��RD؏7��@��#2'������^��svw�#%�l���9n����}z�Bz���o��W��`�q��>߮�����i:�$3��;�N#2�����v�>ޯ�[~�Y~��#,�~a�+O��b6%�'s�~rz4��Ot7WqK��s���g&����8�ZX{SaǓ8��m�*�ԩ+鰱�b�D�tu��e	g>Z�2�3Ru��`�dxL��Q�\���I2�����,"@�C�\#%kX>��#2t�C���;>h���U����J��[*�.�T�+�›��-�f�\Zb�S92j�XR�W#22rE�N#,�k0m3��f���1csQ�t�Σ�CL�[l��͌�9�B�XgF�E5(Ԧ.3Z�H��X\om.t�fں�zsְ'�|JҔ���w���U/��B�^,3���7���Qæ��� �2�8�?k�z�K#2�jf[CՒf5�f2�U��=ژ�ݜa��gmgf��]iڃK�T�-������t���x3Fӕ��3��X��$0�7$��l�ؒrV�ғ�`���wߩ�&B�o�,�7#2��R[�&*_������������4�To#,�?.02�!�n�6#,�Ω���с�Đ�4�&:�JF��9^H�.�V:��W<CM5sy��767��L��L��$�g�-b���<w���;am<F��OK9�{O�b�0�cM5%ܚ������0����01�H�I�#ӭ4�5u��,Z��:�q�ޕ�h�M���G���s�О���|������NU��e�QoDJ��٬�L��b�>*u�n)��g@:wC��և����ٲ�o���mcX�G�|6�'�Fv(��n$�=�JL%��f���Lx�glhpI	�S��n+�4�G`7���)�R�w�_<�0���^�P��d�>��llg:���5���%�GQ�vY0™���ti�X�	2c�X8��"$�kfM�(}m���%�]���B0H�Ђv������MqdKZ��2D�CȹiawPPe�#20��qL,}��)��y[6ۍiT��aS�J*V*·��U�|;�k�L	Be�PcUpA��=y��<�;C�Y���+�Yt�WΨ��~뜷y��ff�#,5��1�LP�M��Yz�t$#,hi��m<-�bmu:a���mx2��G(�0냮`�\6�%�C����j��f��q �ba�v��dHK��#,���?+��#,��	+DLzY�UoeS�.i8u���e�E�‚q��Y��ջ� ����+/I�#,re�먱L-�THl�iv3ss4tӕ�Ӷ�WCBn�R�o!�N����Q��2(dش�#�.G �u&p�-JO����0������\�b�B�fY|c�4D#2�v$7��F7w����"���!4�t���p�����њ����n�ޡ�,IL�cs/{�z�V�ʒ����1�S�[O�s5m�i������f�L�F!ȟޣk|�.�9"ffP�d�x�6���!�	�\�8u|"��m�q�Kf���s%O6;�a5c|��7�$t5��q�����֌ne��dwvt[��LLLb||��1�Œ�3Ԋ-���p�*!L�E }��#2����?���V��=�'�d\r�^rV6�$M���e�4Kb�3�#,e����m�+k�s2�B�9���H4q�:jn�21�O)&PmV����\�[�l�f���5�,yU�Lb�0vB��E�h�tz�#l�[�K��~�2��C.|�p��,��pe��s���괝S���,V��N��a59e����1;3���T�'|IO�f�WG��|�&���"�P�$'I#%Ƿ�ڗ�@�M�@�S0�BƯ���0�1����Y2�F�&���ml�J�Z�5/Epf�Ǖ����=3��>��."qݢ��Y��$�h�[K�]qۀ�P����$8�)�[� T$�#,�GHؚ�5�}f��#%��7�I()^���5_^�#,"�&�T��;3��`�t�G��#��wb��hTk�!Kႃm�҂`6��`q�Br�dvl'�d��^�kJ$�C���a8�l'`���Ŷ2�*6��J����SR�3�@�0��t�w�)&�#,7Hkҫlɮh9���a2�D�#%ٛ�jɔ����" di���Jf�JE˻4�Z�N�(X��S7p��ͤ��C�sִ�M�RC��9$��iL7�l�.Dˑ��IŘx3�a�՗�Jtf�05a�0�ƹ��f8� �v�!=��eV'���A�	���짒��6�у�:8D�	�Q����p��r��l��f#,�To&�������z�.N'ZB2�9C��q+���Y�L�F��j��fcO���:[!͎	�@:�4cC#C8-Aon�4>ɫ	�Y�U��q��/���}��FjP��L���І�45���0�5�������g��砠�+�d�C:8���A����P�Oj�|"ǭ�\�!`�C�F�u  ��L�3[Q<w��x���ST)�P�RT���� 5��L�#I-��N�(ö{���(�"<#%�L�1��F6�_���0�\�cKY��,��E�Dv��J��l��q�>���#%T���ն�+��p:���!�!�CU-�%�iu�1`hq�y2C���fL�.cX��#,���k0غ�WU)���}��0��2,.���@�@m�Rd'��{��� �UP�C���@Cc�04p�o�6p��bIy���n�hg4g.3hn�"K�n�x�G�6Q�E��iuA�&O���H6G����P�,�v��ڹ�CX�2'#R��ͦMIH�GL�k�L������.�#,;#,���i3�-�g8f#%b���缾}<��_�T�ɚ2f�п�A(P����E!\4{3��6�k(\�>ԤA�����Q����ˆj�{���$�22FI!#%'¨�}c�L�1�NB����F����8ԑ����P*��g�2�2�]��we��-g���@i�u��❲���}(=������pc��/y���YËK��W)L֍�&��[����ay�/��(U�F��u�͓)���\�s�'M�.�iR�k5����Bh7�n�20+a�6t:����<7B,����z�1�����^��5��4pu\0Rg8`"}� �R��#,S#2u2����I����J�yf�6E���,�B-��MD��=�h؍U��� V��*�N�qT"Q�K�=���5�d�z����m���;U~�#%7|w)(%���9uwu]���2����6J�r�S���vE��nW�]g���ìy��C��5��;e1ت;����~�#%r�x��}�C���P��H�j(��Q���q`O��n<|;26��w��~�2.��f`��y9?ce}�6��|X�{s/���'��4�Sk /��hiQ��6Y8v��o@�P�o��nF��k`�Ѡc�SLA-�%T��GL0�.֔��.e��A2Ac��y��� H����Ə�bf!�DCXu?;���Q���H�>ƶ�6��s������ZmJf�Tk5�mD��D�6�2Ѩ(�ŌW��գE��D���k�+EN�E+�N:��$�2]���v�Y��C��H�|�k��DK1L!$�8�DV����Q�X�vz���;���N���������f���C�rzM#,���"�v��T�Y���*Ʌ~ ��d�vP#2r:m�m2�3+���4�L�d��p��R�7�N(��cKi"�F'���f4j�]*�M�K�oB5L��כ&1l�R�#,�h�q�ip�h�b�Q��8�D͌pgܨEb��`)�8Yv S©H�p���$i0`_����0ޤsL�w߄��#2<�=/Rҁ�rL��ݵq�$��1���d�7a�P��T�^�J\�Z!Z����f2���tV���h�-	nQ����S3���x����#���#MTK&B��f��:b�x�0�y�ӻȧbm��lc+A)aLDH�c%���dĕ�H]��H�~lA�P`�#%����4#%�}�����'=b!�S2�4LY�A�t�]'�m�Z�7p����H�U��NJ�##	�q��]rg�R�rE0��g�i#2Ҙo�*#�|1)�7v��#H���Pފp�(e�\��#,!6�~���Y�f�o`�8dd9:pD��TL��H�#2_;>�a�!9�Đ�h�B�n�ܢ�ְ2A�}N�'.���N��YVᕣ����i8f�~>[/<��;�y�Y"��u�n��L3�RA�>U	��R��X�U��k�+�"��saZmC�7��R�ג�3�bh�č('<���;X�B&�[M"���ս1� ]����Ž� C��X�)�(ݺ�d�����<�HB0�L2 ��F�����@8#%Z�H#2���-��06:��3�	F�f�h�P(+�P�#,{B�g���Q#2�FdϹ\��R(�=���պPa�(=�`,\�'�Ά�|i�l!��ƶ3;�.?�h����}�u��Jb`FC�+�d�&	�I#^#%��VōQ��mX���*H$�	Kަh}J�~z�)ܹz�>*�ˑ��淔=}O��֊_N+�����ԭ^���]Y[Q�Y����ZI\�&�tӆ��J�4�ɕj�`teJ����i�j�m&��&�d��v5-z�b����3f��F�4��]2����m�Hm�|�o$�)��j�ޡ(ef^i��W%�����J�4�D��\5&艹��p0�Nh��SP�pJ4c:ڝo���!�F✩�Y���ã8��i֝1��s\�Xwܺ�]�	E2±J|�&-M�	31�5ę��dgZ�3��m⪆��������	5�䯙��)L�i��1���$�#2��c�#,T�C	Kʊ��Zn���dآ���sL�g�g(mIA��ņ��c����V�J��#%*"�5�$b��hڲ�fz{Yay�/&�r�}��q�k��@hX2���"�6&�I#2�	"D�"�5���P�*�HE_��ՃT�`���O©��s���=��QU�>�J���v�ٮ��^�sח��e��H�!���V���i���WV�I��w]wqI�W-z�re�i��ʼ�V�kp��i��1,��C%"G��F�HZ+m�c)m2�$,�ț5���5"��������ɭ,ʚ�4�����j-P`�S4Z����ā�o-��3y �+�DZSV��#2!�2.�� ��B�m76�.Ģ%"�QP�X!�+��D='q��z����.�kի�XR÷�@���45���fa����x���P_X'�لӢ��U�;4z��KS-��#%D�F����&d��c&�M��sLU<���93#%��z�a�T�s�Y:�t��*UR�#,bQ��#,"��Zm�`�n�)�'':+��.#{�硈M���G��iׅ���6��O���D)�5�r;3#%XQ�p���ȯ���$HZ5C^�=����Xlw0�#�7�L��W��r�Q߷�S��~d�/��ݥ��IyU�\��#%r���nU��3%�ܤ1�lC)$<�D���.��~��l���x3�ϱB���4@޹5��9��r����F���J���W��8�^"��jﲀ�&�j�ޡ��~��D*DBU���1����������(�QP'gR�?���P���T@��� Kt�vKQ���Ւ/aD��*�L�nkk�e�Md���ݫ\�m6����(ش���d��)TS��#2Q��u�6��a�hf4ěEj��4ON(��Ԯ��%��v�j����SA�S5��f���%�A���_������K���I�(�����ȒD�6��u��I�I5-��w�6&�i���*j�m��i7��Z���*#���-�W^w$�Zd��-՚���j�]�)��Б���b����ޗ��O��T�Cݍ*�o�ϵ��V�Q�#2���|;+�զ�j4��xI`�w̒a:}Z��F�S }����c���r�U����i�:K@������Mx�&��TA֨bA �$A�H,�F#%!��=�6����_�"-�J٦��l�DTd�0��IP"]P�Dd�Ȍ�[�D,�T�:�SJl)�iJ)��A�*ۛUE�֖�F�R�3�E	E�&�Kmi�i�Y5�Қ)R�|V�(�-EeQ-%�(�JHQ���)M"jLѰ�1�b��a�+e��2IdhXԚ�j��#2���R��T����-$mJ!��i�d(II�&Ra)�i�����#TEY6��&mI�E�kR�dɣJIiM�Y[RV�{�ݫiYm��YjCIoymk�͛Z��Y+V�W�W�=�\ֽf��F�K`��j�%V�6�ѭ}b�m�>��8\p�u9XE��pR�UM$j0�R��Fs~لފ����O�p��j2{ἯAp7;�4ڊygI*L�#%�x�#�7#x�=�-Q$!�Ï+����*/�'��OD7�dz�!�>��(��W��ɍtl��[4m����F�GV�C%��J7i(wr�J�1.��^����s1���=�_f8��r�J~�a�"��6��1�0��CBGp)��]28��"Flk��b���]z#%v��C�%~��ހ#2��B\r��6j����Xl�r��b���{�PO#,y�6G$��`A�Q���$��s�D�b�"����qݶӳ\w�	z�U�jV7�bb�M<Â�3�l(n�ؑe?R>�B�.r�)Vᲁn���M#,���!)i��R��}J�#�T蔴����1�>���ᵉ����	Y�#,܅$�j(�$�T ��Ζ�_#,���F�&��Y��U&F5�P�̵�}!����H����j�Η�{��{v�b�]�#%�m�U6�<���S�����V��o(������"2! �D��K��5��t��z�Vb�$���}��JE`0��nx�Q�X�ipQRU#,��(�0���l4R��MMSY�>�$���@���o�Ӡq.�������q���7����:���J`���֚��#%�0>�V����$�ko[��Ǖw�������\���\G��R�dA]%�@���m|��or�أhee$H�KFsU@Ʊ�&F�h4=�!�&�Qk�#,�m&�=:ōbb)�F�I�ʹq�ba�qV Ց�M�V6p�P`۴�H�9�0�A@�@�in1v8����D1��U"��].�L-Z)�T��R⑿UI��#%/N�#2:�\�z5J<TBG���B)�5�5�N� �7��#,�Ct④T��`S���Gv��ͥP���x'�My����e�>)�0wy���sRp�ӷ�z�������P#%TF�Aj#2��#2__mn�?�Z��٩���H|A�>���	��Uv.n�km�W�������c)��4��j[Ǻ%1����I9�0�%mŧ�֪žw�f���U�j[�mrk��i�Q�I�f�!�@�d�#,nj�RY��VTʁ��ߓ�f=����د�a�d ����/ �㞱J�Ͼa��U�c�C�y���cHd�H&@lFظ`V(Ė��Ma����V/���)})N0$#,qKJ��7~��rLڅ�~?[�Z�RU�����(40i!��:I�$����-Z�����5#%�c�(�I�1����s�s�gٙ�.�!�L#2�P�R3�xQȵ�x�ĩ`�X�h�N�����w�m�f�F����'3�GÜx�k�ii�}'S�qU��z��I#~MD����ҕ5�)�[�S>���"*̊!kken�kI��I�Lz�Q�`U2��힜q s�o{��K(����#,�<6�2#2��xd)`�XQ�O�@"��Z,+���X��0���x�@�Po�~�̈Ɖ›�&#,��h�"v���,��j�7v���&�29m��ښ��5�$k1��Dzc[���ت��l�#%`E3����6�*�U�QJ�!=e�,��v�3���V��T.4�;�3sΌ�9�A�D��dB�4�jH�^��*�j�Ě�k�IXB�%��9�F�Cqp��G���H�Ԯ�]�3iB"s��"HҪq�A߂�,U���f�m�}r��Qꗗ��qS��8e��=�mY	&&���4�.��!�=� �c�~�Kůu�4�uԛ3U1��z*]��5�w����v���n&p�y]m�f�<����~V�2����@�(I���F!U*�Ƕ�w��#4Ja�.��6����{�L���	P�'�u������_"*C�Z&��=��#�m���oN��U� �:�u�'�Ś��(U��ɰ6��B�*�K*ln����z�Cӽ5#2Q�p���ϨJ�:c����#�I]�X��A:����B����'n3�|�ْb#%��$OWa��IR��в�MdRf����>�σA���,�uODB�������Rqa�L/eԒ(� ��K)*�@��쉙D��^kի֮�l&�H� 8"H�:A(��:�3ۼ��v␚�s����.�)%�e#	�_Ul2ÒD:#2;����n�բ���3Oٷ��P�9u�k5ܓ˭��=$��Mq��v$S��� �t�b |D�x_yu�٢��.�%���zB��Z׫F��Udf�d�Tɑ�3Ͷ�*+{�i�h�E�\�*�i4Ԯ�.m��ĖI�X���"��ň��ƔU^���Z׍PF_����U�H���F���7ĸe� �h'k�г)�Ɩ.�Y��!hE	l���+#%����2��8A��`d���{��#%�ܲ�#䷆"��.���Zh�#2����HF�П>�N|����7,#�ޒ�@�<#,Ɔ�e�{����E�8G-bҔ<a���"��@��§�Uj��PT*�d�W�e�\��b(x�u�p:w�(�vG�UB��W6�k�퍦EF�h��	B�@	�7{wJ�#\$l����QxU�_(�)�O�)<�@B*�L�+(6�[�>|_`ow��Z(3��E��P!@��X�Z�0�?#,�3��~8�����k�Map.E�.�$����1���#%�!G�0�&?�ɤ�C��Ϫ�S`�;���l�������H����4@O�}��ŚH݆&�5�ϛ�J���Yq6?Q����F��aK�1#,�d��hOE�a��c<��@�hsO����(#2���Y�!��!]_f\^ިo��G\3�ш�YP��;u#%Ő�~a9�@8:�|)�)���gz�/C���w.;=#%�d#%RI�� #2J�*#2�DYX@��PPf��lY�!x�EdBD ��*�P�p;�̦["7̸�b?G���0V(-4�,̅�#2-�P��#��tN��c�{�~?~��X�"O�y��SҞԣC�'��^6r+/�0�$�$T�C�Dh�'�-��0����"���W#,/"�߫��>y��)Tbb�������p,�qC����k(�y��v���O���|>�"|��봯��J${�NYv���ԟ�H��T̉I:(�����V��t���"����"�������-��_�ᆌ3TAb��UH)��qML�)�U0)���;�Vha���h�}/o�\��U�-*D�9��$��u�*���ኒeb�mq���0���!�bY�dȂ��L�[\K�pd��P�&Qd���X��B��j�yQ�!�6��3+%hQ�#�Vk������BS ,��H�¶��)&Y#2�p��2S�PaD��Y�	��C	�#2d��pƽ��ɵx����ֽ*��Rm�j�ф&!�5e��2�M�1���7Hڭ |��cx��l���1�+E��T=eX��A�F���P��J����aG$NM�r�.m�i]�b�nm��|�$ƽwz\hyu�|[#aH�/Y5M�h�ި��vp����aF��:�v�F�#,2�F���5fn�0�(2Ƥ��#,�0e�17F�H-kjVVڦ�ガm�D��Tx���#,���ds�}"0�I�,�3����-�I�R`B扭<x:���_��g�@���I���ڭ�v�ɖ�5��.�O��褦��h�~����������~��<� ����'�7�?T��h��@`U�W�������KN��n^VƥK%�ʮ�1�D�/�*��-UԬj�m���H��%�YPu��#%��II��n>�� �#2r,;Q5R1i��x���X#,Gꂤ@��Y���Wg�¬{S(��k���f�!��1#%�REV�(F�T��F1%��D*�l#���`3#2��(�<�]_n3��{@�r�8�	A2T�����#,�z��H�*�j�SBm�r��)d��o;u)Rʮk��6��myfDQl��6B�=Mb�u]��5{(�̂���ѡBmRE��RKjMZ�4����#%�lM �	 TQ#�2<�Ԭ~|��!���$Z��&Q]��H#�#,E*\+�Hʢ�$�>�`@�#2H�e�`�ɖ@2��9$��㨋k��'%�#%GA .ʟC����1�����cs|�S/F��I�{W�$��\{��<�)�b���L����Ŭg*��+:w�}�#,��R#]�Bq.*��\W0�a6]�\��X7��:�\^�)QP��� �/�3��{���XU#,�unE�j!�=�`�+��ZT�v��%Rҕ5Xچm5�+�4�f��z��mbf�e$M�ey��o�}��ӷ�}���v����G��(PH�������H�>ύ�8�!y~�G�������tĹ�i�Zxt|�`�|t�I�m�*�N.��7/1�����CZ�h��S#,��3GK��\$��VR�E��pc#,�v�� ��Ãܘ���}�#%�(r��7���Y��>�� �)�z�����I$HI�="�?�72r=���Zލܴ����o��׮k�	����W�b��#2���5C-E��!l����Ȅ[���nts��S<0gQ�Uɳ�b?��51��G��#%�5��!$@C�1�Jt�ff�#�}l;���#1?��+�F�4��L	��#	J ]�54�U���SD�Ct�~����jL�Y�p]!:@�Gų�U?ږ�?�����'�?�ɦ�'+��#%�M{�ź�5��kf���7���C�C�S�MZʸk2P��CT��������ڍ�5��PajJL�i�������֌�e5��tA&��2���չmL�SdZ(Y��+f*��6�j�i��e��l�%�ZQM���5Y�i�m���`#KA�M�����������7Q�6N;�%��B&��rz��?�:K[�h�k�ʭE��]Mk\���#2�£���k�C�l$pB'bu�|4��6D���b����R�V���:�$�~���K�<�ʹ����ӎ0)!�4F#2}�?���>Y1q@a>;�VG������E/i�#2z<S�]98�	(�T#%=��CC؜�����h~"���C'�Il���)�cr��-�)8R��	����,[ǐ�><4�M���5�b�	j��`TЏ�,��i�jClnIrz���6�)��u�2�^�30x��p�#2XXP�ȅp>w��֪p"wCH�#�:Ed�$���(J;��uwv�&�0jO����T/Wb�n��#%A�l��n�,ef	��0#2OtPܘpqC�K�c�F���V�"��!��А��$p��/�/�4tv���Yr����=�6ϔR�b�]C�ZN?�5��t�T/���}�}}#2h^0���a4� ��t�����	ӅpMaj4����GF*AD�����Îxݿ��/:)y�$$=���~F����੝?a�L	�}=(#2I�B�i�VB�e%,��-&�|�#,1�j�>i�.�R�EebRb��u����ψ0���@w��������F�֘�VYd�AH�x�@�B0ܶHF�aS�$RF�d_o�����)���`H��E)�����*#ӲvDIU��V�J!��	F�� ����0.�c֭=���/�P#,�3�U�2���6�bA�Ȥ@�T7F2��KA�zYn̲C<�ͦ�(�"b��#,0R!��5�5R��5���K�y��%��k����0�3��x���ˉ���Dpa�B� �d��7S�q#2Ĩ�(�B�\i����X�b�� Z/9��ލH�E�G�Di@�ȁB�!ICb�����BȔ�P�e'��#2z�<TC;4��?#2^W֨�:�?/��!�_D}.��'}U2#�Jd��"�!M��j�UQ�I�O�3˹@�x�4m���0�K ����y�`�B��f�Y��%	�B������ƽ#j�0�Y6J-�1d�5##,p>m�3;�>09*(Nl�0)��e��Ĺ���MD�hFYH9)���}�I�ww`��tg�}\l�ȡ�k�=�P��"�u�2�փM3��L<����p���F�%�Hbz ��K#,,J�IZ��k��D�#X=<C��v%�v"|Jr+wt��}�>Ȉ��#,#,����\�er(�z�|���#%!^��C�ͭ�Ɯ_����B4�{�w%?#,��95��/���h~D$��߸��&M�e֔je 5VWE�[�$F�����B��N�x#�/t����'�7�@n0���L���5N�6��D]I��4^�/&sAn\\�(8#,�Z�#zJX��Ӳ�3Oo�ҭN���S�u�V��	������i�s������>Y�{�c�#2�]Y��Y�݌_]#���c�����o���5ЁY�T�0X#%I#%���b$���T-��a@C�,Y,��"n1�l+p<;�T�)� ��ٿ�:��Uy�n�.���^�#%�j�5����CG�&,��קذ�@B8�t(�'_R4/���@nYGC���#%��<�p��:����@k���mCV��v��V�{�����@�_[��:���OB���ŜNl��^��E0M�6��5ʶ#,B����ƒBc#%@�I�m�, ܄��B\�)����Ө�6�P[C��.�խ �*�'��	#@!���]�~�	�Z��0#2Ļ!��*ٖ�#2f1kR&'ѓ=����ۻ�z�+�.�p�k��X�0c#2�S+Ԗ��yx�]-�^���7��a�ZYl�VP�lT�,�C:E����^�M�	�$AM�=(Mj��+��(l�YC�\m����tx&�%�FѨ�	Hْ� a�X%���46��lJ���;��n���(a֔^,C6�f#�j�pQ���@_��qS��~F�Q����U�L��ݽ��}������.�@؜��}��ʶ7{�^�{$<%�P�#%�@���V��E�3�L�LJ�wuv �������Z5_�[}�יY���Y+be�d���5Jj�FH#����b��%!P*#$�}��ސ^��c�0�w,%6�6����;UU����j�T>Pr)N=G.;��O~Ye�U�O�k�>E���Y�#R&@���m���7��<�y�������m�S�W�?%�m���>��k}L��i��d�TA�G��#,����2��A�߳7؆V8����#,�hH܁���p�&/m����I	�&��N���ŌX�=��^����$Ρӂ	k���ro��1m�7�y�3�S-�Қ�{O���]��m�s�6�H_��;�m��#s�z�%��2t����1&y�r�ž���Վ9�<��^�j�ݤճ�����*��>g��>����i�����`Rv��@��� �*hiaW���\�E637�#,>OrcL�ǽ.�'X�t֯<�q:��u�kC2��t�D��fsM��%�HTb���[���S�F��A��b�;�~Y����ձP��&�P��!/g�f�sl�2�,�s��g�|]��/ �D=�`��*L���B,�S��(����rf�����#20�Q��KA�Co�U��Q�tݩDa�/��&��������_�d���M�:���`�b!A1�L���$�A�u�b���G#�\"�F��� �DD��V/@�Vĸ�&�*A��Q�s7��:��\�C�ԜǨ���YV_����t�PJ�ŬZձ[���"��'�4�|�l��M�G���3��=���J�J��q4a�\!yNHRe�L�Һ6y���.�z i���0#N����$���-��hG�>1"��5e�%�zѿ��>|MB�w��$	E���� fhl�M�	��0����b�EJnNeEh �m�7�(��4Ք�i۶��؛[f��u[+����˻J�V�͖Q��J����m���6#,��xxC>�/rR�׬�1�f���L��VH$p��Q`RM��|Rl<3��i>L� ���)�uITU���������a!}��)un���'1/��]N�h�_>�9\LN�P�3&r\4��Xv�pngS)d,�1��k��w���#����cÕ��net+�!�n#,�|r�2���{��#�8��ߴ|�F#%�=�����ޅ����r��yk���蹃#%Lq	'[��<1��������+��v4U��#,@yJ��F�?>�k&�1p�]c�?jma'z��ɼ��m���g �״���O����{~�#%�?�	B�':�\ڈs`�FN���E�HH�t��Ij��6�閪��kB�d� �����T��5���B�Vٙ���C֡p��o&�`#,B#2b��8۱d�S#,�.�.�xx�������}S���bs�ށh8ԡ�w� O�2Q9�x"�iѸtSH˥���{��|]����ٰ��<ʢ�*�W���5?6���&ᤎ�n�<yp��Ji����"&.#,����K����w�^�#	sƃj���o�4�l^6����Fx�ܽ:[m�t�P��#2eИ�l%&�L��Hbs�A�e,t�r#,�����^HAY}�U�G��#2�L��t��'�	����m$1�#%��xFQ�����xޥt,d4q�v4�tؖ�&A�c}���[u��|RF��mA�+�`Z4{h��:��!幻Pmה��aШT%_o-U��t�)e�7�����k���?Y�#%:�"W���O#��3ǒ�����cWfێB�" Kv�sk��l^6�V+Qm�V�h�j�6ɍRkF�X��m^*ۛcms[k�L�0k���^ϣ���0����b)�”?>#,ʫ�awI�ٴ�u6�v��g7nY�����;��d(]�)5�=:��}�m0	��fݰ��t��\ �)���M]����a6� �$6ƳRj��f1�e0��^e�{S�u�i6ѯ��#%H�##,G��{s0P�l�D.��=2{}�z�uP{r��?'l�u��#,�l�c�e���\�;�L2� ��@q�^=v-}ą#T����E�T��u��g��4���V�`ڊZT�+f�-��׮�`�&#,�I+o#%='�@�����[��{(P�;�����%UIA�GȒ>^z�g;���Ț�oAL�2e!р{S,���,�(S+��X�A�A��2@�$�B�U��a[#,aA�����׶fp�p�Pc���!�1#$ٕR	��T*���~�k�����˩���s^��4�l$r,&��X���!'�=u��0_,]�:gT9��~#2쩔;�w����\Z��r���*�&='��4u�g�C��-�'t;v3��psבb�1|_���\�X�����	j��tX�:g���.�#,�^�����{��^�9��3D'��#,����]N~��ڴ>:����/Ԙd�P���u�f��Y�!L�2UP�`�C�v#,h)�%��e5'�or�Lo�c`�#2�;�j*(A'�#2BiHڙ��T4Z5�]F,hB_�{*#,�Qf����nBhT�ci0x�`hpU�J�0`�28��h���!�ѭS�� �LkLD��!��6��(��spH��W�3������T����E�*��&�E�%ZR�t��묙R�һ����OSn�����z�n��]KڈX^�ziP�� ���Z@����^J�מ5u��L�hA�[)Y����-I$YM��K6��26�KK�v��\�wr�ܐY���ӷoys^o;Ț(T���]��f�&��yz*F���#2��Ҕ<��A��Ml�VDe��L�̐�(`6X�==Y�cn�#,��d�Z����hj4r05��Z�,�F4=�m|��i<�Tq�i��@�	����3u�����4�pi�)��j�PHV�mt��#_�"A#,RP�B�#,9�2�j�m���d��bR.YA@�1��Й0�m#@20��-6�a�M�l�T�2�VDVm&!�#q�m,d�3-$��{]kƯ'z]���I��v�Lfc��0����8Dj0���2�a����p��4�������R�-�.&��9�����֤2E����`i�l(A����ģ��&��ҙ#%�9�[���#������,��]�%�c)�Y<�G�.�N'�IJG�����0q��֑��#%Ս4���5���1��U%Sg�!K`J��$}f�l8����e��F�%9�i�	x����C?T�	�}�Ƨ"�1�M���ݗ��d6r��ԝ<�A#2������m��t�Wъ�c�B�יP[i���ͲK�����f��7��M%8�k$4$îr�P�Fͬ4�j�Q�b��4q�����Ѿ7o�=�l��Î8X#PX�T��dBN!.�Za�b�`�r�n2�2�ݱ��	��	G�O8a�)� �P4-(���B[w������o.�SR�mR�X���lF�,���$�#�Av�	D$���ЀrӁ��|CşN'��'������Ѫi���z���E��b�?t�h�4Q����i�&��ݺ��}�(ɳ�4�FA���JR�-!wQ�Q����ɽb��4<5���V�on�JYڸ�P��xSpT`VR������������_$�o�BiY<��Ο_�6v��Q��I!�s36��6o:+�x�6�&��RW��������f�#,��*��&c�vi"9z]#,r6ǽk�n�޹��幝���A�=E�A��v��;}ոm#,���������Y��Sx�j1_�Vvu曞8"���{�P�X��곐xFpSԚSvTD�@#m�A ���άႻ��󲛯*5ĕ5�9��I�����`ش��8eh&��8�̍I��{�����\}(qH���Z6�U+|��mc[l��t������\	SSeH��T#2	x4lAR|ER�FȤm!�ۼ�V�ңx����6�M�M��tX���M]���v�C�^6��d�i���5s�껻V5�Zk�^5�����[���7�V4��A`!�В�=z_�У�a�I}ا3߄�E�$V�H��QB�F�Zb���	�]�RAw���A(�{����ֻ^�^L�-��@1���e#,b�)������֢*5R��"�Z�l��+13M*-�����Tlj-E���X4hƙ�M�̢fLJ��#jfM�3iX���5 0�n>XT�W��_��;$L�>}�k�Pi6@d�D�R��:l�䟓������Z^~|�����q�Dll�|��G)�XA n-����UH2>Q�D��Z7���7��Y�U�k}���V�Z��]]AhҞn�#m;�:���%-m�TUX�[s\����7gV��ez�٬�Q����v���7��w����,�>��$�J#%L&D#,�h�LA"#2�b#,���7��`Ij�!&�J:�Q"'#˟���Pm+��4�� ���Nκk�f�ֶ!4��� S�S�:�>-{�>�#2'�%�'��~��0u�C*"�}3M�C�<`l�y�G�����`��31���,�q��ew2M5	�0�"�f��tpI��<��{ZQ��xB�H�����7�>��aI�O	���4C����πʷ���1���a<�5���+��/���h��]�3a�8f���=�6��̈́%��{+�3�Fp�,��;]�R9����0`�)d�LK���x&�`��vб��w�$�s���a=�BZ�,�b��M���g千�|h�X��R���L�)�+j�b���a�6��t�!u���''�0��,���-�T����RcI��Ë��;b+�TnM �b�Ea#%m$#,��B���w�d�s�+�8co:.3�H��"����% t�L_��$�Y��A�� �"��(EE����5�-37lZRE������H���A�QVI�l���i�_l�^wU�Oe�*�"#is]��ZG�*��F2������K�h�*7j*�����X��SV�(1�*�A�XU�!R#,��aS#2$D�Q#2#2��,�ʎXI���aV��BB��L@^4��?U���a84�1z�������{�ʅ� )H^v{:!����O��kh0�U9�87k�s��R2qeĜ�q9>� o�1���KQ�n��������*���"%k_���V�j�*�m�쀑���C�L���B@�P�J3������%�a!�t?Bj�?<k�0�mC��`E�s��l#,7�������+[;~:q>�zXӐc�"<����WO���7�S6r^'o�k��^#,��e�-�/#%����8`��! �1U��Y��xِ��!�(�M!#2�%��(�f�i���6&r��#2���F�U�;20Ƅ�5�*��&��k8(�DR�%+H�I#%� �6�0��@��%ɰdX<�2�^/�#%�ez5r������%���;��>�Hש���7�9���lޭ`gĪt��$��S�����}s�<�	�� �USE2@��J���db�"`A,����IB�.Grc>?�ύ�x��^BSUwU�kl&VvV�1�������2|��,��n�]PRP�)�pҎ��^CbS��y���dM$���R�x�v�d�b�f����\ەʹ�������ێ��s�r��t����<�G4�o'�n�]�fX���mR�v�\ܵ�j�m��Y��6e�d�[���t��Κ�Z3�9Wl��j-9Z�]��r�n���f�#%nn�؞����v"A�#%=�}[��r�����(#%;��pw��A`�j�� �('k,-����C�QM�՚�����#2���6�R#,�)��T{�a=a^��6{�|M+@>1/�Cџx���(P~>����N�Ӭ�!`��V5��5j2��_=�UA�%F@R�,���g�� #2�#%�ίw#2)��","��*	bBh#,#��p(> ZZ����\�nv��]�K+0��^����y��́������%�%Z���BFcչn��)��&I�U�E4H�RQHCL#%Lst{n��I���-��R �#,)k�`&Q@��L`BA�.���{�12#2S�"��y‰��`e~6(La�a�b�C����5��jp�@֙��)U_}�b��+R͖�i�@R#%łGz��r����[�k|vٍdٵ#KL�$UBH����c�����/��{�(�Ԗ��&���P���@#X�.\1�D�t��jgm<f��#%=QRF�⦻) #%�Bw��P"�I�#29�2t�J&b��l���'���{#�!0�S�	{ߧ��=��(M˭�#,`b��f�Jr.#2�hR$�MN�s�#,�	�Z.�#,>2�э��)	$��E!�N:���>��u?�K��:a���h���ܻ�hi�B����D�ʪ�#,�KE(,��H�PH܀4,*1h�r����F�ͥ��0(D@�#,d�L�P�6VjBTBW@#2�#,c0f+vʆ0T��-���-���SҮT���f�׊��Mb���#~N͊��/8��o:�g>�-i\4��T�c3h~`��$.*��j��K�����Y%z�B��5��{�6�;cI��w���3.ZZA��#%$TG���JT�n~��ف678��	�WYI�v��1��P��M�#2� C]��#2Cȫ��:Q���FЦ咐�Ĉ0��(V4ݨTr�)�-P�F�kx�)���@���G��#Ij���^�4T#%���A`ăD�U�UNAk�V��[�~�S4�ޭ;b#,A�#PZ���t�g[1��	�s�xOd#,��y�GP�)�)��DM�p�~���	�6��ij���L[D M�t�g�!���U���������'�צ�V�;\�Z��6�����ɒc��$���c����vHEJ�Gt+�rf���lc������Q��KK�\�P���.Zi�NK��C�^�G�4C�"���4����hv�ڃ�#2�~���q؍��v��T@Ga�x(��d<�B�#2	=t4�Uc�"�C� �DC�!Q�Nɢ�E�)�v?|ž�N,m���3�#,���!�m�zL�׭?=)&�B�S4i�5��a6�|�#�#%:��������|9�}�����,��W����Ԡ��(Th�}U�u��)�op�V]�L��5��!9B4��U��-!�TQ�-�B2�6Pno���)� ���Y��Lm�(��T)���Z�;xxL�)�i�s\�6EУ�"c"�h����JeKjK�I�U���j 3&4hȉi<��|�D7�6(��9�?/޶������LEj#2b�ކw}~g__�4��H�)\j$s����^'bv�=�oi�sEQ��$�0��#�U9�0$�{��~*��#�Ͼ�����1L}�,�jۄ��{�r=��W�����z4����XӁ�����!d$r�6i��1�@�x `؃�[�Z"٭b1��ǢM&�T��}s�!�d�vg�#�^��lsN���Ď�Bē�6��>��3Z)E�A�<��gJy�����l����:�İc�=�7F�>�W`���Y8r�W����`�(7��k�񿎲��<�-��a/<������\��s�#KK�0:��7�#,�}�=#�x�����є�xb��U�L�WK��6SY#����3���#��:@��bF#,��T�r�"��f)�#,���];��#�z�WjXq;��F?���Q������8ndwp�]}[t�	S��y�+��p@���ٛ|���8�i#bf��V��6[k�H���a�bI��F��;g��#27���-]��K�I��S��q�KP*H�f�e��S���#@�h8ᝎOu�m���7��]����fj�|X��=���%l�MfG��&-@��B�߰�MZ��[Բ[ŵ���9�¦����+.j��j�W��!=g�K������*�����3��En�VW���z|4G�@˿k��j���]�ȶ�c@2N�R�b��q������B#,�1��a�GQ�G<��g�h�H��G��@����k�nxy}��N�G�ܴ�\�e�,<������4�tϰN�g���WB�C�H����Nw3�Q�L7H�ρZ7I$#,L���%�Q�1��}��2w�ER�����PL�@�tIz�$�4�n��D_}��>�P#,�a�A���{�J���e�#%D��#,}�0c1�����+eO�P��]�	"��x#%I ���C�X_���#2���ADI�!dH�(wn/WAة���H�Wy�+�zS!����M��1��C�i�N�q#%��s#,An�#���ވ#��:��H������5���c�> y�+M ���/���9٫j���rdы>����(Xt��9C�Ye�H'@�D��H:c�W|�L�y"!��G�Ӑ+Ώe�W��+q��g#�s9eY�b�0j�6��lv�)�0�#R�0*$�=;#,�Sƭᮡ=��uj:�@���7;��l;��1��@q+�Z��������+)$��,�ވ��.?�[�ҁ��>��<C%PA���P�<A�ʘ~�!����#��9��q��[eRq�I~q������KPf��O�)r����J'�����J� 1s�U��;��/��>���[�v��/�>%���}v�3�?d������;�7��#\����x��!�'c�`.s�cj*����T�q�N�Lh1bB$�Z$չpc"�>8J�h\Rg���{��j�F��X$~YG�'���?iz*����#2�U1��RH�D�̺Ħ;�ۿQ�W8K�hB`�ӂz�6��yO��İ���=����P�A���o��?|��|�L��ڭ;�v��50@�:�~�}"�GJT�]��["@���P��l�9tI:�����lB�ЖLgJ��f?*�2Z�J�y9�W*��Uک4km�٬�T�X���SP�E���Ysʵ$���s\�.^��}�'���(��!�R�#%X"�����o^��G��<��3(ʒ#F`,�A4�%Q����(�F�T��M#2BM�&•c!�$�����ɳ'��:��7ޛom���?X�$�6�A��a��h�3tdҊ��i/�x���頖@L@�5!0�#,�%������X0�'N�>�Kn,�>�2�Q#2�ԊF�Vj(�%�VG���oGTa�"P��!��bcm��1�.��[]4����>n���ܟ`��&A߬r���6�����]���B e�t���ױ�q�>ß��P�ќ��A/οPL����U%@�@��=[Hg���rL���[;�Q��2��|�#%�'����[����m��iG#%0NPȩ-D��#21u�2H���Tm�gu�J�m��7WZ����!�����{x�z�q¶�cI��d�i#���8�x)[�R��)(�m�#�R��5LƒM��!�M�Mi�x��W.�,�-$�Fr�=����\�mx3*��_{��H%��)fGH�.P���Z��#r'��N����b��.f�"�b�W�~��8Y�!q6� ]5���\(IQȆyNODj���덮#,�qFD�S�V�*�@ܨtQ��i66U���#,�V����B�������5A�����<w�n�]v���]ݮ�#)�F��f�&�#8���B�����m68�MD�2�mM6��M3�FSLlkp�%#,X�#,��nK�'\���Ir��#l���@��W��#2%]R(܉#2�p���i���n��J*[�%Ta���o#2�T�#,#,�#%�:o.M�y��n��JU�.�*.��U�K��$MT�c�SOy�l�2-�����c4Ng�9z�ƌ8�x��q!ع�R�U��U�� HVI�@��:��j�>��3OK	 �>U���c)Wi���a(� ��Km���E��!聽�T�#���(F5�O�4�A�7�2H�ɭIA�1�R����i�N��4�X#,/)�Tq�Z��F`�)��Z��j�#,�iQn��@dWc��B�64��b�^)����0�#,b��Z ��sȱ�T}f�͛�77|{ƬZ�Q�r��L�!ILs�C#&D�VE�Fi����(a S#2H���+Bd�2´*�NDb���w�PٗOK�ث� 3��!�̘�K���A���ء)�"��7�Q����&��Q# x>l��=�UE�8��a����L�&�f����M�g%FSE A�ǹ�VG���5�C��2#2>"�r5��W����}6�*16K�B/�֛�K#2����3+_�L��.�1�cQlBb8O›er{�k�8YX�E�-�6�4�x5H1�#,���]�`ŰK4�J�(�0�\����0�#,�(��!B��Q!bJ��"���4����Ճ�$C M�5$P�6��¡P�qs�ỻx���ytŨ�!X��'�E(�Z��D"���_^�P[Qm�B�ٴ͠�0�:ժ�Q�=�R��p��>�ݶhj�4�Gex���#%��B�",~p\�X������b�uꢏ��5Q=TQ�꒫2��G�H�B  �#��h ;�(\��/a���%D8�U�b9�_�� ,��T"��N�+�`Y�/5Q�Z��c���#2����`z��X��b1�����komu#,� ���)#241U�)����9���=�4H��M�i�H~�K,!�����9�B��A��ADG8޺�/��������Bfڛ�gy,k�������]x���섋:�#,�/=���I�E�J͞&���j����n��k%�R;t��G>M�3����W�A+h��#,_��T�><��r�y�%C�˂�P�TP�`��N����x�����:����|/b�2A4<!�ʲ%u���{�H�?��b�|�ct�������^]�}��������^��#,��H��\9��M�q�S��5����:�!b���T�d�|�� 4��G��rA��Wԝ�d礇�콦����z�R��'j[b�r�#,v#%�ηU�����T71wV�f��m�Eçа>�N���F($�ȇ`�;�bY*A؂eb����0���N�R�QmT�ޤ��H��s�k"�U� L�0�߉cYHj樤0��mE��-g��#,Α9`8��:i64Ir+�UA����D*"% "�RR�L�6�k�r�Kh����Kr������#,�F�����mm�VCXۛI������msgw�\�dڃj��i��#%��0�'{,���Ny�`OLCTW��8�fk离ᙉY��6�C�d���-���"CtE� @�M�C���.D@�I;��o���f���8��/��#��~`���"(�3M`|g�RK10��'��blL-o����!D��H�JF� Ɛ�$��逑^#%�c!��T0�U$@#,mm&��kC[]&�i�t�-�K�*�	v�ytH����T��&�F���*�D?��>�Q�#�:�G���#%&�܈y�RuۡF-P��K�2P��HD��OE�iA��C�BR�@t#%�ə~c�?��bD���R�n�3�#2��@�C��j�tp$�(��&ںڿ�e-L͒IJ1id��i66hmIEb��RRJd�4)[h�TU����Դ�2ԴjeJŭ��!&�~�>u�ܐA�mֳ V�"8-8d)Kj�+�x0b�"�S��pcq�1��`D�A�P#v#L�G�$�M(�%y�	1&�QX�Cdc`D�Ik	P�FL4�`JZ�QJ�#DQ�4����"�E��B��*#%-@�������wR��Z"�ۦ���ݘ�:��+��n�1R��"V$ �1V���;#%�t�\Eﱻ8D#>V�t�Vt�<%�^���K�Z(�QJ��	RD�`^�?�cdFnh{Z��P�l3v����,~a��%�����n�!#,�Z���0#@���0#2!HT?oN*b��C���B,�”��&��p���G�8'j��BID��n�ɼ���˩R��/һ�j�kbѪ�@$.#,-�g����?�{���)"0�2FnOW��6�5��w�֐�T��/��X{Ap��!�?��?\VQ*r�.&�otzY�F"�`�`΃Ձ��R�ՠ�����J����%�MY��S|��|���#2�u��C����v�q8l�>����[,�0���\O���ʞw�[�c���%a�����҄��~����S���=E�h�&/���ۧ���D'܀��u��3K�.����x�'���4�n���%�f{ET�R!#%�����[#%]��o�c6:b��tu�0b�Y��|u\km�'#,����5�X�̪Ԯ8�.�#2�`f)�bm&ZYLĒ8�n]�=�����~c��7����wl����h�Hr���T2�!#ޫk�$������-k��BLw�7�d!��A#�7f�h���+e_����r��5k�$Iև׭-���K(�C�tSIɂ:@GH�\�Jm�6�8���}��%�7�nJ�y;k�Σݹ;,��)�-@�^��#2�lg�`"f�P0��]�A��w���Ay.N��6�mf%��&�0�.3K�) ���I�-���T�a8���3�{�����+!-c��%K��p����w�fI���V/J������g�p\���>קL�wI��O�Q�;`p��Tq]8���R�|�:���C�t42���o��x<,�.m��"e7�J���xm�l�2a$3��@��#,xzk}"y'�����9�R��^0��2.�e0c���I!��||�3�UY��!b<o�,pѾ�a&	q<G&��S��ݍ�;hY�m�e�fٍb��lC"�q8�1D�l���c#%��~�#2'^Y��3�zY�mS�)]����Nʹ�Ù��>��}�.����М�^I'���4oSI�>%�+횎��H�K�wԇ,�u���^���O��F�%*1�mS�G��C��6�I��A�؄Ez֎��ƻ-���^g��}s׾ҵ�)��^`�qq�$��a�w�)�s��8(u�<d�H9�����7���1�6��M�rJ���Z��(ʖVx˜������|ʼnt�CVo���.�=��$��#]^UQu�=��C���g�srXf��!߃��M����_���z �/f����_��W>������++d]z�c�_��=�M���%�`v؍�豋x<�9]t��9ۗ��rg��3;+�i�&v���^(mF��m<��9�2m��B��YM��*wa��#�U429r������k���@�2Uԗ.�L���s��a����*����$��3��W=��5�F�0d,� xZ��!�xi"e��6�I�jp��&Xw�x]�1�y��w^�B/�$gC���4!׭usJQ��S]�Ćhq3�q冂Z�Yv^A��0#2s�:L�”o���l�V�Ʋv`�q�۝<%?UI��׬���Jfo8t�vp������#%�4����=t���]v�Chd�LC�*�#%�@=�#2� "`�#2�"#2��*Z�˖�QH�d�»6�e�zX�v�s(Z�n�U�������T�WY�Mx��P D�R�3Ս��L��Jњ\D��uV�6\Û��Q�UZ�# �����Dj^�&����'���*i�j��i�cA>�[ ��O����'�a3�a_*T�+9�����]'`�\�Σit��������gh�z�:�癎�����>�c��ET�QSSNF�b((�S�ۜM��e��{A�]��k]zV�4n����{#,�U���	�b���Iy[OD3�}���i	P�XL�KC	b_�l�B�m� w�{�-#�i�j�z#2ծc#,�ۭ���>��)�h���#I�9�̥�-�O���X�}Tp�(fy߉bP/]�7ZU��KL�o��\Ź�'L�<q{��V5�v�f����Q��h�т���r�7�}�zbn�q�j�m��<�Ȼ+��$71��`����]��ʧ��D�]zܷ�9���u�K�8�Ǹ��y�F�Y����������_h�L0xN�q]���3�Ͷ�#2��4vK#2z��p��B^$w۾	������_�����ۃ�L�Β��P�5<���G��z�`rХ�K/V��#%�#XeAO�ATCKx�Y���u�SU��G���P;���'���" 1PК�]�/Cr̆��wG�ѓ�yt2yѴ�sV�#2�o�r�A�a����W+g�"l#,aO=gr&�9f�^�:p.XC;�mr�yĻ��0�͙pp��,�<���G7k[óT/ؖa�r��K��cӹl�F���Q�[Og:C�b�u*�l�A]�P�a \��ɭ��!eø#2���4#,�Y����qbBI��I��@�s8�Z�2�I�@5VH�p������-F�~��idj�6M����1菻�B�&�k]������~#>��ɱ?A�(������p>�r�0����:��ʕ﮿���c�~��}\�ֆ"^����{K`�}S�6�5J�>]|;�ɯ�c}��vu��؜�=7�X��.l����1��$C�ҡE�|�>j	a!)�����zc:B詡Y��1�qU%&F���Ġ=#�	��d	S�kzkW�\�����h�P�U@� �4������V��55�U�����֠��A�ku�R,��`k����APcJ*"��EJ��ބz�o���7�9�ԯ��R�#%��?.'h���˶�/#,'I ��7Ӿ��9�W�񷍹&ƴ�ֿ*�5m�\��j��΀�D/zN����p���SUh���}�X��e��R�9���c`��#2�D"5��j4�{nm������֌t���1h�]�2���M*�vl�8щ*�G�X����^�&�X��HRU�e!ʼn�A�Wˍ=H�wM�Y�H�	�"��ZL�Zc�sd0�j4�M��I��u����� �4#2��T�4�N�n锎�B����3R��7�9#2-�uAH&a�T-G�$َ�˃�J�abnF;ۯc/MJi����e�܌��F�!!��X��ֵL�p��\y'[#,jǩ��9�eo�L�$1����o0)�T,Y�hX��x����j#,Y�m��3���o�js�N��4�XVC3����$H�`�І=�saPBP�"4�1a��ĶыW;QU��Gu��:T�y#,��s��[�#,+&JV���[1�L��L`ΰ4݀���=��Z�ҒF�F襳V�i�]P\��R8�F�0Tj���xH���1FV��򣜵.�CZF�L��2V8�jm��UJa�h�Jhp�6�6����ţo7�L�Y]�9�f��n]>t���*(�W��wV�J�CZ#DQ�F�f�e��Bᇫ�3`P��`p3D�_����e�<��,*F�eǮ)UW$y%�Q�%w��L	��ll�0�ހ��cL�"���b�[�cMUSW˄!K#2P�6�����c�kD�f�Ɋy虜�TD�ˌt�(�%���7�b��Lf#,��/*��"h���v���E�V��^f>��2��@�c�r-H�vS=�i�ǫ�5��#�9�����$)��o̥08�d��#,X��ih��#2���B1��<�FC�T�gAu2&8��ip�ĚlB��CV#2�ebkw�9*h�2B���F֧P�V06��� ��p25�o���Y�/A��g^	19\��i]���i�����wu���S�4���f�PȑR#(�,��l\��>X��m�9�А#�+7O͵~�����5�v�\CW�t��p��(v�6��?!�'D)�$�:��ո��Jc-�?|�Pa"��dw��_s#2z�k��~.7VV,�t�]�I�{���D#,_��7I�A�,�Y�IH)0!�|���?N���ΐ� 3�y���*����̂	N[�95�6�0�A��bs�%b�e�����=Z�M+�F������F*(��*�U��j�FFUS�0�z��g����<�E�J=@r;X�ƺiTZH�]%��C[�����G�OD��yѸ��W	�@H���瘢C�/$j&���IIWj�KV��\��*F�PlPPH��#,Xw졬��G����&�wW���~^�H��b�5CL��ci1�LcH�RP�L��ضKImX��lIY4hQM�F!�B�jF��$�f����41���H����h�M�J��-$�l0لJP�1`B*�����鷰���@'~���t5!���-s�{��s9�?4�]U�s@}��_���k�^D���<�8��_jז�N_,��IiR8�p=1@#2�9�G�ĆuCm��ש��h��;#��R&������a�"#�����V^��|܃���æ޴0�܄$4b(�a��XUSq���}�n�A�j�7=;��Q�j@�iN�}�����Ր�i�F������yy2��&�X�KX��-Z��cR�&�F)d$g2���!*�H��XA�~a�;����D�DT��ぺj��hT½�˃`ς�(TGaE�i��7?�5X����ơҢ���jH�&"(�ك�&����=0&��V`�Z��c��Z���bD�y�IlZ�YU(TF�����ь��6���&�q#,�Lb��P9k5����#2�]��A6�#2pA��mJT���fYd���P�Kő#,�|���-���ٖ�*@�1!E����F���)3r�o��85��������6#�x�m��b�UFƒ��L��!���Q��hN�3�đAB�R�]P��hl����"�p�#2K�H�[ɒD�I#�UlTCٿ��09#%&�&A��7��,$#%#2�v�S���ݎ�����~�#���z�g�)Q=���Q��ߋ�ɑ2uB�N�l�?4����t�@j�t�r�q���"�%H-IP�a��J���<�<�C�#%|���#2�Ȋ��#,���:�[z�魓�Ti���4Y�����6��}x��!K6׭j��e%=gȹ#,��L�̃K���j�D�h=�O�������9-�>E2Q(N�ЇU&��n�H��2I(�Ԣ#,7b����u׊<�9Z���Q�j����+�M��'$�k��^��@�W<M�q!"E��鬰��wwۗl�����`4�����SQ��**��B�#�kԟ�flS���/��T	̹�X�v����Rh�0��x�fs�(�ߥX��h8a6hZ�=��T�8UC2`�����t�@�'3��G� �V$����`��B��!�+��-`�H��\%0�����O��qYqt<%�f||�Cl5�e�m��d��vT�vx�3͞.k�c��"9��_���O>���yy����O�!�"��URa ��J*�.=3���X�Y�	9�\nc�b�S�2�!Ğ]�]���b2F��p���:��v�����,3�̈́JS�uUtD��19W�53��z:�����@#%!�M�&v�fD��@@5��U���K�ȁQT�Nr$�|���rkF�o��9&cq��2��rNb����#�Kn� �Ҋ5�a|j"3e�h@e/Ha�\��v�<v�K�~��:� ��౴�"q�H���Nz5#,�Zu��%1�i>:A$��&�5�D�EPڥH��A��?a��A@��DL��6k#��P;S�Z��f��+a\�FP/#-*<󵚁H�K�!!� ���w8�D���T-��m�h�����(��L�张pT杦j��������A�(�����^�o�<�A��X2E�u���n����n�L�Ȱ�M�&�P,�KI(�a�vY�������D�uS2�cre38�t#%�a�%筻#2Lp�O��o�,��p]��QA�5�J]Hc�r�B�9���]haCR�d"�q�5jd@�)Iz����=t	i�k�����[��Ҷ3��Ԩ�)x�Sq�4E̫��<����0e����;:�X#�e\$�<�,do�b9Έ#,a�]�V���<z6:kb�>x�D^�PM��L�a�\����B�s&���!�H�Ӥ�B�T�垩#��ñ�ͦbv� A�m���L\�RE΢�Fe�%o�ݓ*��,u��p�2oO�hNl�&#�F��%5�!�Ҟ�q��#2�t؄��N��YN�lmt�CHgP�1]0��Fq�Ț�!��^����m�O-e̡�HÕr���"�	5�;���#2�;���#2��-�;Em�v�4�h���d�4Z�:��}	��ʲÂY���s-�00��	�IӜ�+^�*f�zk�0��y���v'#,t�I��*�s&�i�t�ԭq�u!�h�5e�.W+#2�U��n�!�mg��̕*8����εl.��u�4�;��<��ؘ#2���ˁ�z뜣�WC�]&�&�b�(�n�H�&l����3���yt�ҥ���g��;�9��:ޡ�{���AӱMw��HF���ʎ��Ax5�-gD�L��X<dM634�1CMu�#%9�j�V"�"h4��N����Su�t�7�A�ZH�+��BN\��mgY��[6L���V�6�ľ�&���dYH����,i�?5ǖ�i�-����(�Ud�z������k�m��b5�h����.��m#�I�/��2�{l��M�K�ּ�4�~�L�t�#,�*H#2`9�_���p|�_���yScPC�Y�j��%=��(�v~zZb���\�kQ�~�<�'��}a[&��&�7��,	�VJMjf��LX|r�X[[�#5�0CB���.qQ����ݕ���VM��,�L���K�c�k��ĦHk��]!7r��cB�@�̷gn�ՠ�	�P�JP�H��q!�Y�%j�`���R�1ga0�Уh3׾�8��p����&&ڦ�,����*��`�s�����Y���k�|������ܜ�tEr�n\Z��4�3���;^PI��X�ga��;�̐E2��Ƀ7j$�M��a�#�r�hv]!�a"�`�鋫��5o�G܅����tL|0�$6d9қێ��I	�捜��j`TnC]F&&g�$p�$�#,�*C�b���i ��CT�6#%}�PV����kFQ�b��4�E����@u��T�0�,�R��H�74%��]�TК���Y0#,#,L#%�N�\���d�E"+�������jMe�4Y*�n��3,UD��w<�����J-v���&.;B�Uq�섻Q�hYPlD��Y��dE����lY2�i����C}����Յ�K�*��lN!@��'#%.D��a6�U@���SP#,�F��m*����(��@SD]�,��mxri�S@ؤ#29�qbQH�`H���B���ei3��QH�X�"O��^}'�DZ��Q��eTDXkգÜ!�9l{��K#,C�D#%Hv�E�HH	�UB���!�o��ލ��yg?]b�tW 셻f�V)�e�;�ƥ��5^KB�4F}	�����0��9O�v��٫�jQthھH�J��6�ߒL#,%�21�F��+��QK�$�.C!r5�If���#%מ��*�=v�/�n��r�Q����#%p��Jv�fIM��N�:�Ï]���mޚd�<Up�w%Fdw�*D���e"diZ���M1���G�V�|�M2d���폹��4x�w�)���u#��*f�-_�)6�`��M��UV�A^G#nu�#,���{�򳵚�Zcci7�wt'}e�p!>�=u�1�#2"ES�F\8?�C�[�L�3��l�r���~H���n�˙��%�$>�#%�n��T�{����#,�D�� L:{N���j)x��N�+FDm,�n2D*�1��J-�jw���n�#,�]�2Ę���BY!H2;�B�bA���4�bC��%?����@}�W��m�YA�:�nb�&��F����ѫ�M#2��$��,�Z��d�t}�>O��z���jg���Ø��Ԉ�'$��-��Z���[ɊO���F'�j#%�����5���#2�4V%vH��Ja^���C���9-IӀ����&�9w�#2nc���{c���xX��2p�m��RG�RO~�/����!�B'��J�,<��kr,A-�a�M�n\͗�1�s�f��}yJeV����CY�2�jj~��6�7r�p���!��")���=S6m��RB@^�+�4�8i�|.6�ư`��M#,u��{���4ظ���?�M��#��|aG���x��g�ʌʸ ��0�~�k��쵷kQIE��֔��M�u&�5�M�EGE��E�����{�P	l����D�#2����QHR�.�~#%������*��j`p��K����6�l�M�Q�J��ׯ���|���SR�7��~�`�@$#%	RE@����v��ƍ����q�g@�.����;�q֘��:��EK���kdq(1�I#2x��F6U4�8%�&²\��Q$Q���H�̳�[s��U���y�m�^��cVi��X��\�<ݑV@I�N�~��e��d���)�#%nR��&˙`9�Z��('oO3����c�������d����^��0���/e�t��U���V(���m�x�i�Er@1@!wN;�r"/�~���HI�d�S�rkb�|;\��X�{6�M�����AV�y#,�"��;����B/�QI>_�M2Lx��Z(�)�f�����d����m�#�����r���٨���+��@,q(b ��M��Y����Me�WӍ	�f�D�J���|�`B϶#2'2� i��-H�t!�Y/Y�_{c韭>��w+�ܑ��=Fַ���z#,5��)�I�&����d����-fBlH�����Rm�m#%�HʉD�$F,R�s���<��X�员���aޢ�����: ��#,#,������X��{ya�&�$� .l��z�/��ٰn„�N�=Ǿꉑ�K�����W�Qo}��I���w�4|�2ᗂ%�-/PA@<M���+�S��`�)m��tc��I�7;p�#,M�I�qA�q�)\�����e�q�A���a�!�#28:�	7$�l�}uq��;9r�H�@li&�����m���ה�a�%�j2ĭ���l��mN�#,�H#%���c%�B���#,6�-#,�ӭ����N�����NോF��>c)��d݊�h7�#2ֆb�k#,���?c5�c,d_C+#2h|�܁#%�L�Lgo���a��K;�!J#%+�蠗T�J"A�������a:��N�1|ؗL�#2��6	�$`D`C���PA��פy�,|O#,��(D+ˑ��rlT�dZa�z(�+4S(��x�?x7���2J c��A�*r�]�>[o��֭�F]�Ϻ��GB����J(J�A-e2[���O��o���w�ڬ�t<���ِ�'�w�}��E���D��Q�8f��500.=Ԗl���-#,N�9��-��T<A���)��#����N��#-�B Y�*�1�.�b#F�.��$6F�_Gy�����\��7�z�-�$6L��!���Kɻ���Y66����帆1]ݼ[�+����ل_�#,D��C�T�I�$#,�[v}^��QAEWȯ��lj��g�;�+5L'����@1OE�`uu� $��X�1F*K�����2�D���TT�lmH��J�ͫ�~X�o�U�{�4���MEb��R������h����k��ޚ�@DL��JZ�z�9FSĈؐ䐜�I�~(�b�)�#2lkY�Thّ��V*e�'�;��H�@"��uҁh�Eޣ@�D���/ޚ����>��fyO|	�Xp#22{��y|�T�ՙSU�XW��p���0�L[ðG��a�Հ������BH��S�1Ƕ��~7���Q* �):4Ϙ�Ђx���cy#2�F��D#,��!�{�|��0��[ԩ�B���0�tOr�BAy��*)Nci���D�� ���kT�RiI�[NӖ�ɦ����#2��e !�"�B�E��=�*Ȱ�Z̲��4���{���3�ᝈ� �j��W�`�[�i`M�ljh��4-���h�m!�„�#�����`�M��@s���5�y,`�6�z�oxt�/^Q��9�B�f�}ɨ.=��C��*��(<�ե�8ݓE�Ji�Rl�E-�T�5�I�–���o���l4V�6�H��ȢI��s��Y�,�B6�B��$a=*hU�>!sl� s*F�F&L(�QMCfҍa`�7�@��3�{�n�x;��T�������Y[Q�h6�#,Q�*�(�"�c�B|�G��=}M�l���Ue����q���!B#,�ᬱTa�\P�a��W,�5���؎����>�ęm��(ퟕ���[#{fdC`1a`�LLg}Z��x~��D�|Էh��oo��f�SE*[�l+���k���k��k�mMoJ�*-��7feW\ݵs��ȳj��ƚ&�wWw[I���i��M�YT4XXH��*�C�m��FƨІ�E�yq�M-�ԙe^����W^y֫��Ҍ�Z�e-y��v��E�2�]5�B�)�f����E��:qV�m�3��{���{�m,���_#22Ȩ�PL�Y�H$#2|rT1���zL��f�P��2�U��L�]u̒jsB�!�zUʏ��46 Y�%��E��\����䋈������a�b-а+��^01#,�oq�6��)�uF�����B�����>���Ę�"hj�T��|'Fu�x�i���[��30��S����� �Q�r�Fq/�}z���_��$��B05$���3U�w��3)#�#,r# P3>`Ӝ.rp|�M�p�:� �"`�#2� PyС��F�k���/�gW�U�foՁ�DѴR���k�|g��j� ~{7�;J���8b��k�E���{�4�F����8��y~�fk��r����(�Y�<�����Z��I-��������ӓ!�?=F7-�B`�ٷ[0Q�P��1��l���X�®���LPI��2X0�E#2�DC%��8O���a��Xb�#%�]�:�K��6��}�a���F���scF|�{�G9�����X�5h=�b�8����oV�Y��F8h��+-DEC=�vN�|���m�7�J?���n����^eB��#2V�ɤ3#2�w��hT1�5�Ä#,0��Kcb~�p��c�tñ,�#2��`��b(d7��IL��5��$$:(��;���vdl�#%Pl~FNx���������;�q�HH�����q�!�Ep{�g3����d@��e������Q��v�^��m<�Mz�}�%Q'݈������ ,��eAoU*#�l��)�̟Y!#2+e������*�q�,e�#%�ܲ��fk��5j��.*��Be��#%�O������g����~?�ܿ����?�o��������������x�~Oo���G��������_������������������_�����������#��?�������_�u�o�ب���Рy!���s>�����D�y; �e\?��iM�*�"���\��S+VE���e��o�Z��lX���-�~��Y���wQ$�&f}�+e[�5]�q(�Y��HVz5!٦�#,q�rB�)��Dm�쳿���@N��^��S!�iAsT?�-�<Cu����p9=��I��Ǒ^A�:��0�s�,{#%��B<��BR�?�PI\�Μ��x�`D)}�?}��7����K�=>=�#.��]�#,�X.�$0�x�4B@����_���Oü#,�oƗ���eN�&!2�n�3�[3?���0#,�J��!����n�4�Ʒf�Ghl���w�J�1�?���eT�h޶���K��<����R3�U���4²�ZhB�`����2������:���ɦ�6�[��Tu�g��D��U&a�]��K6K� �!��j}^}^#2�i�⑳�����8�+�^�{�:���p�Gꙭ69n˖(W3�$�$b1k��ؼ�@ˍ#%h���B#,�����xe:��սk�A�����#:Ӥlh�f4S���x�#2��M�{O��;�@�g8�����w���n�f�b��\�:"��q#�"a���]’!��W����!�b�('���!J+��*{����rd*&1�X�ɚ�*#2�z�R#2��˻���~�f``3(H�&���p��&�V�"�� �P�;��Vl(bH�$`�$e�2���(w�QV�H1M�}>������-�+&|�9��2�gv�b0P�#%��ҡ���68���;�)��"�j���J�lkY�3[F�m����DŅ�S_E�WmU|>k_[B:?#�E3�y�|#%�]T�i�$HB��"�<Z�J@��P��|��7��##, �\���V��[�Ys#�fs��Y�V�U1�"����í'_��1#2��By�aE����_���@Z>����#%�!����\��joEw°5噫w#%��a��J������Y�D�<�t�fƨ`T����٨��'�E���Q�W8U|n�ch�W�����z���h�R��1�#,��	0[��|��c^+I��k�ش|nmc�m�(��oSE�MAj��Z�U��<�vm�#%�\9!�ȣ"�FI�@���ọ�8����AD�S�����vꅘP�E<��$��e,��U�FFz�Z7y���M�`���A�H�#7b��[���k(�h�Gr:�o!|�`O�`�C�?-b��H��,X�mv���ԍP�E��:���ի����M��^�h	�! H��� ������3����ڦ��"�������(��fYr0�m�C�'`���S�� Ȟ������	�H��k��I��x�$�EO��@P�_���s]9�YT���ȣ��-	ݦ���-��з��m��ۤY�	r�~���}�;O�~����Br�Tr�CΗuǓ�;��Og���	�d�K��70�N���_Eյ��g�c(�?t-A!��K�'痀$#%��*Qv�%?�J�H���\�]Dۧ��X���.�3��v���	}p� ��9�ɓGmGJ��qTE3�o����Y��w��M�N� gA�����X��7^[	c~�qQ-y[Na ��;��fJ�$�	o�������"(�e�׿P`�v�d%�b���9���b��=g&(m��KUc��><q��SN3��7�~��#2����ܑN$��@
+#<==
+#-----BEGIN PGP SIGNATURE-----\n\niQIyBAABCgAdFiEEivIt5aBoIuNHTzxwSbTGfAUneqoFAl5/EXAACgkQSbTGfAUn\neqp2nQ/46vvYBUDSJoGs14ZwZvCon9BigvosXc8by8ncPXNS1GIzbO9oxjjrK70v\nwsFrBJ+gEn4p4x2fR9yXuYcZr0mUVm0rqchXUJRAuwP8zvdDcYS8KZ2t34H4NarK\njGj+tRDQbBa+SmUcJvUFSnesdtm/OFAAJ1JayAzJqvoV9a78fenc3boJ7ag/v1+Y\nIcKscr5FIz4FQk0JBQa2i/DwvmJFlmP2nP589xdtRldbcQjXF24PxnFlGejGf5EY\nWtLPNl0WRSzgcMbN2O/aEAFq8TkCgak36fGeFcIO+2EqQ4Z03QvKwlA0JinmgJSl\nu0I6Pu/YHs3MvrbzZZBEtEhnxKBkilkHFNi4RWymKHBUOqcfpGyDIrDnFiXzoqcs\nsQTJ+Cv95Fm0xbcsiIFbNG/XRWcfvdk7bSb0C3VsVehWS+LyK4twXD9U7iHzPsLM\nHQ0oUqxfMwqp0NgwWeIMhSNROj3eYbHbgn131Dpxad4N5M3ajA/dl/u6T+qVkBh/\nR7hh6g+Q7FwxFyOm82uA0igZhRy0rCvIjpLbteAufA/VUjhSNLha0pYeOKTGkFXr\ndtmgvC77EgAN0lG0/76UTI2NRIeNevcCmFsQvT7/13gusIh/vFetPfKJxXzZNnAw\nlutXw20Mp9LcvdY/vSDCEqrQzB2bJsvF02jlRCGhkumrzEi+Xw==\n=y9ft\n-----END PGP SIGNATURE-----\n
diff --git a/wscript b/wscript
new file mode 100755
index 0000000..46ad72b
--- /dev/null
+++ b/wscript
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+
+import sys, os 
+
+def options(opt):
+    opt.load('compiler_cxx')
+    opt.load('compiler_c')
+
+def configure(conf):
+    conf.load('compiler_cxx')
+    conf.load('compiler_c')
+
+    #conf.check_cxx(lib="glfw",
+    #            errmsg="Please install the glfw library",
+    #            mandatory=True)
+    #conf.check_cxx(lib="glm",
+    #            errmsg="Please install the glm library",
+    #            mandatory=True)
+    #conf.check_cxx(lib="openni",
+    #            errmsg="Please install the openni2 library",
+    #            mandatory=True)
+    #conf.check_cxx(lib="fltk",
+    #            errmsg="Please install the fltk library",
+    #            mandatory=True)
+    #conf.check_cxx(lib="opencv2",
+    #            errmsg="Please install the opencv library",
+    #            mandatory=True)
+    
+
+    #platform specific
+    if sys.platform == 'darwin': 
+        conf.env.INCLUDES_OS = ['/opt/local/include',
+                                '/opt/local/include/libxml2',
+                                '/opt/local/include/opencv4',
+                                '/opt/local/include/opencv3',
+                                '/opt/local/include/openni']
+        conf.env.LIBPATH_OS = ['/opt/local/lib','/opt/local/lib/opencv3']
+        conf.env.LIB_OS = ['m', 'xml2', 'fltk', 'fltk_images',
+                           'glfw', 'glew','OpenNI2',
+                           'opencv_core', 'opencv_highgui', 
+                           'opencv_calib3d', 'opencv_imgproc', 
+                           'opencv_imgcodecs', 'opencv_videoio', 
+                           'opencv_aruco', 'opencv_features2d',
+                           'assimp']
+        conf.env.FRAMEWORK_OS = ['Cocoa','OpenGL', 'AGL', 'Carbon', 
+                                 'Accelerate', 'IOKit','System', 'AppKit',
+                                 'CoreFoundation']
+        conf.env.DEFINES_OS  = ['OSX=1', 'POSIX=1']
+    elif sys.platform == 'win32' or sys.platform == 'cygwin':
+        conf.env.INCLUDES_OS = ['os/win/include/', 'C:\MinGW\include']
+        conf.env.LIBPATH_OS = [os.path.join(os.getcwd(), 'os/win/lib/')]
+        conf.env.LIB_OS = ['m', 'pthreadGC1',
+                           'ws2_32', 'xml2', 'GLU', 'GL',
+                           'OpenNI2', 'fltk', 'fltk_gl', 
+                           'opencv_core', 'opencv_highgui', 
+                           'opencv_calib3d', 'opencv_imgproc']
+    else : #linux
+        conf.env.INCLUDES_OS = ['/usr/include', '/usr/local/include',
+                                '/usr/include/libxml2', 
+                                '/usr/include/opencv4',
+                                '/usr/local/include/opencv4',
+                                '/usr/include/opencv4',
+                                '/usr/local/include/openni2',
+                                '/usr/include/openni2']
+        conf.env.LIB_OS = ['jpeg', 'X11', 'm',
+                           'xml2', 'GLU', 'GL', 'pthread',
+                           'glfw', 'GLEW', 
+                           'OpenNI2', 'fltk', 'fltk_images',
+                           'opencv_core', 'opencv_highgui', 
+                           'opencv_calib3d', 'opencv_imgproc', 
+                           'opencv_imgcodecs', 'opencv_videoio', 
+                           'opencv_aruco', 'opencv_features2d',
+                           'assimp', 'portaudio']
+        conf.env.LIBPATH_OS = ['/usr/local/lib/']
+        conf.env.DEFINES_OS  = ['POSIX=1','GL42=1', 'LINUX=1']
+   
+    #release specific
+    conf.env.CXXFLAGS = ['-O3', '-Wall', '-std=c++2a'] 
+    conf.env.DEFINES  = ['DEBUG(x)=//x']
+
+    #debug specific
+    conf.setenv('debug', env=conf.env.derive())
+    conf.env.CXXFLAGS = ['-g', '-Wall', '-std=c++2a']
+    conf.env.DEFINES  = ['DEBUG(x)=std::cout<< x <<std::endl;']
+
+def build(bld):
+    macApp = False
+    if sys.platform == 'win32' or sys.platform == 'msys' :
+        bld.objects(
+            source  = bld.path.ant_glob('src/osc/oscPack/ip/win32/*.cpp')
+                      +bld.path.ant_glob('src/osc/oscPack/ip/*.cpp')
+                      +bld.path.ant_glob('src/osc/oscPack/osc/*.cpp'),
+            use     = ['OS'],
+            target  = 'oscpack')
+    else : 
+        bld.objects(
+            source  = bld.path.ant_glob('src/osc/oscPack/ip/posix/*.cpp')
+                      +bld.path.ant_glob('src/osc/oscPack/ip/*.cpp')
+                      +bld.path.ant_glob('src/osc/oscPack/osc/*.cpp'),
+            use     = ['OS'],
+            target  = 'oscpack')
+
+    if sys.platform == 'darwin': 
+        installPath = '/opt/bin/'
+        macApp = 'True'
+
+    bld.program(
+        source       = bld.path.ant_glob('src/gui/*.cpp')
+                       + bld.path.ant_glob('src/modules/*.cpp')
+                       + bld.path.ant_glob('src/geoms/*.cpp')
+                       + bld.path.ant_glob('src/osc/*.cpp')
+                       + bld.path.ant_glob('src/audio/*.cpp')
+                       + bld.path.ant_glob('src/*.cpp'),
+        use          = ['OS','ringbuf','oscpack'],
+        target       = 'revil'+bld.variant,
+        vnum         = '0.0.1',
+        mac_app      = macApp,
+        mac_plist     = 'data/Info.plist',
+        mac_resources = 'data/revil.icns',
+    )
+
+    bld.program(
+        source="src/utils/create_marker.cpp",
+        use="OS",
+        target="revil_create_marker")
+
+    bld.install_files('${PREFIX}/share/applications', 
+                       ['data/revil.desktop'])
+    bld.install_files('${PREFIX}/share/mime/packages', 
+                       ['data/revil.xml'])
+    bld.install_files('${PREFIX}/share/icons', 
+                   ['data/revil.png'])
+
+from waflib.Build import BuildContext, CleanContext
+class debug(BuildContext): 
+    cmd = 'debug'
+    variant = 'debug' 
+
-- 
GitLab