/**
\page tutorial-panda3d Rendering a 3D scene with Panda3D
\tableofcontents

\section tutorial-panda3d-intro 1. Introduction

In the context of providing a render-based tracker, this tutorial introduces a new, easy to use renderer based on
Panda3D.

This renderer can output:
- A color image, with support for textures and lighting
- Depth image
- Normal maps
  - In world space
  - In camera space

It only supports camera models with no distortion.

It is also possible to compute camera clipping values, depending on the pose of an object in the camera frame.
This ensures that the depth buffer is as accurate as possible when considering this object.

Below is a set of renders for a textured cube object.
\image html img-cube-rendering-panda3d.jpg

Multi-output rendering is performed via the vpPanda3DRendererSet class, which duplicates the scene across multiple
renders and synchronizes changes to objects and the camera. Each Sub renderer implements a specific type of render:
geometric (vpPanda3DGeometryRenderer) or color-based (vpPanda3DRGBRenderer) etc. They all inherit from
vpPanda3DBaseRenderer, which implements basic functions for a panda renderer.

\section tutorial-panda3d-install 2. Panda3D installation
\subsection tutorial-panda3d-install-ubuntu 2.1 Installation on Ubuntu

- It is recommended to install the assimp package before installing Panda3D. This will allow you to load .obj files,
  which is a common and easily exportable format.
  Without it, you will be restricted to .bam files, which is a panda specific format. To convert to a .bam file,
  see \ref tutorial-panda3d-file-conversion.

  To install assimp, run:
  \code{.sh}
  $ sudo apt install libassimp-dev
  \endcode

- There are three different ways to install Panda3D.
  1. The easiest way is to download an installer available for Ubuntu browsing the
     [download](https://www.panda3d.org/download/) page. At the time this tutorial was written, the last Panda3D
     release was 1.10.15 version. Once downloaded you can install Panda with something similar to:
      \code{.sh}
      $ sudo apt install ./Downloads/panda3d1.10_1.10.15~noble_amd64.deb
      \endcode
  2. The second way is to install Panda3D from source using `makepanda.py`:
      \code{.sh}
      $ sudo apt install python3-pip
      $ mkdir -p $VISP_WS/3rdparty/panda3d
      $ cd $VISP_WS/3rdparty/panda3d
      $ git clone https://github.com/panda3d/panda3d
      $ cd panda3d
      $ python3 makepanda/makepanda.py --everything --installer --no-egl --no-gles --no-gles2 --no-opencv --threads $(nproc)
      \endcode
      At this point you can either:
      1. install the produced Debian package (recommended) with:
        \code{.sh}
        $ sudo dpkg -i panda3d1.11_1.11.0_amd64.deb
        \endcode
      2. use the Panda3D libraries located in the `built` folder without installing the Debian package
        `panda3d1.11_1.11.0_amd64.deb`, but in that case you need to set `LD_LIBRARY_PATH` environment var:
        \code{.sh}
        $ export LD_LIBRARY_PATH=$VISP_WS/3rdparty/panda3d/panda3d/built/lib:$LD_LIBRARY_PATH
        \endcode
        Without setting `LD_LIBRARY_PATH` you may experience the following error when running a binary that uses
        Panda3D capabilities:
        \code{.sh}
        $ ./tutorial-panda3d-renderer
        ./tutorial-panda3d-renderer: error while loading shared libraries: libp3dtoolconfig.so.1.11: cannot open shared object file: No such file or directory
        \endcode
  3. The other way is to install Panda3D from source using `cmake`:
      \code{.sh}
      $ mkdir -p $VISP_WS/3rdparty/panda3d
      $ cd $VISP_WS/3rdparty/panda3d
      $ git clone https://github.com/panda3d/panda3d
      $ cd panda3d
      \endcode
      At this point you need to patch Panda3D source code to ensure Panda3D is build with `-frtti` compiler flag as
      described in \ref tutorial-panda3d-issue-typeinfo section. This could be done by modifying
      `dtool/CompilerFlags.cmake` file replacing:
      \code{.sh}
      add_compile_options(
        "$<${cxx_rtti_property}:${cxx_rtti_on}>"
        "$<$<NOT:${cxx_rtti_property}>:${cxx_rtti_off}>")
      \endcode
      with:
      \code{.sh}
      add_compile_options(
        "$<${cxx_rtti_property}:${cxx_rtti_on}>"
        "$<$<NOT:${cxx_rtti_property}>:${cxx_rtti_on}>")
      \endcode
      Then build and install Panda3D
      \code{.sh}
      $ mkdir build && cd build
      $ cmake .. -DCMAKE_BUILD_TYPE=Release -DHAVE_AUDIO=OFF
      $ make -j$(nproc)
      $ sudo make install
      \endcode
      By default, Panda3D is installed in `/usr/local/`. ViSP is then able to detect Panda3D by using
      `/usr/local/lib/cmake/Panda3D/Panda3DConfig.cmake` file.

- Depending on how you installed Panda3D, building ViSP may differ:
  1. If you install Panda3D using a `.deb` file as described in 1. or 2.a sections, you may notice that there is nothing
    specific to do, just run `cmake` as usual:
    \code{.sh}
    $ cd $VISP_WS/visp-build
    $ cmake ../visp
    $ make -j$(nproc)
    \endcode
  2. If you prefer rather use Panda3D build libraries as described in 2.a section. without installing the `.deb`
    package you can either:
    1. set `Panda3D_DIR` cmake var to the Panda3D cloned folder:
      \code{.sh}
      $ cd $VISP_WS/visp-build
      $ cmake ../visp -DPanda3D_DIR=$VISP_WS/3rdparty/panda3d/panda3d
      $ make -j$(nproc)
      \endcode
    2. or set `Panda3D_DIR` environment variable:
      \code{.sh}
      $ export Panda3D_DIR=$VISP_WS/3rdparty/panda3d/panda3d
      $ cd $VISP_WS/visp-build
      $ cmake ../visp
      $ make -j$(nproc)
      \endcode
  3. If you build Panda from source using `cmake`, just run `cmake` as usual:
      \code{.sh}
      $ cd $VISP_WS/visp-build
      $ cmake ../visp
      $ make -j$(nproc)
      \endcode

\subsection tutorial-panda3d-install-macos 2.2 Installation on macOS

There are three different ways to install Panda3D.

1. Installers are available for macOS by browsing the [download](https://www.panda3d.org/download/) page.
\note For the latest Panda3D 1.10.15 SDK, there is an `Installer for macOS X 10.9+` that is only compatible with
  the `x86_64` architecture. If you are using a Mac M1 or M2, there is no Panda3D SDK available yet for `arm64`
  architecture. The solution is to build Panda3D from source.

2. Hereafter you will find the instructions to build Panda3D from source on macOS with `makepanda.py`.

  - It is recommended to install the assimp package before installing Panda3D. This will allow you to load `.obj` files,
    which is a common and easily exportable format.
    Without it, you will be restricted to `.bam` files, which is a panda specific format. To convert to a `.bam` file,
    see \ref tutorial-panda3d-file-conversion.
    To install assimp, run:
    \code{.sh}
    $ brew install assimp
    \endcode

  - On macOS, you will need to download a set of precompiled third-party packages in order to compile Panda3D.
    Navigate to Panda3D [download page](https://www.panda3d.org/download/), select the lastest SDK
    (in our case SDK 1.10.15), and under `</> Source Code` section, download
    [Thirdparty tools for macOS](https://www.panda3d.org/download/panda3d-1.10.15/panda3d-1.10.15-tools-mac.tar.gz)
    (in our case `panda3d-1.10.15-tools-mac.tar.gz`).
  - Extract third-party tools for macOS from downloaded archive
    \code{.sh}
    $ cd ~/Downloads
    $ tar xvzf panda3d-1.10.15-tools-mac.tar.gz
    \endcode
  - Once done clone Panda3D:
    \code{.sh}
    $ mkdir -p $VISP_WS/3rdparty/panda3d
    $ cd $VISP_WS/3rdparty/panda3d
    $ git clone https://github.com/panda3d/panda3d
    $ cd panda3d
    \endcode
  - Move the downloaded third-party tools in Panda3D source code folder
    \code{.sh}
    $ mv ~/Downloads/panda3d-1.10.15/thirdparty .
    \endcode
  - Build Panda3D from source
    \code{.sh}
    $ python3 makepanda/makepanda.py --everything --installer --no-opencv --no-python --threads $(sysctl -n hw.logicalcpu)
    ...
    created: $VISP_WS/3rdparty/panda3d/panda3d/Panda3D-1.11.0.dmg
    \endcode
    If you encounter the following issue \ref tutorial-panda3d-issue-MacOSX-sdk-not-found, see the corresponding section.

- At this point you can either
  1. install the produced `Panda3D-1.11.0.dmg` file (recommended) just by double clicking on it. In the
    installer window, don't forget to enable the `C++ Header Files` check box before pressing the installation button.
    After that you have to set `DYLIB_LIBRARY_PATH` environment var:
    \code{.sh}
    $ export DYLD_LIBRARY_PATH=/Library/Developer/Panda3D/lib:$DYLD_LIBRARY_PATH
    \endcode

  2. or use the Panda3D libraries located in the `built` folder without installing `.dmg` file, but in that case you
    need to set `DYLIB_LIBRARY_PATH` environment var:
    \code{.sh}
    $ export DYLD_LIBRARY_PATH=$VISP_WS/3rdparty/panda3d/panda3d/built/lib:$DYLD_LIBRARY_PATH
    \endcode
    Without setting `DYLD_LIBRARY_PATH` you may experience the following error when running a binary that uses
    Panda3D capabilities:
    \code{.sh}
    $ ./tutorial-panda3d-renderer
    dyld[257]: Library not loaded: @loader_path/../lib/libpanda.1.11.dylib
    \endcode

- Now to build ViSP with Panda3D support when `.dmg` file `Panda3D-1.11.0.dmg` is installed, you can just
  run cmake as usual. Note that PCL is not compatible with Panda3D, that's why we disable here PCL usage
  (see \ref tutorial-panda3d-issue-segfault-macOS).
    \code{.sh}
    $ cd $VISP_WS/visp-build
    $ cmake ../visp -DUSE_PCL=OFF
    $ make -j$(sysctl -n hw.logicalcpu)
    \endcode

- There is also the possibility to build ViSP with Panda3D support without installing the `.dmg` file
  - By setting `Panda3D_DIR` cmake var to the Panda3D cloned folder
    \code{.sh}
    $ cd $VISP_WS/visp-build
    $ cmake ../visp -DUSE_PCL=OFF -DPanda3D_DIR=$VISP_WS/3rdparty/panda3d/panda3d
    $ make -j$(sysctl -n hw.logicalcpu)
    \endcode

  - Or by setting `Panda3D_DIR` environment variable
    \code{.sh}
    $ export Panda3D_DIR=$VISP_WS/3rdparty/panda3d/panda3d
    $ cd $VISP_WS/visp-build
    $ cmake ../visp -DUSE_PCL=OFF
    $ make -j$(sysctl -n hw.logicalcpu)
    \endcode

\subsection tutorial-panda3d-install-windows 2.3 Installation on Windows

- Installers are available for Windows browsing the [download](https://www.panda3d.org/download/) page.

\section tutorial-panda3d-file-conversion 3. Converting a mesh to Panda's file format

If you did not install assimp before installing Panda, you are fairly restricted in what mesh format you can load with
Panda.

Panda's recommended format is .bam, a binary format specific to the engine itself.
If you have Python, you can easily convert your model to a .bam file by doing the following:

1. Installing the panda3D-gltf package: `pip install panda3d-gltf`
2. From your favorite 3D modelling software export your model to GLTF (available in blender)
3. Running the converter tool:
   \code{.sh}
    $ gltf2bam source.gltf output.bam
   \endcode
4. If you encounter issues, check the tool's settings with `gltf2bam -h`

\section tutorial-panda3d-usage 4. Using Panda3D for rendering

An example that shows how to exploit Panda3D in ViSP to render a color image with support for textures and lighting, a
depth image, normals in object space and in camera space is given in tutorial-panda3d-renderer.cpp.

To start rendering, we first instanciate a vpPanda3DRendererSet. This object allows to render multiple modalities
(color, depth, etc.) in a single pass.
To add different rendering modalities, we will use subclasses that will be registered to the renderer set.
Internally, each sub renderer has its own scene: the renderer set synchronizes everything when the state changes
(i.e, an object is added, an object is moved or the camera parameters change.)

A panda3D renderer should be instanciated with a vpPanda3DRenderParameters object. This object defines:
- The camera intrinsics (see vpCameraParameters): As of now, Only parameters for a distortion free model are supported
- The image resolution
- The near and far clipping plane values. Object parts that are too close (less than the near clipping value) or too
  far (greater than the far clipping value) will not be rendered.

The creation of the renderer set can be found below
\snippet tutorial-panda3d-renderer.cpp Renderer set

To actually render color, normals, etc., we need to define subrenderers:
\snippet tutorial-panda3d-renderer.cpp Subrenderers init

The different subrenderers are:

- vpPanda3DGeometryRenderer instances allow to retrieve 3D information about the object: these are the surface normals
  in the object or camera frame, as well as the depth information.
- vpPanda3DRGBRenderer objects perform the traditional color rendering. Lighting interaction can be disable, as is the
  case for the second renderer (diffuse only).
- Post processing renderers, such as vpPanda3DLuminanceFilter, vpPanda3DCanny, operate on the output image of another
  renderer. They can be used to further process the output data and can be chained together. In this case, the chain
  vpPanda3DLuminanceFilter -> vpPanda3DGaussianBlur -> vpPanda3DCanny will perform a canny edge detection (without
  hysteresis) on a blurred, grayscale image.

For these subrenderers to actually be useful, they should be added to the main renderer:
\snippet tutorial-panda3d-renderer.cpp Adding subrenderers

\warning Once they have been added, a call to vpPanda3DBaseRenderer::initFramework() should be performed. Otherwise,
no rendering will be performed and objects will not be loaded.

Here you will find the code used to configure the scene:
\snippet tutorial-panda3d-renderer.cpp Scene configuration

We start by loading the object to render with vpPanda3DBaseRenderer::loadObject, followed by v
pPanda3DBaseRenderer::addNodeToScene. For the Color-based renderer, we add lights to shade our object.
Different light types are supported, reusing the available Panda3D features.

Once the scene is setup, we can start rendering. This will be performed in a loop.

The first step shown is the following:
\snippet tutorial-panda3d-renderer.cpp Updating render parameters

Each frame, we compute the values of the clipping planes, and update the rendering properties. This will ensure that
the target object is visible. Depending on your use case, this may not be necessary.

Once this is done, we can call upon Panda3D to render the object with
\snippet tutorial-panda3d-renderer.cpp Render frame

\note Note that under the hood, all subrenderers rely on the same Panda3D "framework": calling renderFrame on one will
call it for the others.

To use the renders, we must convert them to ViSP images.
To do so, each subrenderer defines its own *getRender* method, that will perform the conversion from a panda texture
to the relevant ViSP data type.

For each render type, we start by getting the correct renderer via the vpPanda3DRendererSet::getRenderer, then call
its *getRender* method.
\snippet tutorial-panda3d-renderer.cpp Fetch render

Now that we have the retrieved the images, we can display them. To do so, we leverage utility functions defined
beforehand (see the full code for more information). This may be required in cases where the data cannot be directly
displayed. For instance, normals are encoded as 3 32-bit floats, but displays require colors to be represented as 8-bit
unsigned characters. The same goes for the depth render, which is mapped back to the 0-255 range, although its value
unbound.
\snippet tutorial-panda3d-renderer.cpp Display

Finally, we use the snippet below to move the object, updating the scene.
To have a constant velocity, we multiply the displacement by the time that has elapsed between the frame's start and end.
\snippet tutorial-panda3d-renderer.cpp Move object

\section tutorial-panda3d-full-code 5. Tutorial full code

The full code of tutorial-panda3d-renderer.cpp is given below.
\include tutorial-panda3d-renderer.cpp

\section tutorial-panda3d-run 6. Running the tutorial

- Once ViSP is built, you may run the tutorial by:
  \code{.sh}
  $ cd $VISP_WS/visp-build
  $ ./tutorial/ar/tutorial-panda3d-renderer
  \endcode
  It downloads the object located by default in `tutorial/ar/data/suzanne.bam` file.
- You should see something similar to the following video
\htmlonly
<p align="center"><iframe width="560" height="315" src="https://www.youtube.com/embed/oqRuPwzXlD4?si=eYYta_eGWN3AbR51" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
\endhtmlonly

\section tutorial-panda3d-issue 7. Known issues
\subsection tutorial-panda3d-issue-library-macOS 7.1 Library not loaded: libpanda.1.11.dylib

This error occurs on macOS.

\code{.sh}
% cd $VISP_WS/visp-build/tutorial/ar/
% ./tutorial-panda3d-renderer
dyld[1795]: Library not loaded: @loader_path/../lib/libpanda.1.11.dylib
  Referenced from: <0D61FFE0-73FA-3053-8D8D-8912BFF16E36> /Users/fspindle/soft/visp/visp_ws/test-pr/visp-SamFlt/visp-build/tutorial/ar/tutorial-panda3d-renderer
  Reason: tried: '/Users/fspindle/soft/visp/visp_ws/test-pr/visp-SamFlt/visp-build/tutorial/ar/../lib/libpanda.1.11.dylib' (no such file)
zsh: abort      ./tutorial-panda3d-renderer
\endcode

It occurs when you didn't follow carefully the instructions mentionned in \ref tutorial-panda3d-install-macos section.

A quick fix is to add the path to the library in `DYLD_LIBRARY_PATH` env var:
\code{.sh}
$ export DYLD_LIBRARY_PATH=/Library/Developer/Panda3D/lib:$DYLD_LIBRARY_PATH
\endcode

\subsection tutorial-panda3d-issue-segfault-macOS 7.2 Segfault: :framework(error): Unable to create window

This error occurs on macOS.

\code{.sh}
% cd $VISP_WS/visp-build/tutorial/ar/
% ./tutorial-panda3d-renderer
Initializing Panda3D rendering framework
Known pipe types:
  CocoaGLGraphicsPipe
(all display modules loaded.)
:framework(error): Unable to create window.
zsh: segmentation fault  ./tutorial-panda3d-renderer
\endcode
This issue is probably due to `EIGEN_MAX_ALIGN_BYTES` and `HAVE_PNG` macro redefinition that occurs when building
ViSP with Panda3D support:
\code{.sh}
$ cd visp-build
$ make
...
[100%] Building CXX object tutorial/ar/CMakeFiles/tutorial-panda3d-renderer.dir/tutorial-panda3d-renderer.cpp.o
In file included from $VISP_WS/visp/tutorial/ar/tutorial-panda3d-renderer.cpp:17:
In file included from $VISP_WS/visp/modules/ar/include/visp3/ar/vpPanda3DRGBRenderer.h:39:
In file included from $VISP_WS/visp/modules/ar/include/visp3/ar/vpPanda3DBaseRenderer.h:42:
In file included from $VISP_WS/3rdparty/panda3d/panda3d/built/include/pandaFramework.h:17:
In file included from $VISP_WS/3rdparty/panda3d/panda3d/built/include/pandabase.h:21:
In file included from $VISP_WS/3rdparty/panda3d/panda3d/built/include/dtoolbase.h:22:
$VISP_WS/3rdparty/panda3d/panda3d/built/include/dtool_config.h:40:9: warning: 'HAVE_PNG' macro redefined [-Wmacro-redefined]
#define HAVE_PNG 1
        ^
/opt/homebrew/include/pcl-1.14/pcl/pcl_config.h:53:9: note: previous definition is here
#define HAVE_PNG
    ^
In file included from $VISP_WS/visp/tutorial/ar/tutorial-panda3d-renderer.cpp:17:
In file included from $VISP_WS/visp/modules/ar/include/visp3/ar/vpPanda3DRGBRenderer.h:39:
In file included from $VISP_WS/visp/modules/ar/include/visp3/ar/vpPanda3DBaseRenderer.h:42:
In file included from $VISP_WS/3rdparty/panda3d/panda3d/built/include/pandaFramework.h:17:
In file included from $VISP_WS/3rdparty/panda3d/panda3d/built/include/pandabase.h:21:
In file included from $VISP_WS/3rdparty/panda3d/panda3d/built/include/dtoolbase.h:22:
$VISP_WS/3rdparty/panda3d/panda3d/built/include/dtool_config.h:64:9: warning: 'HAVE_ZLIB' macro redefined [-Wmacro-redefined]
#define HAVE_ZLIB 1
        ^
/opt/homebrew/include/pcl-1.14/pcl/pcl_config.h:55:9: note: previous definition is here
#define HAVE_ZLIB
        ^
In file included from $VISP_WS/visp/tutorial/ar/tutorial-panda3d-renderer.cpp:17:
In file included from $VISP_WS/visp/modules/ar/include/visp3/ar/vpPanda3DRGBRenderer.h:39:
In file included from $VISP_WS/visp/modules/ar/include/visp3/ar/vpPanda3DBaseRenderer.h:42:
In file included from $VISP_WS/3rdparty/panda3d/panda3d/built/include/pandaFramework.h:17:
In file included from $VISP_WS/3rdparty/panda3d/panda3d/built/include/pandabase.h:21:
$VISP_WS/3rdparty/panda3d/panda3d/built/include/dtoolbase.h:432:9: warning: 'EIGEN_MAX_ALIGN_BYTES' macro redefined [-Wmacro-redefined]
#define EIGEN_MAX_ALIGN_BYTES MEMORY_HOOK_ALIGNMENT
        ^
/opt/homebrew/include/eigen3/Eigen/src/Core/util/ConfigureVectorization.h:175:11: note: previous definition is here
  #define EIGEN_MAX_ALIGN_BYTES EIGEN_IDEAL_MAX_ALIGN_BYTES
          ^
3 warnings generated.
[100%] Linking CXX executable tutorial-panda3d-renderer
[100%] Built target tutorial-panda3d-renderer
\endcode
The work around consists in disabling `PCL` usage during ViSP configuration
\code{.sh}
$ cd $VISP_WS/visp-build
$ cmake ../visp -DUSE_PCL=OFF
$ make -j$(sysctl -n hw.logicalcpu)
\endcode

\subsection tutorial-panda3d-issue-MacOSX-sdk-not-found 7.3 Couldn't find any suitable MacOSX SDK!

The following error may occur when building Panda3D from source on macOS Sequoia 15.3.1.
\code{.sh}
% python3 makepanda/makepanda.py --everything --installer --no-opencv --no-python --threads $(sysctl -n hw.logicalcpu)
Version: 1.11.0
Platform: macosx-11.0-arm64
Storing dependency cache.
Elapsed Time: 0 sec
Couldn't find any suitable MacOSX SDK!
\endcode
The installer calls `makepanda/makepandacore.py` and enters in `SdkLocateMacOSX()` function to try to find the latest
MacOSX SDK in one of the following folders:
- `/Library/Developer/CommandLineTools/SDKs/`
- `/Developer/SDKs/`
- `/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/`

Inside `SdkLocateMacOSX()` you will find a list of expected SDK versions, like:
\code{.sh}
sdk_versions += ["14.0", "13.3", "13.1", "13.0", "12.3", "11.3", "11.1", "11.0"]
\endcode
while you may have the following SDK versions:
\code{.sh}
$ ls /Library/Developer/CommandLineTools/SDKs/
MacOSX.sdk	MacOSX14.5.sdk	MacOSX14.sdk	MacOSX15.2.sdk	MacOSX15.sdk
\endcode
In our case the fix consists in adding 15.2 SDK version to the list of expected SDKs.
\code{.sh}
sdk_versions += ["15.2", "14.0", "13.3", "13.1", "13.0", "12.3", "11.3", "11.1", "11.0"]
\endcode
Now you should be able to build Panda3D with:
\code{.sh}
% python3 makepanda/makepanda.py --everything --installer --no-opencv --no-python --threads $(sysctl -n hw.logicalcpu)
...
created: $VISP_WS/3rdparty/panda3d/panda3d/Panda3D-1.11.0.dmg
\endcode

\subsection tutorial-panda3d-issue-typeinfo 7.4 Link issue: undefined reference to typeinfo

The following linking issue can occur when you mix `-fno-rtti` and `-frtti` compiler flags.
\code{.sh}
[100%] Linking CXX executable catchPanda
/usr/bin/ld: ../../lib/libvisp_ar.so.3.6.1: undefined reference to `typeinfo for GraphicsOutput'
/usr/bin/ld: ../../lib/libvisp_ar.so.3.6.1: undefined reference to `typeinfo for GraphicsBuffer'
/usr/bin/ld: ../../lib/libvisp_ar.so.3.6.1: undefined reference to `typeinfo for TypedObject'
collect2: error: ld returned 1 exit status
\endcode

ViSP needs to be built with `-frtti` to avoid build issues in vpIoTools.cpp, while
Panda3D enables `-frtti` when built in `Debug` mode and enables `-fno-rtti` otherwise.
We cannot have one library built with `-frtti` and another one with the `-fno-rtti` flag.
The solution here is to patch Panda3D's source code to always enable the `-frtti` flag.
This can be achieved by modifying the `dtool/CompilerFlags.cmake` file:
\code{.sh}
diff --git a/dtool/CompilerFlags.cmake b/dtool/CompilerFlags.cmake
index 31d96279e3..4321872323 100644
--- a/dtool/CompilerFlags.cmake
+++ b/dtool/CompilerFlags.cmake
@@ -215,7 +215,7 @@ if(NOT ANDROID)
 endif()
 add_compile_options(
   "$<${cxx_rtti_property}:${cxx_rtti_on}>"
-  "$<$<NOT:${cxx_rtti_property}>:${cxx_rtti_off}>")
+  "$<$<NOT:${cxx_rtti_property}>:${cxx_rtti_on}>")
 set_property(DIRECTORY "${PROJECT_SOURCE_DIR}" APPEND PROPERTY
   COMPILE_DEFINITIONS "$<${cxx_rtti_property}:HAVE_RTTI>")
\endcode

*/
