This commit is contained in:
guanjunwu 2023-09-24 19:51:57 +08:00
commit 8bf73f413d
2107 changed files with 515597 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
*.pyc
.vscode
output
build
diff_rasterization/diff_rast.egg-info
diff_rasterization/dist
tensorboard_3d
screenshots
data

9
.gitmodules vendored Normal file
View File

@ -0,0 +1,9 @@
[submodule "submodules/simple-knn"]
path = submodules/simple-knn
url = https://gitlab.inria.fr/bkerbl/simple-knn.git
[submodule "submodules/diff-gaussian-rasterization"]
path = submodules/diff-gaussian-rasterization
url = https://github.com/graphdeco-inria/diff-gaussian-rasterization
[submodule "SIBR_viewers"]
path = SIBR_viewers
url = https://gitlab.inria.fr/sibr/sibr_core

83
LICENSE.md Normal file
View File

@ -0,0 +1,83 @@
Gaussian-Splatting License
===========================
**Inria** and **the Max Planck Institut for Informatik (MPII)** hold all the ownership rights on the *Software* named **gaussian-splatting**.
The *Software* is in the process of being registered with the Agence pour la Protection des
Programmes (APP).
The *Software* is still being developed by the *Licensor*.
*Licensor*'s goal is to allow the research community to use, test and evaluate
the *Software*.
## 1. Definitions
*Licensee* means any person or entity that uses the *Software* and distributes
its *Work*.
*Licensor* means the owners of the *Software*, i.e Inria and MPII
*Software* means the original work of authorship made available under this
License ie gaussian-splatting.
*Work* means the *Software* and any additions to or derivative works of the
*Software* that are made available under this License.
## 2. Purpose
This license is intended to define the rights granted to the *Licensee* by
Licensors under the *Software*.
## 3. Rights granted
For the above reasons Licensors have decided to distribute the *Software*.
Licensors grant non-exclusive rights to use the *Software* for research purposes
to research users (both academic and industrial), free of charge, without right
to sublicense.. The *Software* may be used "non-commercially", i.e., for research
and/or evaluation purposes only.
Subject to the terms and conditions of this License, you are granted a
non-exclusive, royalty-free, license to reproduce, prepare derivative works of,
publicly display, publicly perform and distribute its *Work* and any resulting
derivative works in any form.
## 4. Limitations
**4.1 Redistribution.** You may reproduce or distribute the *Work* only if (a) you do
so under this License, (b) you include a complete copy of this License with
your distribution, and (c) you retain without modification any copyright,
patent, trademark, or attribution notices that are present in the *Work*.
**4.2 Derivative Works.** You may specify that additional or different terms apply
to the use, reproduction, and distribution of your derivative works of the *Work*
("Your Terms") only if (a) Your Terms provide that the use limitation in
Section 2 applies to your derivative works, and (b) you identify the specific
derivative works that are subject to Your Terms. Notwithstanding Your Terms,
this License (including the redistribution requirements in Section 3.1) will
continue to apply to the *Work* itself.
**4.3** Any other use without of prior consent of Licensors is prohibited. Research
users explicitly acknowledge having received from Licensors all information
allowing to appreciate the adequacy between of the *Software* and their needs and
to undertake all necessary precautions for its execution and use.
**4.4** The *Software* is provided both as a compiled library file and as source
code. In case of using the *Software* for a publication or other results obtained
through the use of the *Software*, users are strongly encouraged to cite the
corresponding publications as explained in the documentation of the *Software*.
## 5. Disclaimer
THE USER CANNOT USE, EXPLOIT OR DISTRIBUTE THE *SOFTWARE* FOR COMMERCIAL PURPOSES
WITHOUT PRIOR AND EXPLICIT CONSENT OF LICENSORS. YOU MUST CONTACT INRIA FOR ANY
UNAUTHORIZED USE: stip-sophia.transfert@inria.fr . ANY SUCH ACTION WILL
CONSTITUTE A FORGERY. THIS *SOFTWARE* IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES
OF ANY NATURE AND ANY EXPRESS OR IMPLIED WARRANTIES, WITH REGARDS TO COMMERCIAL
USE, PROFESSIONNAL USE, LEGAL OR NOT, OR OTHER, OR COMMERCIALISATION OR
ADAPTATION. UNLESS EXPLICITLY PROVIDED BY LAW, IN NO EVENT, SHALL INRIA OR 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 FROM, OUT OF OR
IN CONNECTION WITH THE *SOFTWARE* OR THE USE OR OTHER DEALINGS IN THE *SOFTWARE*.

488
README.md Normal file
View File

@ -0,0 +1,488 @@
# 3D Gaussian Splatting for Real-Time Radiance Field Rendering
Bernhard Kerbl*, Georgios Kopanas*, Thomas Leimkühler, George Drettakis (* indicates equal contribution)<br>
| [Webpage](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/) | [Full Paper](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/3d_gaussian_splatting_high.pdf) |
[Video](https://youtu.be/T_kXY43VZnk) | [Other GRAPHDECO Publications](http://www-sop.inria.fr/reves/publis/gdindex.php) | [FUNGRAPH project page](https://fungraph.inria.fr) |
| [T&T+DB COLMAP (650MB)](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/datasets/input/tandt_db.zip) | [Pre-trained Models (14 GB)](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/datasets/pretrained/models.zip) | [Viewers for Windows (60MB)](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/binaries/viewers.zip) | [Evaluation Images (7 GB)](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/evaluation/images.zip) | <br>
![Teaser image](assets/teaser.png)
This repository contains the official authors implementation associated with the paper "3D Gaussian Splatting for Real-Time Radiance Field Rendering", which can be found [here](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/). We further provide the reference images used to create the error metrics reported in the paper, as well as recently created, pre-trained models.
<a href="https://www.inria.fr/"><img height="100" src="assets/logo_inria.png"> </a>
<a href="https://univ-cotedazur.eu/"><img height="100" src="assets/logo_uca.png"> </a>
<a href="https://www.mpi-inf.mpg.de"><img height="100" src="assets/logo_mpi.png"> </a>
<a href="https://team.inria.fr/graphdeco/"> <img style="width:100%;" src="assets/logo_graphdeco.png"></a>
Abstract: *Radiance Field methods have recently revolutionized novel-view synthesis of scenes captured with multiple photos or videos. However, achieving high visual quality still requires neural networks that are costly to train and render, while recent faster methods inevitably trade off speed for quality. For unbounded and complete scenes (rather than isolated objects) and 1080p resolution rendering, no current method can achieve real-time display rates. We introduce three key elements that allow us to achieve state-of-the-art visual quality while maintaining competitive training times and importantly allow high-quality real-time (≥ 30 fps) novel-view synthesis at 1080p resolution. First, starting from sparse points produced during camera calibration, we represent the scene with 3D Gaussians that preserve desirable properties of continuous volumetric radiance fields for scene optimization while avoiding unnecessary computation in empty space; Second, we perform interleaved optimization/density control of the 3D Gaussians, notably optimizing anisotropic covariance to achieve an accurate representation of the scene; Third, we develop a fast visibility-aware rendering algorithm that supports anisotropic splatting and both accelerates training and allows realtime rendering. We demonstrate state-of-the-art visual quality and real-time rendering on several established datasets.*
<section class="section" id="BibTeX">
<div class="container is-max-desktop content">
<h2 class="title">BibTeX</h2>
<pre><code>@Article{kerbl3Dgaussians,
author = {Kerbl, Bernhard and Kopanas, Georgios and Leimk{\"u}hler, Thomas and Drettakis, George},
title = {3D Gaussian Splatting for Real-Time Radiance Field Rendering},
journal = {ACM Transactions on Graphics},
number = {4},
volume = {42},
month = {July},
year = {2023},
url = {https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/}
}</code></pre>
</div>
</section>
## Funding and Acknowledgments
This research was funded by the ERC Advanced grant FUNGRAPH No 788065. The authors are grateful to Adobe for generous donations, the OPAL infrastructure from Université Côte dAzur and for the HPC resources from GENCIIDRIS (Grant 2022-AD011013409). The authors thank the anonymous reviewers for their valuable feedback, P. Hedman and A. Tewari for proofreading earlier drafts also T. Müller, A. Yu and S. Fridovich-Keil for helping with the comparisons.
## Cloning the Repository
The repository contains submodules, thus please check it out with
```shell
# SSH
git clone git@github.com:graphdeco-inria/gaussian-splatting.git --recursive
```
or
```shell
# HTTPS
git clone https://github.com/graphdeco-inria/gaussian-splatting --recursive
```
## Overview
The codebase has 4 main components:
- A PyTorch-based optimizer to produce a 3D Gaussian model from SfM inputs
- A network viewer that allows to connect to and visualize the optimization process
- An OpenGL-based real-time viewer to render trained models in real-time.
- A script to help you turn your own images into optimization-ready SfM data sets
The components have different requirements w.r.t. both hardware and software. They have been tested on Windows 10 and Ubuntu Linux 22.04. Instructions for setting up and running each of them are found in the sections below.
## Optimizer
The optimizer uses PyTorch and CUDA extensions in a Python environment to produce trained models.
### Hardware Requirements
- CUDA-ready GPU with Compute Capability 7.0+
- 24 GB VRAM (to train to paper evaluation quality)
- Please see FAQ for smaller VRAM configurations
### Software Requirements
- Conda (recommended for easy setup)
- C++ Compiler for PyTorch extensions (we used Visual Studio 2019 for Windows)
- CUDA SDK 11 for PyTorch extensions (we used 11.8, **known issues with 11.6**)
- C++ Compiler and CUDA SDK must be compatible
### Setup
Our provided install method is based on Conda package and environment management:
```shell
SET DISTUTILS_USE_SDK=1 # Windows only
conda env create --file environment.yml
conda activate gaussian_splatting
```
Please note that this process assumes that you have CUDA SDK **11** installed, not **12**. For modifications, see below.
Tip: Downloading packages and creating a new environment with Conda can require a significant amount of disk space. By default, Conda will use the main system hard drive. You can avoid this by specifying a different package download location and an environment on a different drive:
```shell
conda config --add pkgs_dirs <Drive>/<pkg_path>
conda env create --file environment.yml --prefix <Drive>/<env_path>/gaussian_splatting
conda activate <Drive>/<env_path>/gaussian_splatting
```
#### Modifications
If you can afford the disk space, we recommend using our environment files for setting up a training environment identical to ours. If you want to make modifications, please note that major version changes might affect the results of our method. However, our (limited) experiments suggest that the codebase works just fine inside a more up-to-date environment (Python 3.8, PyTorch 2.0.0, CUDA 12). Make sure to create an environment where PyTorch and its CUDA runtime version match and the installed CUDA SDK has no major version difference with PyTorch's CUDA version.
### Running
To run the optimizer, simply use
```shell
python train.py -s <path to COLMAP or NeRF Synthetic dataset>
```
<details>
<summary><span style="font-weight: bold;">Command Line Arguments for train.py</span></summary>
#### --source_path / -s
Path to the source directory containing a COLMAP or Synthetic NeRF data set.
#### --model_path / -m
Path where the trained model should be stored (```output/<random>``` by default).
#### --images / -i
Alternative subdirectory for COLMAP images (```images``` by default).
#### --eval
Add this flag to use a MipNeRF360-style training/test split for evaluation.
#### --resolution / -r
Specifies resolution of the loaded images before training. If provided ```1, 2, 4``` or ```8```, uses original, 1/2, 1/4 or 1/8 resolution, respectively. For all other values, rescales the width to the given number while maintaining image aspect. **If not set and input image width exceeds 1.6K pixels, inputs are automatically rescaled to this target.**
#### --data_device
Specifies where to put the source image data, ```cuda``` by default, recommended to use ```cpu``` if training on large/high-resolution dataset, will reduce VRAM consumption, but slightly slow down training.
#### --white_background / -w
Add this flag to use white background instead of black (default), e.g., for evaluation of NeRF Synthetic dataset.
#### --sh_degree
Order of spherical harmonics to be used (no larger than 3). ```3``` by default.
#### --convert_SHs_python
Flag to make pipeline compute forward and backward of SHs with PyTorch instead of ours.
#### --convert_cov3D_python
Flag to make pipeline compute forward and backward of the 3D covariance with PyTorch instead of ours.
#### --debug
Enables debug mode if you experience erros. If the rasterizer fails, a ```dump``` file is created that you may forward to us in an issue so we can take a look.
#### --debug_from
Debugging is **slow**. You may specify an iteration (starting from 0) after which the above debugging becomes active.
#### --iterations
Number of total iterations to train for, ```30_000``` by default.
#### --ip
IP to start GUI server on, ```127.0.0.1``` by default.
#### --port
Port to use for GUI server, ```6009``` by default.
#### --test_iterations
Space-separated iterations at which the training script computes L1 and PSNR over test set, ```7000 30000``` by default.
#### --save_iterations
Space-separated iterations at which the training script saves the Gaussian model, ```7000 30000 <iterations>``` by default.
#### --checkpoint_iterations
Space-separated iterations at which to store a checkpoint for continuing later, saved in the model directory.
#### --start_checkpoint
Path to a saved checkpoint to continue training from.
#### --quiet
Flag to omit any text written to standard out pipe.
#### --feature_lr
Spherical harmonics features learning rate, ```0.0025``` by default.
#### --opacity_lr
Opacity learning rate, ```0.05``` by default.
#### --scaling_lr
Scaling learning rate, ```0.005``` by default.
#### --rotation_lr
Rotation learning rate, ```0.001``` by default.
#### --position_lr_max_steps
Number of steps (from 0) where position learning rate goes from ```initial``` to ```final```. ```30_000``` by default.
#### --position_lr_init
Initial 3D position learning rate, ```0.00016``` by default.
#### --position_lr_final
Final 3D position learning rate, ```0.0000016``` by default.
#### --position_lr_delay_mult
Position learning rate multiplier (cf. Plenoxels), ```0.01``` by default.
#### --densify_from_iter
Iteration where densification starts, ```500``` by default.
#### --densify_until_iter
Iteration where densification stops, ```15_000``` by default.
#### --densify_grad_threshold
Limit that decides if points should be densified based on 2D position gradient, ```0.0002``` by default.
#### --densification_interal
How frequently to densify, ```100``` (every 100 iterations) by default.
#### --opacity_reset_interval
How frequently to reset opacity, ```3_000``` by default.
#### --lambda_dssim
Influence of SSIM on total loss from 0 to 1, ```0.2``` by default.
#### --percent_dense
Percentage of scene extent (0--1) a point must exceed to be forcibly densified, ```0.01``` by default.
</details>
<br>
Note that similar to MipNeRF360, we target images at resolutions in the 1-1.6K pixel range. For convenience, arbitrary-size inputs can be passed and will be automatically resized if their width exceeds 1600 pixels. We recommend to keep this behavior, but you may force training to use your higher-resolution images by setting ```-r 1```.
The MipNeRF360 scenes are hosted by the paper authors [here](https://jonbarron.info/mipnerf360/). You can find our SfM data sets for Tanks&Temples and Deep Blending [here](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/datasets/input/tandt_db.zip). If you do not provide an output model directory (```-m```), trained models are written to folders with randomized unique names inside the ```output``` directory. At this point, the trained models may be viewed with the real-time viewer (see further below).
### Evaluation
By default, the trained models use all available images in the dataset. To train them while withholding a test set for evaluation, use the ```--eval``` flag. This way, you can render training/test sets and produce error metrics as follows:
```shell
python train.py -s <path to COLMAP or NeRF Synthetic dataset> --eval # Train with train/test split
python render.py -m <path to trained model> # Generate renderings
python metrics.py -m <path to trained model> # Compute error metrics on renderings
```
If you want to evaluate our [pre-trained models](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/datasets/pretrained/models.zip), you will have to download the corresponding source data sets and indicate their location to ```render.py``` with an additional ```--source_path/-s``` flag. Note: The pre-trained models were created with the release codebase. This code base has been cleaned up and includes bugfixes, hence the metrics you get from evaluating them will differ from those in the paper.
```shell
python render.py -m <path to pre-trained model> -s <path to COLMAP dataset>
python metrics.py -m <path to pre-trained model>
```
<details>
<summary><span style="font-weight: bold;">Command Line Arguments for render.py</span></summary>
#### --model_path / -m
Path to the trained model directory you want to create renderings for.
#### --skip_train
Flag to skip rendering the training set.
#### --skip_test
Flag to skip rendering the test set.
#### --quiet
Flag to omit any text written to standard out pipe.
**The below parameters will be read automatically from the model path, based on what was used for training. However, you may override them by providing them explicitly on the command line.**
#### --source_path / -s
Path to the source directory containing a COLMAP or Synthetic NeRF data set.
#### --images / -i
Alternative subdirectory for COLMAP images (```images``` by default).
#### --eval
Add this flag to use a MipNeRF360-style training/test split for evaluation.
#### --resolution / -r
Changes the resolution of the loaded images before training. If provided ```1, 2, 4``` or ```8```, uses original, 1/2, 1/4 or 1/8 resolution, respectively. For all other values, rescales the width to the given number while maintaining image aspect. ```1``` by default.
#### --white_background / -w
Add this flag to use white background instead of black (default), e.g., for evaluation of NeRF Synthetic dataset.
#### --convert_SHs_python
Flag to make pipeline render with computed SHs from PyTorch instead of ours.
#### --convert_cov3D_python
Flag to make pipeline render with computed 3D covariance from PyTorch instead of ours.
</details>
<details>
<summary><span style="font-weight: bold;">Command Line Arguments for metrics.py</span></summary>
#### --model_paths / -m
Space-separated list of model paths for which metrics should be computed.
</details>
<br>
We further provide the ```full_eval.py``` script. This script specifies the routine used in our evaluation and demonstrates the use of some additional parameters, e.g., ```--images (-i)``` to define alternative image directories within COLMAP data sets. If you have downloaded and extracted all the training data, you can run it like this:
```shell
python full_eval.py -m360 <mipnerf360 folder> -tat <tanks and temples folder> -db <deep blending folder>
```
In the current version, this process takes about 7h on our reference machine containing an A6000. If you want to do the full evaluation on our pre-trained models, you can specify their download location and skip training.
```shell
python full_eval.py -o <directory with pretrained models> --skip_training -m360 <mipnerf360 folder> -tat <tanks and temples folder> -db <deep blending folder>
```
If you want to compute the metrics on our paper's [evaluation images](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/evaluation/images.zip), you can also skip rendering. In this case it is not necessary to provide the source datasets. You can compute metrics for multiple image sets at a time.
```shell
python full_eval.py -m <directory with evaluation images>/garden ... --skip_training --skip_rendering
```
<details>
<summary><span style="font-weight: bold;">Command Line Arguments for full_eval.py</span></summary>
#### --skip_training
Flag to skip training stage.
#### --skip_rendering
Flag to skip rendering stage.
#### --skip_metrics
Flag to skip metrics calculation stage.
#### --output_path
Directory to put renderings and results in, ```./eval``` by default, set to pre-trained model location if evaluating them.
#### --mipnerf360 / -m360
Path to MipNeRF360 source datasets, required if training or rendering.
#### --tanksandtemples / -tat
Path to Tanks&Temples source datasets, required if training or rendering.
#### --deepblending / -db
Path to Deep Blending source datasets, required if training or rendering.
</details>
<br>
## Interactive Viewers
We provide two interactive viewers for our method: remote and real-time. Our viewing solutions are based on the [SIBR](https://sibr.gitlabpages.inria.fr/) framework, developed by the GRAPHDECO group for several novel-view synthesis projects.
### Hardware Requirements
- OpenGL 4.5-ready GPU and drivers (or latest MESA software)
- 4 GB VRAM recommended
- CUDA-ready GPU with Compute Capability 7.0+ (only for Real-Time Viewer)
### Software Requirements
- Visual Studio or g++, **not Clang** (we used Visual Studio 2019 for Windows)
- CUDA SDK 11 (we used 11.8)
- CMake (recent version, we used 3.24)
- 7zip (only on Windows)
### Pre-built Windows Binaries
We provide pre-built binaries for Windows [here](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/binaries/viewers.zip). We recommend using them on Windows for an efficient setup, since the building of SIBR involves several external dependencies that must be downloaded and compiled on-the-fly.
### Installation from Source
If you cloned with submodules (e.g., using ```--recursive```), the source code for the viewers is found in ```SIBR_viewers```. The network viewer runs within the SIBR framework for Image-based Rendering applications.
#### Windows
CMake should take care of your dependencies.
```shell
cd SIBR_viewers
cmake -Bbuild .
cmake --build build --target install --config RelWithDebInfo
```
You may specify a different configuration, e.g. ```Debug``` if you need more control during development.
#### Ubuntu 22.04
You will need to install a few dependencies before running the project setup.
```shell
# Dependencies
sudo apt install -y libglew-dev libassimp-dev libboost-all-dev libgtk-3-dev libopencv-dev libglfw3-dev libavdevice-dev libavcodec-dev libeigen3-dev libxxf86vm-dev libembree-dev
# Project setup
cd SIBR_viewers
cmake -Bbuild . -DCMAKE_BUILD_TYPE=Release # add -G Ninja to build faster
cmake --build build -j24 --target install
```
#### Ubuntu 20.04
Backwards compatibility with Focal Fossa is not fully tested, but building SIBR with CMake should still work after invoking
```shell
git checkout fossa_compatibility
```
### Navigation in SIBR Viewers
The SIBR interface provides several methods of navigating the scene. By default, you will be started with an FPS navigator, which you can control with ```W, A, S, D, Q, E``` for camera translation and ```I, K, J, L, U, O``` for rotation. Alternatively, you may want to use a Trackball-style navigator (select from the floating menu). You can also snap to a camera from the data set with the ```Snap to``` button or find the closest camera with ```Snap to closest```. The floating menues also allow you to change the navigation speed. You can use the ```Scaling Modifier``` to control the size of the displayed Gaussians, or show the initial point cloud.
### Running the Network Viewer
https://github.com/graphdeco-inria/gaussian-splatting/assets/40643808/90a2e4d3-cf2e-4633-b35f-bfe284e28ff7
After extracting or installing the viewers, you may run the compiled ```SIBR_remoteGaussian_app[_config]``` app in ```<SIBR install dir>/bin```, e.g.:
```shell
./<SIBR install dir>/bin/SIBR_remoteGaussian_app
```
The network viewer allows you to connect to a running training process on the same or a different machine. If you are training on the same machine and OS, no command line parameters should be required: the optimizer communicates the location of the training data to the network viewer. By default, optimizer and network viewer will try to establish a connection on **localhost** on port **6009**. You can change this behavior by providing matching ```--ip``` and ```--port``` parameters to both the optimizer and the network viewer. If for some reason the path used by the optimizer to find the training data is not reachable by the network viewer (e.g., due to them running on different (virtual) machines), you may specify an override location to the viewer by using ```-s <source path>```.
<details>
<summary><span style="font-weight: bold;">Primary Command Line Arguments for Network Viewer</span></summary>
#### --path / -s
Argument to override model's path to source dataset.
#### --ip
IP to use for connection to a running training script.
#### --port
Port to use for connection to a running training script.
#### --rendering-size
Takes two space separated numbers to define the resolution at which network rendering occurs, ```1200``` width by default.
Note that to enforce an aspect that differs from the input images, you need ```--force-aspect-ratio``` too.
#### --load_images
Flag to load source dataset images to be displayed in the top view for each camera.
</details>
<br>
### Running the Real-Time Viewer
https://github.com/graphdeco-inria/gaussian-splatting/assets/40643808/0940547f-1d82-4c2f-a616-44eabbf0f816
After extracting or installing the viewers, you may run the compiled ```SIBR_gaussianViewer_app[_config]``` app in ```<SIBR install dir>/bin```, e.g.:
```shell
./<SIBR install dir>/bin/SIBR_gaussianViewer_app -m <path to trained model>
```
It should suffice to provide the ```-m``` parameter pointing to a trained model directory. Alternatively, you can specify an override location for training input data using ```-s```. To use a specific resolution other than the auto-chosen one, specify ```--rendering-size <width> <height>```. Combine it with ```--force-aspect-ratio``` if you want the exact resolution and don't mind image distortion.
**To unlock the full frame rate, please disable V-Sync on your machine and also in the application (Menu &rarr; Display). In a multi-GPU system (e.g., laptop) your OpenGL/Display GPU should be the same as your CUDA GPU (e.g., by setting the application's GPU preference on Windows, see below) for maximum performance.**
![Teaser image](assets/select.png)
In addition to the intial point cloud and the splats, you also have the option to visualize the Gaussians by rendering them as ellipsoids from the floating menu.
SIBR has many other functionalities, please see the [documentation](https://sibr.gitlabpages.inria.fr/) for more details on the viewer, navigation options etc. There is also a Top View (available from the menu) that shows the placement of the input cameras and the original SfM point cloud; please note that Top View slows rendering when enabled. The real-time viewer also uses slightly more aggressive, fast culling, which can be toggled in the floating menu. If you ever encounter an issue that can be solved by turning fast culling off, please let us know.
<details>
<summary><span style="font-weight: bold;">Primary Command Line Arguments for Real-Time Viewer</span></summary>
#### --model-path / -m
Path to trained model.
#### --iteration
Specifies which of state to load if multiple are available. Defaults to latest available iteration.
#### --path / -s
Argument to override model's path to source dataset.
#### --rendering-size
Takes two space separated numbers to define the resolution at which real-time rendering occurs, ```1200``` width by default. Note that to enforce an aspect that differs from the input images, you need ```--force-aspect-ratio``` too.
#### --load_images
Flag to load source dataset images to be displayed in the top view for each camera.
#### --device
Index of CUDA device to use for rasterization if multiple are available, ```0``` by default.
#### --no_interop
Disables CUDA/GL interop forcibly. Use on systems that may not behave according to spec (e.g., WSL2 with MESA GL 4.5 software rendering).
</details>
<br>
## Processing your own Scenes
Our COLMAP loaders expect the following dataset structure in the source path location:
```
<location>
|---images
| |---<image 0>
| |---<image 1>
| |---...
|---sparse
|---0
|---cameras.bin
|---images.bin
|---points3D.bin
```
For rasterization, the camera models must be either a SIMPLE_PINHOLE or PINHOLE camera. We provide a converter script ```convert.py```, to extract undistorted images and SfM information from input images. Optionally, you can use ImageMagick to resize the undistorted images. This rescaling is similar to MipNeRF360, i.e., it creates images with 1/2, 1/4 and 1/8 the original resolution in corresponding folders. To use them, please first install a recent version of COLMAP (ideally CUDA-powered) and ImageMagick. Put the images you want to use in a directory ```<location>/input```.
```
<location>
|---input
|---<image 0>
|---<image 1>
|---...
```
If you have COLMAP and ImageMagick on your system path, you can simply run
```shell
python convert.py -s <location> [--resize] #If not resizing, ImageMagick is not needed
```
Alternatively, you can use the optional parameters ```--colmap_executable``` and ```--magick_executable``` to point to the respective paths. Please note that on Windows, the executable should point to the COLMAP ```.bat``` file that takes care of setting the execution environment. Once done, ```<location>``` will contain the expected COLMAP data set structure with undistorted, resized input images, in addition to your original images and some temporary (distorted) data in the directory ```distorted```.
If you have your own COLMAP dataset without undistortion (e.g., using ```OPENCV``` camera), you can try to just run the last part of the script: Put the images in ```input``` and the COLMAP info in a subdirectory ```distorted```:
```
<location>
|---input
| |---<image 0>
| |---<image 1>
| |---...
|---distorted
|---database.db
|---sparse
|---0
|---...
```
Then run
```shell
python convert.py -s <location> --skip_matching [--resize] #If not resizing, ImageMagick is not needed
```
<details>
<summary><span style="font-weight: bold;">Command Line Arguments for convert.py</span></summary>
#### --no_gpu
Flag to avoid using GPU in COLMAP.
#### --skip_matching
Flag to indicate that COLMAP info is available for images.
#### --source_path / -s
Location of the inputs.
#### --camera
Which camera model to use for the early matching steps, ```OPENCV``` by default.
#### --resize
Flag for creating resized versions of input images.
#### --colmap_executable
Path to the COLMAP executable (```.bat``` on Windows).
#### --magick_executable
Path to the ImageMagick executable.
</details>
<br>
## FAQ
- *Where do I get data sets, e.g., those referenced in ```full_eval.py```?* The MipNeRF360 data set is provided by the authors of the original paper on the project site. Note that two of the data sets cannot be openly shared and require you to consult the authors directly. For Tanks&Temples and Deep Blending, please use the download links provided at the top of the page.
- *How can I use this for a much larger dataset, like a city district?* The current method was not designed for these, but given enough memory, it should work out. However, the approach can struggle in multi-scale detail scenes (extreme close-ups, mixed with far-away shots). This is usually the case in, e.g., driving data sets (cars close up, buildings far away). For such scenes, you can lower the ```--position_lr_init```, ```--position_lr_final``` and ```--scaling_lr``` (x0.3, x0.1, ...). The more extensive the scene, the lower these values should be. Below, we use default learning rates (left) and ```--position_lr_init 0.000016 --scaling_lr 0.001"``` (right).
| ![Default learning rate result](assets/worse.png "title-1") <!-- --> | <!-- --> ![Reduced learning rate result](assets/better.png "title-2") |
| --- | --- |
- *I don't have 24 GB of VRAM for training, what do I do?* The VRAM consumption is determined by the number of points that are being optimized, which increases over time. If you only want to train to 7k iterations, you will need significantly less. To do the full training routine and avoid running out of memory, you can increase the ```--densify_grad_threshold```, ```--densification_interval``` or reduce the value of ```--densify_until_iter```. Note however that this will affect the quality of the result. Also try setting ```--test_iterations``` to ```-1``` to avoid memory spikes during testing. If ```--densify_grad_threshold``` is very high, no densification should occur and training should complete if the scene itself loads successfully.
- *24 GB of VRAM for reference quality training is still a lot! Can't we do it with less?* Yes, most likely. By our calculations it should be possible with **way** less memory (~8GB). If we can find the time we will try to achieve this. If some PyTorch veteran out there wants to tackle this, we look forward to your pull request!
- *How can I use the differentiable Gaussian rasterizer for my own project?* Easy, it is included in this repo as a submodule ```diff-gaussian-rasterization```. Feel free to check out and install the package. It's not really documented, but using it from the Python side is very straightforward (cf. ```gaussian_renderer/__init__.py```).
- *Wait, but ```<insert feature>``` isn't optimized and could be much better?* There are several parts we didn't even have time to think about improving (yet). The performance you get with this prototype is probably a rather slow baseline for what is physically possible.
- *Something is broken, how did this happen?* We tried hard to provide a solid and comprehensible basis to make use of the paper's method. We have refactored the code quite a bit, but we have limited capacity to test all possible usage scenarios. Thus, if part of the website, the code or the performance is lacking, please create an issue. If we find the time, we will do our best to address it.

45
SIBR_viewers/.gitignore vendored Normal file
View File

@ -0,0 +1,45 @@
extlibs/
build/
install/
src/projects/*
cmake-gui.exe.stackdump
__pycache__/
# emacs garbage
\#*
.\#*
# vim garbage
*.swp
*.swo
*.idea/
*.log
*.sh
*.tmp
hs_err_*
# re include common public projects
!src/projects/ulr/
!src/projects/dataset_tools/
# more vim garbage
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
Sessionx.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~

213
SIBR_viewers/CMakeLists.txt Normal file
View File

@ -0,0 +1,213 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
CMAKE_MINIMUM_REQUIRED(VERSION 3.22)
set (CMAKE_SYSTEM_VERSION 10.0.15063.0 CACHE INTERNAL "Cmake system version" FORCE)
PROJECT(sibr_projects)
set(REQUIRED_VERSION "3.22.0")
set(CHECKED_VERSION "3.27.0")
if (CMAKE_VERSION VERSION_LESS REQUIRED_VERSION)
message(WARNING "Deprecated version of cmake. Please update to at least ${REQUIRED_VERSION} (${CHECKED_VERSION} recommended).")
elseif (CMAKE_VERSION VERSION_GREATER CHECKED_VERSION)
message(WARNING "Untested version of cmake. If you checked everything is working properly, please update ${CHECKED_VERSION} in the main CmakeLists.txt with the version you tested.")
endif()
## Include cmake stuff (functions/macros) : Modules files
if(WIN32)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows/Modules)
else()
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/linux)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/linux/Modules)
endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
## To maintain cmake versions compatibilities
include(cmake_policies)
setPolicies()
include(git_describe)
git_describe(GIT_BRANCH SIBR_CORE_BRANCH GIT_COMMIT_HASH SIBR_CORE_COMMIT_HASH GIT_TAG SIBR_CORE_TAG GIT_VERSION SIBR_CORE_VERSION)
message(STATUS "SIBR version :\n BRANCH ${SIBR_CORE_BRANCH}\n COMMIT_HASH ${SIBR_CORE_COMMIT_HASH}\n TAG ${SIBR_CORE_TAG}\n VERSION ${SIBR_CORE_VERSION}")
if(NOT WIN32)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
if (WIN32)
## Allow C++11 + other flags
include(CheckCXXCompilerFlag)
get_filename_component(currentBuildTool ${CMAKE_BUILD_TOOL} NAME_WE) # tool that can launch the native build system. returned value may be the full path
if(${currentBuildTool} MATCHES "(msdev|devenv|nmake|MSBuild)")
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/W3;/DNOMINMAX;/MP;-D_USE_MATH_DEFINES>")
#add_definitions(/W3 /DNOMINMAX /MP -D_USE_MATH_DEFINES)# /D_ITERATOR_DEBUG_LEVEL=1 because you need all external DLl to compile with this flag too
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING "" FORCE)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
elseif(${currentBuildTool} MATCHES "(make|gmake)")
add_definitions("-Wall -Wno-unknown-pragmas -Wno-sign-compare -g -std=c++14 -D__forceinline=\"inline\ __attribute__((always_inline))\"")
# CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_CXX11)
# CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" COMPILER_SUPPORTS_CXX0X)
# if(COMPILER_SUPPORTS_CXX11)
# add_definitions(-std=gnu++11)
# elseif(COMPILER_SUPPORTS_CXX0X)
# add_definitions(-std=gnu++0x)
# else()
# message(SEND_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler.")
# endif()
elseif(APPLE) ## \todo TODO: do a better test and send error on unsupported c++14 compiler
add_definitions(-std=c++14 -stdlib=libc++)
endif()
else()
## Allow C++11 + other flags
include(CheckCXXCompilerFlag)
get_filename_component(currentBuildTool ${CMAKE_BUILD_TOOL} NAME_WE) # tool that can launch the native build system. returned value may be the full path
if(${currentBuildTool} MATCHES "(msdev|devenv|nmake|MSBuild)")
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/W3;/DNOMINMAX;/MP;-D_USE_MATH_DEFINES>")
#add_definitions(/W3 /DNOMINMAX /MP -D_USE_MATH_DEFINES)# /D_ITERATOR_DEBUG_LEVEL=1 because you need all external DLl to compile with this flag too
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING "" FORCE)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
elseif(${currentBuildTool} MATCHES "(make|gmake|ninja)")
add_definitions("-fpermissive -fPIC -Wall -Wno-unknown-pragmas -Wno-sign-compare -g -std=c++17 -D__forceinline=\"inline\ __attribute__((always_inline))\"")
elseif(APPLE) ## \todo TODO: do a better test and send error on unsupported c++14 compiler
add_definitions(-std=c++17 -stdlib=libc++)
endif()
endif()
set(INSTALL_STANDALONE ON)
## Set default build output binaries (used also in sub CMakeLists.txt) :
set(BIN_BUILT_DIR "bin")
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ARCHI_BUILT_DIR "x64")
set(LIB_BUILT_DIR "lib64")
else()
set(ARCHI_BUILT_DIR "x86")
set(LIB_BUILT_DIR "lib")
endif()
option(SEPARATE_CONFIGURATIONS "Clearer separation between configurations" OFF)
SET(CMAKE_INSTALL_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/install)
SET(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_ROOT})
if(DEFINED CMAKE_BUILD_TYPE) ## for mono config type (make/nmake/ninja based)
if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
set(CMAKE_DEBUG_POSTFIX "_d")
elseif(${CMAKE_BUILD_TYPE} MATCHES "RelWithDebInfo")
set(CMAKE_RELWITHDEBINFO_POSTFIX "_rwdi")
elseif(${CMAKE_BUILD_TYPE} MATCHES "MinSizeRel")
set(CMAKE_MINSIZEREL_POSTFIX "_msr")
elseif(${CMAKE_BUILD_TYPE} MATCHES "Release")
set(CMAKE_RELEASE_POSTFIX "")
endif()
if(SEPARATE_CONFIGURATIONS)
SET(CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE} ${CMAKE_INSTALL_ROOT}/${CMAKE_BUILD_TYPE})
else()
SET(CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE} ${CMAKE_INSTALL_ROOT})
endif()
MESSAGE(STATUS "Install path set to ${CMAKE_INSTALL_PREFIX}.")
SET(CMAKE_OUTPUT_LIB_${CMAKE_BUILD_TYPE} ${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}/lib)
SET(CMAKE_OUTPUT_BIN_${CMAKE_BUILD_TYPE} ${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE} ${CMAKE_OUTPUT_LIB_${CMAKE_BUILD_TYPE}})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE} ${CMAKE_OUTPUT_LIB_${CMAKE_BUILD_TYPE}})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE} ${CMAKE_OUTPUT_BIN_${CMAKE_BUILD_TYPE}})
set(CMAKE_PDB_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE} ${CMAKE_OUTPUT_BIN_${CMAKE_BUILD_TYPE}})
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
if(${CONFIG_TYPES} MATCHES "Debug")
set(CMAKE_DEBUG_POSTFIX "_d")
elseif(${CONFIG_TYPES} MATCHES "RelWithDebInfo")
set(CMAKE_RELWITHDEBINFO_POSTFIX "_rwdi")
elseif(${CONFIG_TYPES} MATCHES "MinSizeRel")
set(CMAKE_MINSIZEREL_POSTFIX "_msr")
elseif(${CMAKE_BUILD_TYPE} MATCHES "Release")
set(CMAKE_RELEASE_POSTFIX "")
endif()
if(SEPARATE_CONFIGURATIONS)
SET(CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC} ${CMAKE_INSTALL_ROOT}/${CONFIG_TYPES})
else()
SET(CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC} ${CMAKE_INSTALL_ROOT})
endif()
MESSAGE(STATUS "Install path for ${CONFIG_TYPES} set to ${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}.")
SET(CMAKE_OUTPUT_LIB_${CONFIG_TYPES_UC} ${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}/lib)
SET(CMAKE_OUTPUT_BIN_${CONFIG_TYPES_UC} ${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC} ${CMAKE_OUTPUT_LIB_${CONFIG_TYPES_UC}})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC} ${CMAKE_OUTPUT_LIB_${CONFIG_TYPES_UC}})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC} ${CMAKE_OUTPUT_BIN_${CONFIG_TYPES_UC}})
set(CMAKE_PDB_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC} ${CMAKE_OUTPUT_BIN_${CONFIG_TYPES_UC}})
endforeach()
# Settings for RPATH
if (NOT WIN32)
# Default config of Fedora at INRIA has no LD_LIBRARY_PATH (for security reasons I guess)
# So at least I had "./" in RPATH and found link paths
#set(CMAKE_SKIP_RPATH TRUE)
#SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH "$ORIGIN")
#SET(CMAKE_INSTALL_RPATH "./")
#SET(CMAKE_INSTALL_RPATH "./:/usr/lib64/:/usr/lib/:/usr/local/lib64/:/usr/local/lib/") # This one causes be a problem -> a "default" version of libGL (swrast) is located in /usr/lib64 and was selected instead of nvidia one (in /usr/lib64/nividia)
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
endif()
set(SIBR_PROGRAMARGS "" CACHE STRING "Default program arguments used in Visual Studio target properties")
if ("${SIBR_PROGRAMARGS}" STREQUAL "")
if (DEFINED ENV{SIBR_PROGRAMARGS})
set(SIBR_PROGRAMARGS "$ENV{SIBR_PROGRAMARGS}" CACHE STRING "Default program arguments used in Visual Studio target properties" FORCE)
message( STATUS "Using program options found in environment variable 'SIBR_PROGRAMARGS' => '${SIBR_PROGRAMARGS}'")
else()
message(
"Note you can provide default program options for Visual Studio target properties by either setting"
" a value for the cmake cached variable 'SIBR_PROGRAMARGS' or by setting a new environment "
"variable 'SIBR_PROGRAMARGS'")
endif()
endif()
add_custom_target(PREBUILD ALL)
## Include all projects
set(SIBR_PROJECTS_SAMPLES_SUBPAGE_REF "")
set(SIBR_PROJECTS_OURS_SUBPAGE_REF "")
set(SIBR_PROJECTS_TOOLBOX_SUBPAGE_REF "")
set(SIBR_PROJECTS_OTHERS_SUBPAGE_REF "")
set(SIBR_PROJECTS_SAMPLES_REF_REF "")
set(SIBR_PROJECTS_OURS_REF_REF "")
set(SIBR_PROJECTS_TOOLBOX_REF_REF "")
set(SIBR_PROJECTS_OTHERS_REF_REF "")
set(DOXY_APP_SPECIFIC_IMG_PATH "")
set(DOXY_DOC_EXCLUDE_PATTERNS_DIRS "")
ADD_SUBDIRECTORY(src)
## handle documentation
if (WIN32)
ADD_SUBDIRECTORY(docs)
endif()

83
SIBR_viewers/LICENSE.md Normal file
View File

@ -0,0 +1,83 @@
SIBR License
============
**Inria** and **UCA** hold all the ownership rights on the *Software* named **sibr-core**.
The *Software* has been registered with the Agence pour la Protection des
Programmes (APP) under IDDN.FR.001.430020.000.S.P.2019.000.31235
The *Software* is still being developed by the *Licensor*.
*Licensor*'s goal is to allow the research community to use, test and evaluate
the *Software*.
## 1. Definitions
*Licensee* means any person or entity that uses the *Software* and distributes
its *Work*.
*Licensor* means the owners of the *Software*, i.e Inria and UCA
*Software* means the original work of authorship made available under this
License ie Sibr-core.
*Work* means the *Software* and any additions to or derivative works of the
*Software* that are made available under this License.
## 2. Purpose
This license is intended to define the rights granted to the *Licensee* by
Licensors under the *Software*.
## 3. Rights granted
For the above reasons Licensors have decided to distribute the *Software*.
Licensors grant non-exclusive rights to use the *Software* for research purposes
to research users (both academic and industrial), free of charge, without right
to sublicense.. The *Software* may be used "non-commercially", i.e., for research
and/or evaluation purposes only.
Subject to the terms and conditions of this License, you are granted a
non-exclusive, royalty-free, license to reproduce, prepare derivative works of,
publicly display, publicly perform and distribute its *Work* and any resulting
derivative works in any form.
## 4. Limitations
**4.1 Redistribution.** You may reproduce or distribute the *Work* only if (a) you do
so under this License, (b) you include a complete copy of this License with
your distribution, and (c) you retain without modification any copyright,
patent, trademark, or attribution notices that are present in the *Work*.
**4.2 Derivative Works.** You may specify that additional or different terms apply
to the use, reproduction, and distribution of your derivative works of the *Work*
("Your Terms") only if (a) Your Terms provide that the use limitation in
Section 2 applies to your derivative works, and (b) you identify the specific
derivative works that are subject to Your Terms. Notwithstanding Your Terms,
this License (including the redistribution requirements in Section 3.1) will
continue to apply to the *Work* itself.
**4.3** Any other use without of prior consent of Licensors is prohibited. Research
users explicitly acknowledge having received from Licensors all information
allowing to appreciate the adequacy between of the *Software* and their needs and
to undertake all necessary precautions for its execution and use.
**4.4** The *Software* is provided both as a compiled library file and as source
code. In case of using the *Software* for a publication or other results obtained
through the use of the *Software*, users are strongly encouraged to cite the
corresponding publications as explained in the documentation of the *Software*.
## 5. Disclaimer
THE USER CANNOT USE, EXPLOIT OR DISTRIBUTE THE *SOFTWARE* FOR COMMERCIAL PURPOSES
WITHOUT PRIOR AND EXPLICIT CONSENT OF LICENSORS. YOU MUST CONTACT INRIA FOR ANY
UNAUTHORIZED USE: stip-sophia.transfert@inria.fr . ANY SUCH ACTION WILL
CONSTITUTE A FORGERY. THIS *SOFTWARE* IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES
OF ANY NATURE AND ANY EXPRESS OR IMPLIED WARRANTIES, WITH REGARDS TO COMMERCIAL
USE, PROFESSIONNAL USE, LEGAL OR NOT, OR OTHER, OR COMMERCIALISATION OR
ADAPTATION. UNLESS EXPLICITLY PROVIDED BY LAW, IN NO EVENT, SHALL INRIA OR 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 FROM, OUT OF OR
IN CONNECTION WITH THE *SOFTWARE* OR THE USE OR OTHER DEALINGS IN THE *SOFTWARE*.

142
SIBR_viewers/README.md Normal file
View File

@ -0,0 +1,142 @@
# SIBR Core
**SIBR** is a System for Image-Based Rendering.
It is built around the *sibr-core* in this repo and several *Projects* implementing published research papers.
For more complete documentation, see here: [SIBR Documentation](https://sibr.gitlabpages.inria.fr)
This **SIBR core** repository provides :
- a basic Image-Based Renderer
- a per-pixel implementation of Unstructured Lumigraph (ULR)
- several dataset tools & pipelines do process input images
Details on how to run in the documentation and in the section below.
If you use this code in a publication, please cite the system as follows:
```
@misc{sibr2020,
author = "Bonopera, Sebastien and Esnault, Jerome and Prakash, Siddhant and Rodriguez, Simon and Thonat, Theo and Benadel, Mehdi and Chaurasia, Gaurav and Philip, Julien and Drettakis, George",
title = "sibr: A System for Image Based Rendering",
year = "2020",
url = "https://gitlab.inria.fr/sibr/sibr_core"
}
```
## Setup
**Note**: The current release is for *Windows 10* only. We are planning a Linux release soon.
#### Binary distribution
The easiest way to use SIBR is to download the binary distribution. All steps described below, including all preprocessing for your datasets will work using this code.
Download the distribution from the page: https://sibr.gitlabpages.inria.fr/download.html (Core, 57Mb); unzip the file and rename the directory "install".
#### Install requirements
- [**Visual Studio 2019**](https://visualstudio.microsoft.com/fr/downloads/)
- [**Cmake 3.16+**](https://cmake.org/download)
- [**7zip**](https://www.7-zip.org)
- [**Python 3.8+**](https://www.python.org/downloads/) for shaders installation scripts and dataset preprocess scripts
- [**Doxygen 1.8.17+**](https://www.doxygen.nl/download.html#srcbin) for documentation
- [**CUDA 10.1+**](https://developer.nvidia.com/cuda-downloads) and [**CUDnn**](https://developer.nvidia.com/cudnn) if projects requires it
Make sure Python, CUDA and Doxygen are in the PATH
If you have Chocolatey, you can grab most of these with this command:
```sh
choco install cmake 7zip python3 doxygen.install cuda
## Visual Studio is available on Chocolatey,
## though we do advise to set it from Visual Studio Installer and to choose your licensing accordingly
choco install visualstudio2019community
```
#### Generation of the solution
- Checkout this repository's master branch:
```sh
## through HTTPS
git clone https://gitlab.inria.fr/sibr/sibr_core.git -b master
## through SSH
git clone git@gitlab.inria.fr:sibr/sibr_core.git -b master
```
- Run Cmake-gui once, select the repo root as a source directory, `build/` as the build directory. Configure, select the Visual Studio C++ Win64 compiler
- Select the projects you want to generate among the BUILD elements in the list (you can group Cmake flags by categories to access those faster)
- Generate
#### Compilation
- Open the generated Visual Studio solution (`build/sibr_projects.sln`)
- Build the `ALL_BUILD` target, and then the `INSTALL` target
- The compiled executables will be put in `install/bin`
- TODO: are the DLLs properly installed?
#### Compilation of the documentation
- Open the generated Visual Studio solution (`build/sibr_projects.sln`)
- Build the `DOCUMENTATION` target
- Run `install/docs/index.html` in a browser
## Scripts
Some scripts will require you to install `PIL`, and `convert` from `ImageMagick`.
```sh
## To install pillow
python -m pip install pillow
## If you have Chocolatey, you can install imagemagick from this command
choco install imagemagick
```
## Troubleshooting
#### Bugs and Issues
We will track bugs and issues through the Issues interface on gitlab. Inria gitlab does not allow creation of external accounts, so if you have an issue/bug please email <code>sibr@inria.fr</code> and we will either create a guest account or create the issue on our side.
#### Cmake complaining about the version
if you are the first to use a very recent Cmake version, you will have to update `CHECKED_VERSION` in the root `CmakeLists.txt`.
#### Weird OpenCV error
you probably selected the 32-bits compiler in Cmake-gui.
#### `Cmd.exe failed with error 009` or similar
make sure Python is installed and in the path.
#### `BUILD_ALL` or `INSTALL` fail because of a project you don't really need
build and install each project separately by selecting the proper targets.
#### Error in CUDA headers under Visual Studio 2019
make sure CUDA >= 10.1 (first version to support VS2019) is installed.
## To run an example
For more details, please see the documentation: http://sibr.gitlabpages.inria.fr
Download a dataset from: https://repo-sam.inria.fr/fungraph/sibr-datasets/
e.g., the *sibr-museum-front* dataset in the *DATASETS_PATH* directory.
```
wget https://repo-sam.inria.fr/fungraph/sibr-datasets/museum_front27_ulr.zip
```
Once you have built the system or downloaded the binaries (see above), go to *install/bin* and you can run:
```
sibr_ulrv2_app.exe --path DATASETS_PATH/sibr-museum-front
```
You will have an interactive viewer and you can navigate freely in the captured scene.
Our default interactive viewer has a main view running the algorithm and a top view to visualize the position of the calibrated cameras. By default you are in WASD mode, and can toggle to trackball using the "y" key. Please see the page [Interface](https://sibr.gitlabpages.inria.fr/docs/nightly/howto_sibr_useful_objects.html) for more details on the interface.
Please see the documentation on how to create a dataset from your own scene, and the various other IBR algorithms available.

View File

@ -0,0 +1,149 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
if(__MSVCsetUserCommand_cmake_INCLUDED__)
return()
else()
set(__MSVCsetUserCommand_cmake_INCLUDED__ ON)
endif()
## Allow to configure the Debugger settings of visual studio
## Note: Using this command under linux doesn't affect anything
## On run Debug Windows local : visual will try to load a specific COMMAND with ARGS in the provided WORKING_DIR
##
## usage:
## MSVCsetUserCommand( <targetName>
## [COMMAND <myCustomAppToLaunch> | [ PATH <myCustomDirWhereIsDefaultTargetFileNameToLaunch> [FILE <myCustomExecFileToLaunch>] ] ]
## ARGS <associatedArguments>
## WORKING_DIR <whereStartTheProgram>
## )
##
## Warning 1 : All arugments () must be passed under quotes
## Warning 2 : WORKING_DIR path arg have to finish with remain slah '/'
## Warning 3 : use COMMAND for external app OR PATH (optionaly with FILE) option(s) to set your built/installed/moved target
##
## Example 1:
## include(MSVCsetUserCommand)
## MSVCsetUserCommand( UnityRenderingPlugin
## COMMAND "C:/Program Files (x86)/Unity/Editor/Unity.exe"
## ARGS "-force-opengl -projectPath \"${CMAKE_HOME_DIRECTORY}/UnityPlugins/RenderingPluginExample/UnityProject\""
## WORKING_DIR "${CMAKE_HOME_DIRECTORY}/UnityPlugins/RenderingPluginExample/UnityProject"
## VERBOSE
## )
##
## Example 2:
## include(MSVCsetUserCommand)
## MSVCsetUserCommand( ibrApp
## PATH "C:/Program Files (x86)/workspace/IBR/install"
## FILE "ibrApp${CMAKE_EXECUTABLE_SUFFIX}" ## this option line is optional since the target name didn't change between build and install step
## ARGS "-path \"${CMAKE_HOME_DIRECTORY}/dataset\""
## WORKING_DIR "${CMAKE_HOME_DIRECTORY}"
## VERBOSE
## )
##
function(MSVCsetUserCommand targetName)
cmake_parse_arguments(MSVCsuc "VERBOSE" "PATH;FILE;COMMAND;ARGS;WORKING_DIR" "" ${ARGN} )
## If no arguments are given, do not create an unecessary .vcxproj.user file
set(MSVCsuc_DEFAULT OFF)
if(MSVCsuc_PATH AND MSVCsuc_DEFAULT)
set(MSVCsuc_DEFAULT OFF)
endif()
if(MSVCsuc_FILE AND MSVCsuc_DEFAULT)
set(MSVCsuc_DEFAULT OFF)
endif()
if(NOT MSVCsuc_COMMAND)
if(MSVCsuc_PATH AND MSVCsuc_FILE)
set(MSVCsuc_COMMAND "${MSVCsuc_PATH}\\${MSVCsuc_FILE}")
elseif(MSVCsuc_PATH)
set(MSVCsuc_COMMAND "${MSVCsuc_PATH}\\$(TargetFileName)")
else()
set(MSVCsuc_COMMAND "$(TargetPath)") ## => $(TargetDir)\$(TargetName)$(TargetExt)
endif()
elseif(MSVCsuc_DEFAULT)
set(MSVCsuc_DEFAULT OFF)
endif()
# NOTE: there was a typo here. there is an else if written after else statement
# changing the order of the else if statement
if(MSVCsuc_WORKING_DIR)
file(TO_NATIVE_PATH ${MSVCsuc_WORKING_DIR} MSVCsuc_WORKING_DIR)
elseif(MSVCsuc_DEFAULT)
set(MSVCsuc_DEFAULT OFF)
else()
set(MSVCsuc_WORKING_DIR "$(ProjectDir)")
endif()
if(NOT MSVCsuc_ARGS)
set(MSVCsuc_ARGS "")
elseif(MSVCsuc_DEFAULT)
set(MSVCsuc_DEFAULT OFF)
endif()
if(MSVC10 OR (MSVC AND MSVC_VERSION GREATER 1600)) # 2010 or newer
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(PLATEFORM_BITS x64)
else()
set(PLATEFORM_BITS Win32)
endif()
if(NOT MSVCsuc_DEFAULT AND PLATEFORM_BITS)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${targetName}.vcxproj.user"
"<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|${PLATEFORM_BITS}'\">
<LocalDebuggerCommand>${MSVCsuc_COMMAND}</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>${MSVCsuc_ARGS}</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerWorkingDirectory>${MSVCsuc_WORKING_DIR}</LocalDebuggerWorkingDirectory>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|${PLATEFORM_BITS}'\">
<LocalDebuggerCommand>${MSVCsuc_COMMAND}</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>${MSVCsuc_ARGS}</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerWorkingDirectory>${MSVCsuc_WORKING_DIR}</LocalDebuggerWorkingDirectory>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='MinSizeRel|${PLATEFORM_BITS}'\">
<LocalDebuggerCommand>${MSVCsuc_COMMAND}</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>${MSVCsuc_ARGS}</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerWorkingDirectory>${MSVCsuc_WORKING_DIR}</LocalDebuggerWorkingDirectory>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='RelWithDebInfo|${PLATEFORM_BITS}'\">
<LocalDebuggerCommand>${MSVCsuc_COMMAND}</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>${MSVCsuc_ARGS}</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerWorkingDirectory>${MSVCsuc_WORKING_DIR}</LocalDebuggerWorkingDirectory>
</PropertyGroup>
</Project>"
)
if(MSVCsuc_VERBOSE)
message(STATUS "[MSVCsetUserCommand] Write ${CMAKE_CURRENT_BINARY_DIR}/${targetName}.vcxproj.user file")
message(STATUS " to execute ${MSVCsuc_COMMAND} ${MSVCsuc_ARGS}")
message(STATUS " from derectory ${MSVCsuc_WORKING_DIR}")
message(STATUS " on visual studio run debugger button")
endif()
else()
message(WARNING "PLATEFORM_BITS is undefined...")
endif()
else()
if(MSVCsuc_VERBOSE)
message(WARNING "MSVCsetUserCommand is disable because too old MSVC is used (need MSVC10 2010 or newer)")
endif()
endif()
endfunction()

View File

@ -0,0 +1,114 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## Try to find the ASSIMP library
## Once done this will define
##
## ASSIMP_FOUND - system has ASSIMP
## ASSIMP_INCLUDE_DIR - The ASSIMP include directory
## ASSIMP_LIBRARIES - The libraries needed to use ASSIMP
## ASSIMP_CMD - the full path of ASSIMP executable
## ASSIMP_DYNAMIC_LIB - the Assimp dynamic lib (available only on windows as .dll file for the moment)
##
## Edited for using a bugfixed version of Assimp
if(NOT ASSIMP_DIR)
set(ASSIMP_DIR "$ENV{ASSIMP_DIR}" CACHE PATH "ASSIMP root directory")
message("NO ASSIMP DIR " ASSIMP_DIR )
file(TO_CMAKE_PATH "/data/graphdeco/share/usr/local" ASSIMP_DIR)
set(ASSIMP_DIR "/data/graphdeco/share/usr/local" )
message("SETTING ASSIMP DIR " ASSIMP_DIR )
endif()
if(ASSIMP_DIR)
file(TO_CMAKE_PATH ${ASSIMP_DIR} ASSIMP_DIR)
file(TO_CMAKE_PATH "/data/graphdeco/share/usr/local" ASSIMP_DIR)
message("ASSIMP DIR " ASSIMP_DIR )
endif()
## set the LIB POSTFIX to find in a right directory according to what kind of compiler we use (32/64bits)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ASSIMP_SEARCH_LIB "lib64")
set(ASSIMP_SEARCH_BIN "bin64")
set(ASSIMP_SEARCH_LIB_PATHSUFFIXE "x64")
else()
set(ASSIMP_SEARCH_LIB "lib32")
set(ASSIMP_SEARCH_BIN "bin32")
set(ASSIMP_SEARCH_LIB_PATHSUFFIXE "x86")
endif()
set(PROGRAMFILESx86 "PROGRAMFILES(x86)")
FIND_PATH(ASSIMP_INCLUDE_DIR
NAMES assimp/config.h
PATHS
${ASSIMP_DIR}
## linux
/usr
/usr/include
/usr/local
/opt/local
## windows
"$ENV{PROGRAMFILES}/Assimp"
"$ENV{${PROGRAMFILESx86}}/Assimp"
"$ENV{ProgramW6432}/Assimp"
PATH_SUFFIXES include
)
FIND_LIBRARY(ASSIMP_LIBRARY
NAMES assimp-vc140-mt assimp
PATHS
${ASSIMP_DIR}/${ASSIMP_SEARCH_LIB}
${ASSIMP_DIR}/lib
${ASSIMP_DIR}/lib64
## linux
/usr/${ASSIMP_SEARCH_LIB}
/usr/local/${ASSIMP_SEARCH_LIB}
/opt/local/${ASSIMP_SEARCH_LIB}
/usr/lib
/usr/lib64
/usr/local/lib
/opt/local/lib
## windows
"$ENV{PROGRAMFILES}/Assimp/${ASSIMP_SEARCH_LIB}"
"$ENV{${PROGRAMFILESx86}}/Assimp/${ASSIMP_SEARCH_LIB}"
"$ENV{ProgramW6432}/Assimp/${ASSIMP_SEARCH_LIB}"
"$ENV{PROGRAMFILES}/Assimp/lib"
"$ENV{${PROGRAMFILESx86}}/Assimp/lib"
"$ENV{ProgramW6432}/Assimp/lib"
PATH_SUFFIXES ${ASSIMP_SEARCH_LIB_PATHSUFFIXE}
)
set(ASSIMP_LIBRARIES ${ASSIMP_LIBRARY})
if(ASSIMP_LIBRARY)
get_filename_component(ASSIMP_LIBRARY_DIR ${ASSIMP_LIBRARY} PATH)
if(WIN32)
file(GLOB ASSIMP_DYNAMIC_LIB "${ASSIMP_LIBRARY_DIR}/assimp*.dll")
if(NOT ASSIMP_DYNAMIC_LIB)
message("ASSIMP_DYNAMIC_LIB is missing... at ${ASSIMP_LIBRARY_DIR}")
endif()
endif()
set(ASSIMP_DYNAMIC_LIB ${ASSIMP_DYNAMIC_LIB} CACHE PATH "Windows dll location")
endif()
MARK_AS_ADVANCED(ASSIMP_DYNAMIC_LIB ASSIMP_INCLUDE_DIR ASSIMP_LIBRARIES)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ASSIMP
REQUIRED_VARS ASSIMP_INCLUDE_DIR ASSIMP_LIBRARIES
FAIL_MESSAGE "ASSIMP wasn't found correctly. Set ASSIMP_DIR to the root SDK installation directory."
)
if(NOT ASSIMP_FOUND)
set(ASSIMP_DIR "" CACHE STRING "Path to ASSIMP install directory")
endif()

View File

@ -0,0 +1,161 @@
#.rst:
# FindEGL
# -------
#
# Try to find EGL.
#
# This will define the following variables:
#
# ``EGL_FOUND``
# True if (the requested version of) EGL is available
# ``EGL_VERSION``
# The version of EGL; note that this is the API version defined in the
# headers, rather than the version of the implementation (eg: Mesa)
# ``EGL_LIBRARIES``
# This can be passed to target_link_libraries() instead of the ``EGL::EGL``
# target
# ``EGL_INCLUDE_DIRS``
# This should be passed to target_include_directories() if the target is not
# used for linking
# ``EGL_DEFINITIONS``
# This should be passed to target_compile_options() if the target is not
# used for linking
#
# If ``EGL_FOUND`` is TRUE, it will also define the following imported target:
#
# ``EGL::EGL``
# The EGL library
#
# In general we recommend using the imported target, as it is easier to use.
# Bear in mind, however, that if the target is in the link interface of an
# exported library, it must be made available by the package config file.
#
# Since pre-1.0.0.
#=============================================================================
# Copyright 2014 Alex Merry <alex.merry@kde.org>
# Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
#
# 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 copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the 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.
#=============================================================================
include(CheckCXXSourceCompiles)
include(CMakePushCheckState)
# Use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig)
pkg_check_modules(PKG_EGL QUIET egl)
set(EGL_DEFINITIONS ${PKG_EGL_CFLAGS_OTHER})
find_path(EGL_INCLUDE_DIR
NAMES
EGL/egl.h
HINTS
${PKG_EGL_INCLUDE_DIRS}
)
find_library(EGL_LIBRARY
NAMES
EGL
HINTS
${PKG_EGL_LIBRARY_DIRS}
)
# NB: We do *not* use the version information from pkg-config, as that
# is the implementation version (eg: the Mesa version)
if(EGL_INCLUDE_DIR)
# egl.h has defines of the form EGL_VERSION_x_y for each supported
# version; so the header for EGL 1.1 will define EGL_VERSION_1_0 and
# EGL_VERSION_1_1. Finding the highest supported version involves
# finding all these defines and selecting the highest numbered.
file(READ "${EGL_INCLUDE_DIR}/EGL/egl.h" _EGL_header_contents)
string(REGEX MATCHALL
"[ \t]EGL_VERSION_[0-9_]+"
_EGL_version_lines
"${_EGL_header_contents}"
)
unset(_EGL_header_contents)
foreach(_EGL_version_line ${_EGL_version_lines})
string(REGEX REPLACE
"[ \t]EGL_VERSION_([0-9_]+)"
"\\1"
_version_candidate
"${_EGL_version_line}"
)
string(REPLACE "_" "." _version_candidate "${_version_candidate}")
if(NOT DEFINED EGL_VERSION OR EGL_VERSION VERSION_LESS _version_candidate)
set(EGL_VERSION "${_version_candidate}")
endif()
endforeach()
unset(_EGL_version_lines)
endif()
cmake_push_check_state(RESET)
list(APPEND CMAKE_REQUIRED_LIBRARIES "${EGL_LIBRARY}")
list(APPEND CMAKE_REQUIRED_INCLUDES "${EGL_INCLUDE_DIR}")
check_cxx_source_compiles("
#include <EGL/egl.h>
int main(int argc, char *argv[]) {
EGLint x = 0; EGLDisplay dpy = 0; EGLContext ctx = 0;
eglDestroyContext(dpy, ctx);
}" HAVE_EGL)
cmake_pop_check_state()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(EGL
FOUND_VAR
EGL_FOUND
REQUIRED_VARS
EGL_LIBRARY
EGL_INCLUDE_DIR
HAVE_EGL
VERSION_VAR
EGL_VERSION
)
if(EGL_FOUND AND NOT TARGET EGL::EGL)
add_library(EGL::EGL UNKNOWN IMPORTED)
set_target_properties(EGL::EGL PROPERTIES
IMPORTED_LOCATION "${EGL_LIBRARY}"
INTERFACE_COMPILE_OPTIONS "${EGL_DEFINITIONS}"
INTERFACE_INCLUDE_DIRECTORIES "${EGL_INCLUDE_DIR}"
)
endif()
mark_as_advanced(EGL_LIBRARY EGL_INCLUDE_DIR HAVE_EGL)
# compatibility variables
set(EGL_LIBRARIES ${EGL_LIBRARY})
set(EGL_INCLUDE_DIRS ${EGL_INCLUDE_DIR})
set(EGL_VERSION_STRING ${EGL_VERSION})
include(FeatureSummary)
set_package_properties(EGL PROPERTIES
URL "https://www.khronos.org/egl/"
DESCRIPTION "A platform-agnostic mechanism for creating rendering surfaces for use with other graphics libraries, such as OpenGL|ES and OpenVG."
)

View File

@ -0,0 +1,94 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## Important Note:
## This is not an official Find*cmake. It has been written for searching through
## a custom path (EMBREE_DIR) before checking elsewhere.
##
## FindEMBREE.cmake
## Find EMBREE's includes and library
##
## This module defines :
## [in] EMBREE_DIR, The base directory to search for EMBREE (as cmake var or env var)
## [out] EMBREE_INCLUDE_DIR where to find EMBREE.h
## [out] EMBREE_LIBRARIES, EMBREE_LIBRARY, libraries to link against to use EMBREE
## [out] EMBREE_FOUND, If false, do not try to use EMBREE.
##
if(NOT EMBREE_DIR)
set(EMBREE_DIR "$ENV{EMBREE_DIR}" CACHE PATH "EMBREE root directory")
endif()
if(EMBREE_DIR)
file(TO_CMAKE_PATH ${EMBREE_DIR} EMBREE_DIR)
endif()
## set the LIB POSTFIX to find in a right directory according to what kind of compiler we use (32/64bits)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(EMBREE_SEARCH_LIB "lib64")
set(EMBREE_SEARCH_BIN "bin64")
set(EMBREE_SEARCH_LIB_PATHSUFFIXE "x64")
else()
set(EMBREE_SEARCH_LIB "lib32")
set(EMBREE_SEARCH_BIN "bin32")
set(EMBREE_SEARCH_LIB_PATHSUFFIXE "x86")
endif()
set(PROGRAMFILESx86 "PROGRAMFILES(x86)")
FIND_PATH(EMBREE_INCLUDE_DIR
NAMES embree3/rtcore_geometry.h
PATHS
${EMBREE_DIR}
## linux
/usr
/usr/local
/opt/local
## windows
"$ENV{PROGRAMFILES}/EMBREE"
"$ENV{${PROGRAMFILESx86}}/EMBREE"
"$ENV{ProgramW6432}/EMBREE"
PATH_SUFFIXES include
)
FIND_LIBRARY(EMBREE_LIBRARY
NAMES embree3
PATHS
${EMBREE_DIR}/${EMBREE_SEARCH_LIB}
${EMBREE_DIR}/lib
## linux
/usr/${EMBREE_SEARCH_LIB}
/usr/local/${EMBREE_SEARCH_LIB}
/opt/local/${EMBREE_SEARCH_LIB}
/usr/lib
/usr/local/lib
/opt/local/lib
## windows
"$ENV{PROGRAMFILES}/EMBREE/${EMBREE_SEARCH_LIB}"
"$ENV{${PROGRAMFILESx86}}/EMBREE/${EMBREE_SEARCH_LIB}"
"$ENV{ProgramW6432}/EMBREE/${EMBREE_SEARCH_LIB}"
"$ENV{PROGRAMFILES}/EMBREE/lib"
"$ENV{${PROGRAMFILESx86}}/EMBREE/lib"
"$ENV{ProgramW6432}/EMBREE/lib"
PATH_SUFFIXES ${EMBREE_SEARCH_LIB_PATHSUFFIXE}
)
set(EMBREE_LIBRARIES ${EMBREE_LIBRARY})
MARK_AS_ADVANCED(EMBREE_INCLUDE_DIR EMBREE_LIBRARIES)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(EMBREE
REQUIRED_VARS EMBREE_INCLUDE_DIR EMBREE_LIBRARIES
FAIL_MESSAGE "EMBREE wasn't found correctly. Set EMBREE_DIR to the root SDK installation directory."
)
if(NOT EMBREE_FOUND)
set(EMBREE_DIR "" CACHE STRING "Path to EMBREE install directory")
endif()

View File

@ -0,0 +1,110 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## Try to find the FFMPEG library
## Once done this will define
##
## FFMPEG_FOUND - system has FFmpeg
## FFMPEG_INCLUDE_DIR - The FFmpeg include directory
## FFMPEG_LIBRARIES - The libraries needed to use FFmpeg
## FFMPEG_DYNAMIC_LIBS - DLLs for windows
if(NOT FFMPEG_DIR)
set(FFMPEG_DIR "$ENV{FFMPEG_DIR}" CACHE PATH "FFMPEG_DIR root directory")
endif()
if(FFMPEG_DIR)
file(TO_CMAKE_PATH ${FFMPEG_DIR} FFMPEG_DIR)
endif()
MACRO(FFMPEG_FIND varname shortname headername)
# Path to include dirs
FIND_PATH(FFMPEG_${varname}_INCLUDE_DIRS
NAMES "lib${shortname}/${headername}"
PATHS
"${FFMPEG_DIR}/include" # modify this to adapt according to OS/compiler
"/usr/include"
"/usr/include/ffmpeg"
)
#Add libraries
IF(${FFMPEG_${varname}_INCLUDE_DIRS} STREQUAL "FFMPEG_${varname}_INCLUDE_DIR-NOTFOUND")
MESSAGE(STATUS "Can't find includes for ${shortname}...")
ELSE()
FIND_LIBRARY(FFMPEG_${varname}_LIBRARIES
NAMES ${shortname}
PATHS
${FFMPEG_DIR}/lib
"/usr/lib"
"/usr/lib64"
"/usr/local/lib"
"/usr/local/lib64"
)
# set libraries and other variables
SET(FFMPEG_${varname}_FOUND 1)
SET(FFMPEG_${varname}_INCLUDE_DIRS ${FFMPEG_${varname}_INCLUDE_DIR})
SET(FFMPEG_${varname}_LIBS ${FFMPEG_${varname}_LIBRARIES})
ENDIF()
ENDMACRO(FFMPEG_FIND)
#Calls to ffmpeg_find to get librarires ------------------------------
FFMPEG_FIND(LIBAVFORMAT avformat avformat.h)
FFMPEG_FIND(LIBAVDEVICE avdevice avdevice.h)
FFMPEG_FIND(LIBAVCODEC avcodec avcodec.h)
FFMPEG_FIND(LIBAVUTIL avutil avutil.h)
FFMPEG_FIND(LIBSWSCALE swscale swscale.h)
# check if libs are found and set FFMPEG related variables
#SET(FFMPEG_FOUND "NO")
IF(FFMPEG_LIBAVFORMAT_FOUND
AND FFMPEG_LIBAVDEVICE_FOUND
AND FFMPEG_LIBAVCODEC_FOUND
AND FFMPEG_LIBAVUTIL_FOUND
AND FFMPEG_LIBSWSCALE_FOUND)
# All ffmpeg libs are here
SET(FFMPEG_FOUND "YES")
SET(FFMPEG_INCLUDE_DIR ${FFMPEG_LIBAVFORMAT_INCLUDE_DIRS})
SET(FFMPEG_LIBRARY_DIRS ${FFMPEG_LIBAVFORMAT_LIBRARY_DIRS})
SET(FFMPEG_LIBRARIES
${FFMPEG_LIBAVFORMAT_LIBS}
${FFMPEG_LIBAVDEVICE_LIBS}
${FFMPEG_LIBAVCODEC_LIBS}
${FFMPEG_LIBAVUTIL_LIBS}
${FFMPEG_LIBSWSCALE_LIBS} )
# add dynamic libraries
if(WIN32)
file(GLOB FFMPEG_DYNAMIC_LIBS "${FFMPEG_DIR}/bin/*.dll")
if(NOT FFMPEG_DYNAMIC_LIBS)
message("FFMPEG_DYNAMIC_LIBS is missing...")
endif()
set(FFMPEG_DYNAMIC_LIBS ${FFMPEG_DYNAMIC_LIBS} CACHE PATH "Windows dll location")
endif()
mark_as_advanced(FFMPEG_INCLUDE_DIR FFMPEG_LIBRARY_DIRS FFMPEG_LIBRARIES FFMPEG_DYNAMIC_LIBS)
ELSE ()
MESSAGE(STATUS "Could not find FFMPEG")
ENDIF()
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFMPEG
REQUIRED_VARS FFMPEG_INCLUDE_DIR FFMPEG_LIBRARIES
FAIL_MESSAGE "FFmpeg wasn't found correctly. Set FFMPEG_DIR to the root SDK installation directory."
)
if(NOT FFMPEG_FOUND)
set(FFMPEG_DIR "" CACHE STRING "Path to FFmpeg install directory")
endif()

View File

@ -0,0 +1,109 @@
##=============================================================================
##
## Copyright (c) Kitware, Inc.
## All rights reserved.
## See LICENSE.txt for details.
##
## This software is distributed WITHOUT ANY WARRANTY; without even
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##
## Copyright 2016 Sandia Corporation.
## Copyright 2016 UT-Battelle, LLC.
## Copyright 2016 Los Alamos National Security.
##
## Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
## the U.S. Government retains certain rights in this software.
## Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
## Laboratory (LANL), the U.S. Government retains certain rights in
## this software.
##
##=============================================================================
# Try to find EGL library and include dir.
# Once done this will define
#
# GLFW_FOUND
# GLFW_INCLUDE_DIR
# GLFW_LIBRARY
#
include(FindPackageHandleStandardArgs)
if (WIN32)
find_path( GLFW_INCLUDE_DIR
NAMES
GLFW/glfw3.h
PATHS
${PROJECT_SOURCE_DIR}/shared_external/glfw/include
${PROJECT_SOURCE_DIR}/../shared_external/glfw/include
${GLFW_LOCATION}/include
$ENV{GLFW_LOCATION}/include
$ENV{PROGRAMFILES}/GLFW/include
${GLFW_LOCATION}
$ENV{GLFW_LOCATION}
DOC "The directory where GLFW/glfw3.h resides" )
if(ARCH STREQUAL "x86")
find_library( GLFW_LIBRARY
NAMES
glfw3
PATHS
${GLFW_LOCATION}/lib
$ENV{GLFW_LOCATION}/lib
$ENV{PROGRAMFILES}/GLFW/lib
DOC "The GLFW library")
else()
find_library( GLFW_LIBRARY
NAMES
glfw3
PATHS
${GLFW_LOCATION}/lib
$ENV{GLFW_LOCATION}/lib
$ENV{PROGRAMFILES}/GLFW/lib
DOC "The GLFW library")
endif()
endif ()
if (${CMAKE_HOST_UNIX})
message("GFLW LOCATION " $ENV{GLFW_LOCATION} )
find_path( GLFW_INCLUDE_DIR
NAMES
GLFW/glfw3.h
PATHS
# ${GLFW_LOCATION}/include
$ENV{GLFW_LOCATION}/include
# /usr/include
# /usr/local/include
# /sw/include
# /opt/local/include
# NO_DEFAULT_PATH
DOC "The directory where GLFW/glfw3.h resides"
)
find_library( GLFW_LIBRARY
NAMES
glfw3 glfw
PATHS
# ${GLFW_LOCATION}/lib
$ENV{GLFW_LOCATION}/lib
$ENV{GLFW_LOCATION}/lib64
# /usr/lib64
# /usr/lib
# /usr/local/lib64
# /usr/local/lib
# /sw/lib
# /opt/local/lib
# /usr/lib/x86_64-linux-gnu
# NO_DEFAULT_PATH
DOC "The GLFW library")
set( GLFW_INCLUDE_DIR $ENV{GLFW_LOCATION}/include )
set( GLFW_LIBRARY $ENV{GLFW_LOCATION}/lib64/libglfw3.a )
message("*************==========> FindGLFW .cmake " ${GLFW_INCLUDE_DIR} " LIB " ${GLFW_LIBRARY} )
endif ()
find_package_handle_standard_args(GLFW DEFAULT_MSG
GLFW_INCLUDE_DIR
GLFW_LIBRARY
)
mark_as_advanced( GLFW_FOUND )

View File

@ -0,0 +1,337 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## This file should be include and use only on WIN32 OS and once
## It allow to auto check/download and use a preconfigured 3rdParty binaries for cmake usage
## It use the downloadAndExtractZipFile cmake module to work.
##
if(__Win3rdParty_cmake_INCLUDED__)
return()
else()
set(__Win3rdParty_cmake_INCLUDED__ ON)
endif()
##
## To be sure to reset an empty cached variable but keep any other kind of variables
##
## Usage:
## check_cached_var(<var> <resetedCachedValue> <cacheType> <cacheDoc> [FORCE])
##
## <var> is the cached cmake variable you need to reset
## <resetedCachedValue> is the new default value of the reseted cached cmake variable
## <cacheType> is the kind of GUI cache input can be : FILEPATH; PATH; STRING or BOOL
## <cacheDoc> is the associated GUI cache input documentation display in the GUI
## FORCE option could be use to reset a cached variable even if it is not empty.
##
macro(check_cached_var var resetedCachedValue cacheType cacheDoc)
# message(STATUS "inside check_cached_var macro. argn=${ARGN}")
cmake_parse_arguments(ccv "FORCE" "" "" ${ARGN})
if(ccv_FORCE)
set(FORCE FORCE)
else()
set(FORCE )
endif()
if(NOT ${var} OR ccv_FORCE)
unset(${var} CACHE)
# message(STATUS "setting new cache value. var ${var} = ${resetedCachedValue}")
set(${var} "${resetedCachedValue}" CACHE ${cacheType} "${cacheDoc}" ${FORCE})
endif()
endmacro()
##
## Win3rdParty function allow to specify a directory which contain all necessary windows dependenties.
## By uploading 3rdParty directory (which contain dependencies, *.lib, *.dll... for a specific version of compiler) onto Gforge file tab,
## you get back an URL of download you can give to this function with a directory name. So you can provide multiple 3rdParty version of same dependencies (MSVC11, MSVC12...).
## By providing a prefix to this function, you allow to use different kind of 3rdParty which can be handled by CMAKE OPTIONS depending on what your framework need for example.
##
## Usage 1:
## Win3rdParty(<prefix> MSVC<XX> <DirName> <URL>
## [MSVC<XX> <DirName> <URL>] [...]
## [VCID] [DEFAULT_USE] [VERBOSE] )
##
## * <prefix> allow to identify which 3rdParty you process (prefix name)
## * MSVC<XX> flag could be MSVC11 or MSVC12 (any element of the MSVC_VERSIONS_LIST) and refer to a 3rdParty compiler with :
## * <DirName> which will be the local pathName of the downloaded 3rdParty : relative to CMAKE_BINARY_DIR
## * <URL> which is the link location of the 3rdParty zip
## * VCID flag will make available a cache variable ${prefix}_WIN3RDPARTY_VCID
## * DEFAULT_USE flag [ON|OFF] may be used to set default value of cmake cached variable : <prefix>_WIN3RDPARTY_USE [default to ON]
##
## WARNING:
## This function define CACHE variables you can use after :
## * ${prefix}_WIN3RDPARTY_USE : allow to check/downloaded win3rdParty dir (it will force the cached variables for this dependency folder generally <prefix>_DIR>)
## * ${prefix}_WIN3RDPARTY_DIR : where is your local win3rdParty dir (the PATH)
## * ${prefix}_WIN3RDPARTY_VCID : [if VCID flag is used] the MSVC id (commonly used to prefix/suffix library name, see boost or CGAL)
##
## If you want to add a win3rdParty version, please:
## 1- build dependencies on your local side with the compiler you want
## 2- build your own zip with your built dependencies
## 3- upload it (onto the forge where the project is stored) and copy the link location in order to use it for this function
## 4- if you just introduced a new MSVC version, add it to the MSVC_VERSIONS_LIST bellow
##
## In a second pass, you can also use this function to set necessary cmake cached variables in order to let cmake find packages of these 3rdParty.
##
## Usage 2:
## win3rdParty(<prefix> [VERBOSE] MULTI_SET|SET
## CHECK_CACHED_VAR <cmakeVar> <cmakeCacheType> [LIST] <cmakeValue> [DOC <stringToolTips>]
## [ CHECK_CACHED_VAR <cmakeVar> <cmakeCacheType> [LIST] <cmakeValue> [DOC <stringToolTips>] ] [...]
##
## * MULTI_SET or SET flags are used to tell cmake that all next arguments will use repeated flags with differents entries (SET mean we will provide only one set of arguments, without repetition)
## * CHECK_CACHED_VAR are the repeated flag which contain differents entries
## * <cmakeVar> is the cmake variable you want to be cached for the project
## * <cmakeCacheType> is the kind of cmake variable (couble be: FILEPATH; PATH; STRING or BOOL) => see check_cached_var.
## * LIST optional flag could be used with CHECK_CACHED_VAR when <cmakeCacheType> = STRING. It allow to handle multiple STRINGS value list.
## * <cmakeValue> is the value of the variable (if FILEPATH, PATH or STRING: use quotes, if BOOL : use ON/OFF)
## * DOC optional flag is used to have a tooltips info about this new cmake variable entry into the GUI (use quotes).
##
## Full example 1 :
## win3rdParty(COMMON MSVC11 "win3rdParty-MSVC11" "https://path.to/an.archive.7z"
## SET CHECK_CACHED_VAR SuiteSparse_DIR PATH "SuiteSparse-4.2.1" DOC "default empty doc"
## )
##
## WARNING:
## For the 2nd usage (with MULTI_SET), if you planned to set some CACHED_VAR using/composed by ${prefix}_WIN3RDPARTY_* just set in this macro (usage 1),
## then (due to the not yet existing var) you will need to call this function 2 times :
## One for the 1st usage (downloading of the current compiler 3rdParty).
## One for the MLUTI_SET flag which will use existsing ${prefix}_WIN3RDPARTY_* cached var.
##
## Full example 2 :
## win3rdParty(COMMON MSVC11 "win3rdParty-MSVC11" "https://path.to/an.archive.7z")
## win3rdParty(COMMON MULTI_SET
## CHECK_CACHED_VAR CGAL_INCLUDE_DIR PATH "CGAL-4.3/include" DOC "default empty doc"
## CHECK_CACHED_VAR CGAL_LIBRARIES STRING LIST "debug;CGAL-4.3/lib${LIB_POSTFIX}/CGAL-${WIN3RDPARTY_COMMON_VCID}-mt-gd-4.3.lib;optimized;CGAL-4.3/lib${LIB_POSTFIX}/CGAL-${WIN3RDPARTY_COMMON_VCID}-mt-4.3.lib"
##
##
## WARNING: This function use internaly :
## * downloadAndExtractZipFile.cmake
## * parse_arguments_multi.cmake
## * check_cached_var macro
##
function(win3rdParty prefix )
# ARGV: list of all arguments given to the macro/function
# ARGN: list of remaining arguments
if(NOT WIN32)
return()
endif()
## set the handled version of MSVC
## if you plan to add a win3rdParty dir to download with a new MSVC version: build the win3rdParty dir and add the MSCV entry here.
set(MSVC_VERSIONS_LIST "MSVC17;MSVC11;MSVC12;MSVC14")
#include(CMakeParseArguments) # CMakeParseArguments is obsolete since cmake 3.5
# cmake_parse_arguments (<prefix> <options> <one_value_keywords> <multi_value_keywords> args)
# <options> : options (flags) pass to the macro
# <one_value_keywords> : options that neeed a value
# <multi_value_keywords> : options that neeed more than one value
cmake_parse_arguments(w3p "VCID" "VERBOSE;TIMEOUT;DEFAULT_USE" "${MSVC_VERSIONS_LIST};MULTI_SET;SET" ${ARGN})
# message(STATUS "value of w3p_VCID = ${w3p_VCID}")
# message(STATUS "value of w3p_VERBOSE = ${w3p_VERBOSE}")
# message(STATUS "value of w3p_TIMEOUT = ${w3p_TIMEOUT}")
# message(STATUS "value of w3p_DEFAULT_USE = ${w3p_DEFAULT_USE}")
# foreach (loop_var ${MSVC_VERSIONS_LIST})
# message(STATUS "value of w3p_${loop_var} = ${w3p_${loop_var}}")
# endforeach(loop_var)
# message(STATUS "value of w3p_MULTI_SET = ${w3p_MULTI_SET}")
# message(STATUS "value of w3p_SET = ${w3p_SET}")
# message("values for MSVC = ${w3p_MSVC14}")
if(NOT w3p_TIMEOUT)
set(w3p_TIMEOUT 300)
endif()
if(NOT DEFINED w3p_DEFAULT_USE)
set(w3p_DEFAULT_USE ON)
endif()
## 1st use (check/update|download) :
set(${prefix}_WIN3RDPARTY_USE ${w3p_DEFAULT_USE} CACHE BOOL "Use required 3rdParty binaries from ${prefix}_WIN3RDPARTY_DIR or download it if not exist")
## We want to test if each version of MSVC was filled by the function (see associated parameters)
## As CMake is running only for one version of MSVC, if that MSVC version was filled, we get back associated parameters,
## otherwise we can't use the downloadAndExtractZipFile with win3rdParty.
set(enableWin3rdParty OFF)
foreach(MSVC_VER ${MSVC_VERSIONS_LIST})
if(${MSVC_VER} AND w3p_${MSVC_VER} OR ${MSVC_TOOLSET_VERSION} EQUAL 143 AND ${MSVC_VER} STREQUAL "MSVC17")
list(LENGTH w3p_${MSVC_VER} count)
if("${count}" LESS "2")
#message(WARNING "You are using ${MSVC_VER} with ${prefix}_WIN3RDPARTY_USE=${${prefix}_WIN3RDPARTY_USE}, but win3rdParty function isn't filled for ${MSVC_VER}!")
else()
list(GET w3p_${MSVC_VER} 0 Win3rdPartyName)
list(GET w3p_${MSVC_VER} 1 Win3rdPartyUrl)
if(w3p_VCID)
## try to get the VcId of MSVC. See also MSVC_VERSION cmake var in the doc.
string(REGEX REPLACE "MS([A-Za-z_0-9-]+)" "\\1" vcId ${MSVC_VER})
string(TOLOWER ${vcId} vcId)
set(${prefix}_WIN3RDPARTY_VCID "${vcId}0" CACHE STRING "the MSVC id (commonly used to prefix/suffix library name, see boost or CGAL)")
mark_as_advanced(${prefix}_WIN3RDPARTY_VCID)
endif()
set(enableWin3rdParty ON)
set(suffixCompilerID ${MSVC_VER})
break()
endif()
endif()
endforeach()
## If previous step succeed to get MSVC dirname and URL of the current MSVC version, use it to auto download/update the win3rdParty dir
if(enableWin3rdParty AND ${prefix}_WIN3RDPARTY_USE)
if(IS_ABSOLUTE "${Win3rdPartyName}")
else()
set(Win3rdPartyName "${CMAKE_BINARY_DIR}/${Win3rdPartyName}")
endif()
if(NOT EXISTS "${Win3rdPartyName}")
file(MAKE_DIRECTORY ${Win3rdPartyName})
endif()
include(downloadAndExtractZipFile)
downloadAndExtractZipFile( "${Win3rdPartyUrl}" ## URL link location
"Win3rdParty-${prefix}-${suffixCompilerID}.7z" ## where download it: relative path, so default to CMAKE_BINARY_DIR
"${Win3rdPartyName}" ## where extract it : fullPath (default relative to CMAKE_BINARY_DIR)
CHECK_DIRTY_URL "${Win3rdPartyName}/Win3rdPartyUrl" ## last downloaded url file : fullPath (default relative to CMAKE_BINARY_DIR)
TIMEOUT ${w3p_TIMEOUT}
VERBOSE ${w3p_VERBOSE}
)
file(GLOB checkDl "${Win3rdPartyName}/*")
list(LENGTH checkDl checkDlCount)
if("${checkDlCount}" GREATER "1")
else()
message("The downloadAndExtractZipFile didn't work...?")
set(enableWin3rdParty OFF)
endif()
endif()
## Try to auto set ${prefix}_WIN3RDPARTY_DIR or let user set it manually
set(${prefix}_WIN3RDPARTY_DIR "" CACHE PATH "windows ${Win3rdPartyName} dir to ${prefix} dependencies of the project")
if(NOT ${prefix}_WIN3RDPARTY_DIR AND ${prefix}_WIN3RDPARTY_USE)
if(EXISTS "${Win3rdPartyName}")
unset(${prefix}_WIN3RDPARTY_DIR CACHE)
set(${prefix}_WIN3RDPARTY_DIR "${Win3rdPartyName}" CACHE PATH "dir to ${prefix} dependencies of the project")
endif()
endif()
if(EXISTS ${${prefix}_WIN3RDPARTY_DIR})
message(STATUS "Found a 3rdParty ${prefix} dir : ${${prefix}_WIN3RDPARTY_DIR}.")
set(enableWin3rdParty ON)
elseif(${prefix}_WIN3RDPARTY_USE)
message(WARNING "${prefix}_WIN3RDPARTY_USE=${${prefix}_WIN3RDPARTY_USE} but ${prefix}_WIN3RDPARTY_DIR=${${prefix}_WIN3RDPARTY_DIR}.")
set(enableWin3rdParty OFF)
endif()
## Final check
if(NOT enableWin3rdParty)
message("Disable ${prefix}_WIN3RDPARTY_USE (cmake cached var will be not set), due to a win3rdParty problem.")
message("You still can set ${prefix}_WIN3RDPARTY_DIR to an already downloaded Win3rdParty directory location.")
set(${prefix}_WIN3RDPARTY_USE OFF CACHE BOOL "Use required 3rdParty binaries from ${prefix}_WIN3RDPARTY_DIR or download it if not exist" FORCE)
endif()
## 2nd use : handle multi values args to set cached cmake variables in order to ease the next find_package call
if(${prefix}_WIN3RDPARTY_USE AND ${prefix}_WIN3RDPARTY_DIR)
if(w3p_VERBOSE)
message(STATUS "Try to set cmake cached variables for ${prefix} required libraries directly from : ${${prefix}_WIN3RDPARTY_DIR}.")
endif()
include(parse_arguments_multi)
# message (STATUS "before defining an override of parse_arguments_multi_function")
function(parse_arguments_multi_function ) ## overloaded function to handle all CHECK_CACHED_VAR values list (see: parse_arguments_multi)
# message(STATUS "inside overloaded parse_arguments_multi_function defined in Win3rdParty.cmake")
# message(STATUS ${ARGN})
## we know the function take 3 args : var cacheType resetedCachedValue (see check_cached_var)
cmake_parse_arguments(pamf "" "DOC" "LIST" ${ARGN})
## var and cacheType are mandatory (with the resetedCachedValue)
set(var ${ARGV0})
set(cacheType ${ARGV1})
# message(STATUS "var=${var} and cacheType=${cacheType} list=${pamf_LIST}")
if(pamf_DOC)
set(cacheDoc ${pamf_DOC})
else()
set(cacheDoc "")
endif()
if(pamf_LIST)
set(value ${pamf_LIST})
else()
# message("USING ARGV2 with value ${ARGV2}")
set(value ${ARGV2})
endif()
# message("inside override function in Win3rdparty.cmake value+ ${value}")
if("${cacheType}" MATCHES "PATH" AND EXISTS "${${prefix}_WIN3RDPARTY_DIR}/${value}")
# message("math with path")
set(resetedCachedValue "${${prefix}_WIN3RDPARTY_DIR}/${value}") ## path relative to ${prefix}_WIN3RDPARTY_DIR
elseif ("${cacheType}" MATCHES "PATH" AND EXISTS "${${prefix}_WIN3RDPARTY_DIR}")
set(resetedCachedValue "${${prefix}_WIN3RDPARTY_DIR}") ## path relative to ${prefix}_WIN3RDPARTY_DIR
elseif("${cacheType}" MATCHES "STRING")
foreach(var IN LISTS value)
if(EXISTS "${${prefix}_WIN3RDPARTY_DIR}/${var}")
list(APPEND resetedCachedValue "${${prefix}_WIN3RDPARTY_DIR}/${var}") ## string item of the string list is a path => make relative to ${prefix}_WIN3RDPARTY_DIR
else()
list(APPEND resetedCachedValue ${var}) ## string item of the string list is not an existing path => simply use the item
endif()
endforeach()
else()
set(resetedCachedValue "${value}") ## could be a BOOL or a STRING
endif()
## call our macro to reset cmake cache variable if empty
check_cached_var(${var} "${resetedCachedValue}" ${cacheType} "${cacheDoc}" FORCE)
endfunction()
# message (STATUS "after defining an override of parse_arguments_multi_function")
if(w3p_MULTI_SET)
parse_arguments_multi(CHECK_CACHED_VAR w3p_MULTI_SET ${w3p_MULTI_SET}) ## internaly will call our overloaded parse_arguments_multi_function
elseif(w3p_SET)
# message("calling set version of parse_arguments_multi with w3p_set = ${w3p_SET}")
parse_arguments_multi(CHECK_CACHED_VAR w3p_SET ${w3p_SET})
endif()
endif()
endfunction()
## cmake variables introspection to globally activate/deactivate ${prefix}_WIN3RDPARTY_USE
## This "one shot" call (only one for the next cmake configure) will automatically then reset the global variable WIN3RDPARTY_USE to UserDefined (do nothing).
## use (call it) before and after the call of all your win3rdParty functions
function(Win3rdPartyGlobalCacheAction )
set(WIN3RDPARTY_USE "UserDefined" CACHE STRING "Choose how to handle all cmake cached *_WIN3RDPARTY_USE for the next configure.\nCould be:\nUserDefined [default]\nActivateAll\nDesactivateAll" )
set_property(CACHE WIN3RDPARTY_USE PROPERTY STRINGS "UserDefined;ActivateAll;DesactivateAll" )
if(${WIN3RDPARTY_USE} MATCHES "UserDefined")
else()
if(${WIN3RDPARTY_USE} MATCHES "ActivateAll")
set(win3rdPvalue ON)
elseif(${WIN3RDPARTY_USE} MATCHES "DesactivateAll")
set(win3rdPvalue OFF)
endif()
get_cmake_property(_variableNames CACHE_VARIABLES)
foreach (_variableName ${_variableNames})
string(REGEX MATCH "[A-Za-z_0-9-]+_WIN3RDPARTY_USE" win3rdpartyUseCacheVar ${_variableName})
if(win3rdpartyUseCacheVar)
string(REGEX REPLACE "([A-Za-z_0-9-]+_WIN3RDPARTY_USE)" "\\1" win3rdpartyUseCacheVar ${_variableName})
set(${win3rdpartyUseCacheVar} ${win3rdPvalue} CACHE BOOL "Use required 3rdParty binaries from ${prefix}_WIN3RDPARTY_DIR or download it if not exist" FORCE)
message(STATUS "${win3rdpartyUseCacheVar} cached variable set to ${win3rdPvalue}.")
endif()
endforeach()
set(WIN3RDPARTY_USE "UserDefined" CACHE STRING "Choose how to handle all cmake cached *_WIN3RDPARTY_USE for the next configure.\nCould be:\nUserDefined [default]\nActivateAll\nDesactivateAll" FORCE)
message(STATUS "reset WIN3RDPARTY_USE to UserDefined.")
endif()
mark_as_advanced(WIN3RDPARTY_USE)
endfunction()

View File

@ -0,0 +1,19 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
if(__set_policies_INCLUDED__)
return()
else()
set(__set_policies_INCLUDED__ ON)
endif()
macro(setPolicies)
# No more policies to enforce
endmacro()

View File

@ -0,0 +1,324 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## Included once for all sub project.
## It contain the whole cmake instructions to find necessary common dependencies.
## 3rdParty (provided by sibr_addlibrary win3rdParty or from external packages) are then available in cmake sub projects.
##
## Do not include this file more than once but you can modify it to fit to your own project.
## So please, read it carefully because you can use on of these dependencies for your project or appen new one.
##
## As it is included after camke options, you can use conditional if(<CMAKE_PROJ_OPT>)/endif() to encapsulate your 3rdParty.
##
## win3rdParty function allowing to auto check/download/update binaries dependencies for current windows compiler
## Please open this file in order to get more documentation and usage examples.
include(Win3rdParty)
include(sibr_library)
Win3rdPartyGlobalCacheAction()
find_package(OpenGL REQUIRED)
set(OpenGL_GL_PREFERENCE "GLVND")
############
## Find GLEW
############
##for headless rendering
find_package(EGL QUIET)
if(EGL_FOUND)
add_definitions(-DGLEW_EGL)
message("Activating EGL support for headless GLFW/GLEW")
else()
message("EGL not found : EGL support for headless GLFW/GLEW is disabled")
endif()
if (MSVC11 OR MSVC12)
set(glew_multiset_arguments
CHECK_CACHED_VAR GLEW_INCLUDE_DIR PATH "glew-1.10.0/include" DOC "default empty doc"
CHECK_CACHED_VAR GLEW_LIBRARIES STRING LIST "debug;glew-1.10.0/${LIB_BUILT_DIR}/glew32d.lib;optimized;glew-1.10.0/${LIB_BUILT_DIR}/glew32.lib" DOC "default empty doc"
)
elseif (MSVC14)
set(glew_multiset_arguments
CHECK_CACHED_VAR GLEW_INCLUDE_DIR PATH "glew-2.0.0/include" DOC "default empty doc"
CHECK_CACHED_VAR GLEW_SHARED_LIBRARY_RELEASE PATH "glew-2.0.0/${LIB_BUILT_DIR}/glew32.lib"
CHECK_CACHED_VAR GLEW_STATIC_LIBRARY_RELEASE PATH "glew-2.0.0/${LIB_BUILT_DIR}/glew32s.lib"
CHECK_CACHED_VAR GLEW_SHARED_LIBRARY_DEBUG PATH "glew-2.0.0/${LIB_BUILT_DIR}/glew32d.lib"
CHECK_CACHED_VAR GLEW_STATIC_LIBRARY_DEBUG PATH "glew-2.0.0/${LIB_BUILT_DIR}/glew32sd.lib"
)
else ()
message("There is no provided GLEW library for your compiler, relying on find_package to find it")
endif()
sibr_addlibrary(NAME GLEW #VERBOSE ON
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/glew-1.10.0.7z"
MSVC12 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/glew-1.10.0.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/glew-2.0.0.7z" # using recompiled version of glew
MULTI_SET ${glew_multiset_arguments}
)
set(GLEW_VERBOSE ON)
FIND_PACKAGE(GLEW REQUIRED)
IF(GLEW_FOUND)
INCLUDE_DIRECTORIES(${GLEW_INCLUDE_DIR})
ELSE(GLEW_FOUND)
MESSAGE("GLEW not found. Set GLEW_DIR to base directory of GLEW.")
ENDIF(GLEW_FOUND)
##############
## Find ASSIMP
##############
if (MSVC11 OR MSVC12)
set(assimp_set_arguments
CHECK_CACHED_VAR ASSIMP_DIR PATH "Assimp_3.1_fix"
)
elseif (MSVC14)
set(assimp_set_arguments
CHECK_CACHED_VAR ASSIMP_DIR PATH "Assimp-4.1.0"
)
else ()
message("There is no provided ASSIMP library for your compiler, relying on find_package to find it")
endif()
sibr_addlibrary(NAME ASSIMP #VERBOSE ON
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/Assimp_3.1_fix.7z"
MSVC12 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/Assimp_3.1_fix.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/Assimp-4.1.0.7z"
MULTI_SET
${assimp_set_arguments}
)
find_package(ASSIMP REQUIRED)
include_directories(${ASSIMP_INCLUDE_DIR})
################
## Find FFMPEG
################
sibr_addlibrary(NAME FFMPEG
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/ffmpeg.zip"
MSVC12 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/ffmpeg.zip"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/ffmpeg-4.0.2-win64-win3rdParty.7z"
SET CHECK_CACHED_VAR FFMPEG_DIR PATH ${FFMPEG_WIN3RDPARTY_DIR}
)
find_package(FFMPEG)
include_directories(${FFMPEG_INCLUDE_DIR})
## COMMENT OUT ALL FFMPEG FOR CLUSTER
###################
## Find embree3
###################
sibr_addlibrary(
NAME embree3
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/embree2.7.0.x64.windows.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/embree-3.6.1.x64.vc14.windows.7z" # TODO SV: provide a valid version if required
)
# CLUSTER
#find_package(embree 3.0 REQUIRED PATHS "/data/graphdeco/share/embree/usr/local/lib64/cmake/" )
find_package(embree 3.0 )
###################
## Find eigen3
###################
sibr_addlibrary(
NAME eigen3
#MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/eigen-eigen-dc6cfdf9bcec.7z"
#MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/eigen-eigen-dc6cfdf9bcec.7z" # TODO SV: provide a valid version if required
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/eigen3.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/eigen3.7z"
SET CHECK_CACHED_VAR eigen3_DIR PATH "eigen/share/eigen3/cmake"
)
include_directories(/usr/include/eigen3)
add_definitions(-DEIGEN_INITIALIZE_MATRICES_BY_ZERO)
#############
## Find Boost
#############
set(Boost_REQUIRED_COMPONENTS "system;chrono;filesystem;date_time" CACHE INTERNAL "Boost Required Components")
if (WIN32)
# boost multiset arguments
if (MSVC11 OR MSVC12)
set(boost_multiset_arguments
CHECK_CACHED_VAR BOOST_ROOT PATH "boost_1_55_0"
CHECK_CACHED_VAR BOOST_INCLUDEDIR PATH "boost_1_55_0"
CHECK_CACHED_VAR BOOST_LIBRARYDIR PATH "boost_1_55_0/${LIB_BUILT_DIR}"
#CHECK_CACHED_VAR Boost_COMPILER STRING "-${Boost_WIN3RDPARTY_VCID}" DOC "vcid (eg: -vc110 for MSVC11)"
CHECK_CACHED_VAR Boost_COMPILER STRING "-vc110" DOC "vcid (eg: -vc110 for MSVC11)" # NOTE: if it doesnt work, uncomment this option and set the right value for VisualC id
)
elseif (MSVC14)
set(boost_multiset_arguments
CHECK_CACHED_VAR BOOST_ROOT PATH "boost-1.71"
CHECK_CACHED_VAR BOOST_INCLUDEDIR PATH "boost-1.71"
CHECK_CACHED_VAR BOOST_LIBRARYDIR PATH "boost-1.71/${LIB_BUILT_DIR}"
CHECK_CACHED_VAR Boost_COMPILER STRING "-vc141" DOC "vcid (eg: -vc110 for MSVC11)" # NOTE: if it doesnt work, uncomment this option and set the right value for VisualC id
)
option(BOOST_MINIMAL_VERSION "Only get minimal Boost dependencies" ON)
if(${BOOST_MINIMAL_VERSION})
set(BOOST_MSVC14_ZIP "boost-1.71-ibr-minimal.7z")
else()
set(BOOST_MSVC14_ZIP "boost-1.71.7z")
endif()
else ()
message("There is no provided Boost library for your compiler, relying on find_package to find it")
endif()
sibr_addlibrary(NAME Boost VCID TIMEOUT 600 #VERBOSE ON
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/boost_1_55_0.7z"
MSVC12 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/boost_1_55_0.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/${BOOST_MSVC14_ZIP}" # boost compatible with msvc14
MULTI_SET ${boost_multiset_arguments}
CHECK_CACHED_VAR Boost_NO_SYSTEM_PATHS BOOL ON DOC "Set to ON to disable searching in locations not specified by these boost cached hint variables"
CHECK_CACHED_VAR Boost_NO_BOOST_CMAKE BOOL ON DOC "Set to ON to disable the search for boost-cmake (package cmake config file if boost was built with cmake)"
)
if(NOT Boost_COMPILER AND Boost_WIN3RDPARTY_USE)
message(WARNING "Boost_COMPILER is not set and it's needed.")
endif()
endif()
find_package(Boost 1.65.0 REQUIRED COMPONENTS ${Boost_REQUIRED_COMPONENTS})
# for CLUSTER
##find_package(Boost 1.58.0 REQUIRED COMPONENTS ${Boost_REQUIRED_COMPONENTS})
if(WIN32)
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/EHsc>")
#add_definitions(/EHsc)
endif()
if(Boost_LIB_DIAGNOSTIC_DEFINITIONS)
add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
endif()
#if(WIN32)
add_definitions(-DBOOST_ALL_DYN_LINK -DBOOST_ALL_NO_LIB)
#endif()
include_directories(${BOOST_INCLUDEDIR} ${Boost_INCLUDE_DIRS})
link_directories(${BOOST_LIBRARYDIR} ${Boost_LIBRARY_DIRS})
##############
## Find OpenMP
##############
find_package(OpenMP)
##############
## Find OpenCV
##############
if (WIN32)
if (${MSVC_TOOLSET_VERSION} EQUAL 143)
MESSAGE("SPECIAL OPENCV HANDLING")
set(opencv_set_arguments
CHECK_CACHED_VAR OpenCV_DIR PATH "install" ## see OpenCVConfig.cmake
)
elseif (MSVC11 OR MSVC12)
set(opencv_set_arguments
CHECK_CACHED_VAR OpenCV_DIR PATH "opencv/build" ## see OpenCVConfig.cmake
)
elseif (MSVC14)
set(opencv_set_arguments
CHECK_CACHED_VAR OpenCV_DIR PATH "opencv-4.5.0/build" ## see OpenCVConfig.cmake
)
else ()
message("There is no provided OpenCV library for your compiler, relying on find_package to find it")
endif()
else()
message("There is no provided OpenCV library for your compiler, relying on find_package to find it")
endif()
sibr_addlibrary(NAME OpenCV #VERBOSE ON
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/sibr/~0.9/opencv.7z"
MSVC12 "https://repo-sam.inria.fr/fungraph/dependencies/sibr/~0.9/opencv.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/sibr/~0.9/opencv-4.5.0.7z" # opencv compatible with msvc14 and with contribs
MSVC17 "https://repo-sam.inria.fr/fungraph/dependencies/sibr/~0.9/opencv4-8.7z"
SET ${opencv_set_arguments}
)
find_package(OpenCV 4.5 REQUIRED) ## Use directly the OpenCVConfig.cmake provided
## FOR CLUSTER
###find_package(OpenCV 4.5 REQUIRED PATHS "/data/graphdeco/share/opencv/usr/local/lib64/cmake/opencv4/" ) ## Use directly the OpenCVConfig.cmake provided
##https://stackoverflow.com/questions/24262081/cmake-relwithdebinfo-links-to-debug-libs
set_target_properties(${OpenCV_LIBS} PROPERTIES MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE)
add_definitions(-DOPENCV_TRAITS_ENABLE_DEPRECATED)
if(OpenCV_INCLUDE_DIRS)
foreach(inc ${OpenCV_INCLUDE_DIRS})
if(NOT EXISTS ${inc})
set(OpenCV_INCLUDE_DIR "" CACHE PATH "additional custom include DIR (in case of trouble to find it (fedora 17 opencv package))")
endif()
endforeach()
if(OpenCV_INCLUDE_DIR)
list(APPEND OpenCV_INCLUDE_DIRS ${OpenCV_INCLUDE_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
endif()
endif()
###################
## Find GLFW
###################
sibr_addlibrary(
NAME glfw3
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/glfw-3.2.1.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/glfw-3.2.1.7z" # TODO SV: provide a valid version if required
SET CHECK_CACHED_VAR glfw3_DIR PATH "glfw-3.2.1"
)
### FOR CLUSTER COMMENT OUT lines above, uncomment lines below
##find_package(GLFW REQUIRED 3.3 )
##message("***********=============> GLFW IS " ${GLFW_LIBRARY})
##message("***********=============> GLFW IS " ${GLFW_LIBRARIES})
find_package(glfw3 REQUIRED)
sibr_gitlibrary(TARGET imgui
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/imgui.git"
GIT_TAG "741fb3ab6c7e1f7cef23ad0501a06b7c2b354944"
)
## FOR CLUSTER COMMENT OUT nativefiledialog
sibr_gitlibrary(TARGET nativefiledialog
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/nativefiledialog.git"
GIT_TAG "ae2fab73cf44bebdc08d997e307c8df30bb9acec"
)
sibr_gitlibrary(TARGET mrf
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/mrf.git"
GIT_TAG "30c3c9494a00b6346d72a9e37761824c6f2b7207"
)
sibr_gitlibrary(TARGET nanoflann
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/nanoflann.git"
GIT_TAG "7a20a9ac0a1d34850fc3a9e398fc4a7618e8a69a"
)
sibr_gitlibrary(TARGET picojson
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/picojson.git"
GIT_TAG "7cf8feee93c8383dddbcb6b64cf40b04e007c49f"
)
sibr_gitlibrary(TARGET rapidxml
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/rapidxml.git"
GIT_TAG "069e87f5ec5ce1745253bd64d89644d6b894e516"
)
sibr_gitlibrary(TARGET xatlas
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/xatlas.git"
GIT_TAG "0fbe06a5368da13fcdc3ee48d4bdb2919ed2a249"
INCLUDE_DIRS "source/xatlas"
)
Win3rdPartyGlobalCacheAction()

View File

@ -0,0 +1,243 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## downloadAndExtractZipFile cmake function
## Provide a way to download zip file from public internet ZIP_URL host
## and to extract it in a specific EXCTRATED_ZIP_PATH destination.
## This function use 7-Zip external tool to maximize the compatibles formats.
## This will be not download again if the EXCTRATED_ZIP_PATH already exist and DL_FORCE is set to OFF.
## This will try to unzip file if already exist in the ZIP_DL_PATH.
##
## If EXCTRATED_ZIP_PATH and/or ZIP_DL_PATH are not full path,
## it will be interpreted relative to CMAKE_BINARY_DIR
##
## Usage example :
## include(downloadAndExtractZipFile)
## downloadAndExtractZipFile(
## http://www.cs.cornell.edu/~snavely/bundler/distr/bundler-v0.4-source.zip
## ${CMAKE_BINARY_DIR}/Bundler/bundler-v0.4-source.zip
## ${CMAKE_BINARY_DIR}/Bundler
## [DL_FORCE ON|OFF]
## [TIMEOUT]
## [CHECK_DIRTY_URL]
## )
##
## option DL_FORCE will redownload the zip file [deafult to OFF]
## option TIMEOUT will end the unzip process after this period of time [default to 600s]
## option CHECK_DIRTY_URL will write into the given file the downloaded URL and then,
## next time, if the URL was updated, it detect it with this file
## and will download the last version. This prevent to alway set manually DL_FORCE to ON...
##
if(__downloadAndExtractZipFile_cmake_INCLUDED__)
return()
else()
set(__downloadAndExtractZipFile_cmake_INCLUDED__ ON)
endif()
function(downloadAndExtractZipFile ZIP_URL ZIP_DL_PATH EXCTRATED_ZIP_PATH)
# message(STATUS "zipUrl=${ZIP_URL} zipDlPath=${ZIP_DL_PATH} extractedZipPath=${EXCTRATED_ZIP_PATH}")
cmake_parse_arguments(dwnlezf "" "VERBOSE;DL_FORCE;TIMEOUT;CHECK_DIRTY_URL" "" ${ARGN})
set(PROGRAMFILESx86 "PROGRAMFILES(x86)")
## Check entries mandatory args
if(IS_ABSOLUTE "${ZIP_DL_PATH}")
else()
set(ZIP_DL_PATH "${CMAKE_BINARY_DIR}/${ZIP_DL_PATH}")
endif()
if(IS_ABSOLUTE "${EXCTRATED_ZIP_PATH}")
else()
set(EXCTRATED_ZIP_PATH "${CMAKE_BINARY_DIR}/${EXCTRATED_ZIP_PATH}")
endif()
if(NOT EXISTS "${EXCTRATED_ZIP_PATH}")
file(MAKE_DIRECTORY ${EXCTRATED_ZIP_PATH})
endif()
# SB: Once, one of downloaded zip was corrupted by an error message coming from the server.
if(EXISTS "${ZIP_DL_PATH}")
# So I check for removing such corrupted files
message("Removing previous ${ZIP_DL_PATH} (might be corrupted)")
file(REMOVE "${ZIP_DL_PATH}")
if(EXISTS "${dwnlezf_CHECK_DIRTY_URL}")
# and remove the previous (corrupted) made 'Win3rdPartyUrl' file
file(REMOVE "${dwnlezf_CHECK_DIRTY_URL}")
endif()
endif()
## Check entries optional args
macro(readDirtyUrl )
if(dwnlezf_CHECK_DIRTY_URL)
if(IS_ABSOLUTE "${dwnlezf_CHECK_DIRTY_URL}")
else()
set(dwnlezf_CHECK_DIRTY_URL "${CMAKE_BINARY_DIR}/${dwnlezf_CHECK_DIRTY_URL}")
endif()
get_filename_component(unzipDir ${EXCTRATED_ZIP_PATH} NAME)
get_filename_component(unzipPath ${EXCTRATED_ZIP_PATH} PATH)
message(STATUS "Checking ${unzipDir} [from ${unzipPath}]...")
if(EXISTS "${dwnlezf_CHECK_DIRTY_URL}")
get_filename_component(CHECK_DIRTY_URL_FILENAME ${dwnlezf_CHECK_DIRTY_URL} NAME)
file(STRINGS "${dwnlezf_CHECK_DIRTY_URL}" contents)
list(GET contents 0 downloadURL)
list(REMOVE_AT contents 0)
if("${downloadURL}" MATCHES "${ZIP_URL}")
if(dwnlezf_VERBOSE)
message(STATUS "Your downloaded version (URL) seems to be up to date. Let me check if nothing is missing... (see ${dwnlezf_CHECK_DIRTY_URL}).")
endif()
file(GLOB PATHNAME_PATTERN_LIST "${EXCTRATED_ZIP_PATH}/*") ## is there something inside the downloaded destination ?
unset(NAME_PATTERN_LIST)
foreach(realPathPattern ${PATHNAME_PATTERN_LIST})
get_filename_component(itemName ${realPathPattern} NAME)
list(APPEND NAME_PATTERN_LIST ${itemName})
endforeach()
if(NAME_PATTERN_LIST)
foreach(item ${contents})
list(FIND NAME_PATTERN_LIST ${item} id)
if(${id} MATCHES "-1")
message(STATUS "${item} is missing, your downloaded version content changed, need to redownload it.")
set(ZIP_DL_FORCE ON)
break()
else()
list(REMOVE_AT NAME_PATTERN_LIST ${id})
set(ZIP_DL_FORCE OFF)
endif()
endforeach()
if(NOT ZIP_DL_FORCE AND NAME_PATTERN_LIST)
message("Yours seems to be up to date (regarding to ${CHECK_DIRTY_URL_FILENAME})!\nBut there are additional files/folders into your downloaded destination (feel free to clean it if you want).")
foreach(item ${NAME_PATTERN_LIST})
if(item)
message("${item}")
endif()
endforeach()
endif()
endif()
else()
set(ZIP_DL_FORCE ON)
message(STATUS "Your downloaded version is dirty (too old).")
endif()
else()
file(GLOB PATHNAME_PATTERN_LIST "${EXCTRATED_ZIP_PATH}/*") ## is there something inside the downloaded destination ?
if(NOT PATHNAME_PATTERN_LIST)
message("We found nothing into ${EXCTRATED_ZIP_PATH}, we will try to download it for you now.")
endif()
set(ZIP_DL_FORCE ON)
endif()
endif()
endmacro()
readDirtyUrl()
if(NOT ZIP_DL_FORCE)
return() ## do not need to further (as we are up to date, just exit the function
endif()
macro(writeDirtyUrl )
if(dwnlezf_CHECK_DIRTY_URL)
file(WRITE "${dwnlezf_CHECK_DIRTY_URL}" "${ZIP_URL}\n")
file(GLOB PATHNAME_PATTERN_LIST "${EXCTRATED_ZIP_PATH}/*") ## is there something inside the downloaded destination ?
unset(NAME_PATTERN_LIST)
foreach(realPathPattern ${PATHNAME_PATTERN_LIST})
get_filename_component(itemName ${realPathPattern} NAME)
list(APPEND NAME_PATTERN_LIST ${itemName})
endforeach()
if(NAME_PATTERN_LIST)
foreach(item ${NAME_PATTERN_LIST})
file(APPEND "${dwnlezf_CHECK_DIRTY_URL}" "${item}\n")
endforeach()
endif()
endif()
endmacro()
if(dwnlezf_DL_FORCE)
set(ZIP_DL_FORCE ON)
endif()
if(NOT dwnlezf_TIMEOUT)
set(dwnlezf_TIMEOUT 600)
endif()
math(EXPR dwnlezf_TIMEOUT_MIN "${dwnlezf_TIMEOUT}/60")
macro(unzip whichZipFile)
if(NOT SEVEN_ZIP_CMD)
find_program(SEVEN_ZIP_CMD NAMES 7z 7za p7zip DOC "7-zip executable" PATHS "$ENV{PROGRAMFILES}/7-Zip" "$ENV{${PROGRAMFILESx86}}/7-Zip" "$ENV{ProgramW6432}/7-Zip")
endif()
if(SEVEN_ZIP_CMD)
if(dwnlezf_VERBOSE)
message(STATUS "UNZIP: please, WAIT UNTIL ${SEVEN_ZIP_CMD} finished...\n(no more than ${dwnlezf_TIMEOUT_MIN} min)")
else()
message(STATUS "UNZIP...wait...")
endif()
execute_process( COMMAND ${SEVEN_ZIP_CMD} x ${whichZipFile} -y
WORKING_DIRECTORY ${EXCTRATED_ZIP_PATH} TIMEOUT ${dwnlezf_TIMEOUT}
RESULT_VARIABLE resVar OUTPUT_VARIABLE outVar ERROR_VARIABLE errVar
)
if(${resVar} MATCHES "0")
if(dwnlezf_VERBOSE)
message(STATUS "SUCESS to unzip in ${EXCTRATED_ZIP_PATH}. Now we can remove the downloaded zip file.")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${whichZipFile})
mark_as_advanced(SEVEN_ZIP_CMD)
else()
message(WARNING "something wrong in ${EXCTRATED_ZIP_PATH}\n with \"${SEVEN_ZIP_CMD} x ${whichZipFile} -y\", redo or try to unzip by yourself...")
message("unzip: resVar=${resVar}")
message("unzip: outVar=${outVar}")
message("unzip: errVar=${errVar}")
message("unzip: failed or canceled or timeout")
endif()
else()
message(WARNING "You need 7zip (http://www.7-zip.org/download.html) to unzip the downloaded dir.")
set(SEVEN_ZIP_CMD "" CACHE FILEPATH "7-zip executable")
mark_as_advanced(CLEAR SEVEN_ZIP_CMD)
endif()
endmacro()
if(dwnlezf_VERBOSE)
message(STATUS "Trying to look ${ZIP_DL_PATH} if a zip file exist...")
endif()
if(EXISTS "${ZIP_DL_PATH}")
## already downloaded, so just unzip it
unzip(${ZIP_DL_PATH})
writeDirtyUrl()
elseif(ZIP_DL_FORCE)
## the download part (+ unzip)
message(STATUS "Let me try to download package for you : ${ZIP_URL}")
if(dwnlezf_VERBOSE)
message(STATUS "Downloading...\n SRC=${ZIP_URL}\n DEST=${ZIP_DL_PATH}.tmp\n INACTIVITY_TIMEOUT=180s")
endif()
file(DOWNLOAD ${ZIP_URL} ${ZIP_DL_PATH}.tmp INACTIVITY_TIMEOUT 360 STATUS status SHOW_PROGRESS)
list(GET status 0 numResult)
if(${numResult} MATCHES "0")
if(dwnlezf_VERBOSE)
message(STATUS "Download succeed, so let me rename the tmp file to unzip it")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -E rename ${ZIP_DL_PATH}.tmp ${ZIP_DL_PATH})
unzip(${ZIP_DL_PATH})
writeDirtyUrl()
else()
list(GET status 1 errMsg)
message(WARNING "DOWNLOAD ${ZIP_URL} to ${ZIP_DL_PATH} failed\n:${errMsg}")
message(WARNING "OK, you need to download the ${ZIP_URL} manually and put it into ${ZIP_DL_PATH}")
message("Take a look at the project website page to check available URL.")
endif()
endif()
## clean up the tmp downloaded file
if(EXISTS "${ZIP_DL_PATH}.tmp")
execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${ZIP_DL_PATH}.tmp)
endif()
endfunction()

View File

@ -0,0 +1,114 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
if(__git_describe_INCLUDED__)
return()
else()
set(__git_describe_INCLUDED__ ON)
endif()
find_package(Git)
if(Git_FOUND)
message(STATUS "Git found: ${GIT_EXECUTABLE}")
else()
message(FATAL_ERROR "Git not found. Aborting")
endif()
macro(git_describe)
cmake_parse_arguments(GIT_DESCRIBE "" "GIT_URL;GIT_BRANCH;GIT_COMMIT_HASH;GIT_TAG;GIT_VERSION;PATH" "" ${ARGN})
if(NOT GIT_DESCRIBE_PATH)
set(GIT_DESCRIBE_PATH ${CMAKE_SOURCE_DIR})
endif()
if(GIT_DESCRIBE_GIT_URL)
# Get the current remote
execute_process(
COMMAND git remote
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE GIT_DESCRIBE_GIT_REMOTE
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
# Get the current remote
execute_process(
COMMAND git remote get-url ${GIT_DESCRIBE_GIT_REMOTE}
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE ${GIT_DESCRIBE_GIT_URL}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if(GIT_DESCRIBE_GIT_BRANCH)
# Get the current working branch
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE ${GIT_DESCRIBE_GIT_BRANCH}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if(GIT_DESCRIBE_GIT_COMMIT_HASH)
# Get the latest abbreviated commit hash of the working branch
execute_process(
COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE ${GIT_DESCRIBE_GIT_COMMIT_HASH}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if(GIT_DESCRIBE_GIT_TAG)
# Get the tag
execute_process(
COMMAND git describe --tags --exact-match
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE ${GIT_DESCRIBE_GIT_TAG}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if(GIT_DESCRIBE_GIT_VERSION)
# Get the version from git describe
execute_process(
COMMAND git describe
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE ${GIT_DESCRIBE_GIT_VERSION}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(${GIT_DESCRIBE_GIT_VERSION} STREQUAL "")
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE GIT_DESCRIBE_GIT_VERSION_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
execute_process(
COMMAND git log -1 --format=%h
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE GIT_DESCRIBE_GIT_VERSION_COMMIT
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
set(${GIT_DESCRIBE_GIT_VERSION} "${GIT_DESCRIBE_GIT_VERSION_BRANCH}-${GIT_DESCRIBE_GIT_VERSION_COMMIT}")
endif()
endif()
endmacro()

View File

@ -0,0 +1,22 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
macro(include_once file)
get_filename_component(INCLUDE_ONCE_FILEPATH ${file} REALPATH)
string(REGEX REPLACE "(\\.|\\/+|\\:|\\\\+)" "_" INCLUDE_ONCE_FILEPATH ${INCLUDE_ONCE_FILEPATH})
get_property(INCLUDED_${INCLUDE_ONCE_FILEPATH}_LOCAL GLOBAL PROPERTY INCLUDED_${INCLUDE_ONCE_FILEPATH})
if (INCLUDED_${INCLUDE_ONCE_FILEPATH}_LOCAL)
return()
else()
set_property(GLOBAL PROPERTY INCLUDED_${INCLUDE_ONCE_FILEPATH} true)
include(${file})
endif()
endmacro()

View File

@ -0,0 +1,887 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## This file is mainly used to allow runtime installation
## There are some utilities cmake functions to ease the generic deployement (abstract common usage of cmake)...
##
## You cannot run your programm automaticaly from your CNAKE_BINARY_DIR when you build
## as it will miss all dependencies and ressources files...
## You have to run install target in order to test your programm.
##
## The only one function/macros you may use inside your sub-CMakeLists.txt (sub-project) is :
## ******************
## ibr_install_target macro => see documentation at the end of this file
## ******************
## It use these utilities cmake functions to abstract the installation in an uniform way for all sub-projects.
##
if(__install_runtime_cmake_INCLUDED__)
return()
else()
set(__install_runtime_cmake_INCLUDED__ ON)
endif()
##
## Allow to write a resource config file which contain additional ressource paths
## (used by IBR_Common Resource system to load shaders and potentialy images, plugins and so on)
##
## ADD option list all the paths to add in the file (relative paths are interpreted relative to working dir of the executable)
## INSTALL option to specify where we want to install this file
##
## Example usage:
## resourceFile(ADD "shaders" "${PROJECT_NAME}_rsc" INSTALL bin)
##
macro(resourceFile)
cmake_parse_arguments(rsc "" "INSTALL;FILE_PATH;CONFIG_TYPE" "ADD" ${ARGN}) ## both args are directory path
if(rsc_ADD)
unset(IBR_RSC_FILE_CONTENT_LIST)
if(EXISTS "${rsc_FILE_PATH}")
file(READ "${rsc_FILE_PATH}" IBR_RSC_FILE_CONTENT)
string(REGEX REPLACE "\n" ";" IBR_RSC_FILE_CONTENT_LIST "${IBR_RSC_FILE_CONTENT}")
endif()
list(APPEND IBR_RSC_FILE_CONTENT_LIST "${rsc_ADD}")
list(REMOVE_DUPLICATES IBR_RSC_FILE_CONTENT_LIST)
file(WRITE "${rsc_FILE_PATH}" "")
foreach(rscDir ${IBR_RSC_FILE_CONTENT_LIST})
file(APPEND "${rsc_FILE_PATH}" "${rscDir}\n")
endforeach()
unset(rsc_ADD)
endif()
if(rsc_INSTALL)
install(FILES ${rsc_FILE_PATH} CONFIGURATIONS ${rsc_CONFIG_TYPE} DESTINATION ${rsc_INSTALL})
unset(rsc_INSTALL)
endif()
endmacro()
##
## Install *.pdb generated file for the current cmake project
## assuming the output target name is the cmake project name.
## This macro is useful for crossplateform multi config mode.
##
## Usage Example:
##
## if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
## installPDB(${PROJECT_NAME} ${CMAKE_BUILD_TYPE} RUNTIME_DEST bin ARCHIVE_DEST lib LIBRARY_DEST lib)
## endif()
## foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
## installPDB(${PROJECT_NAME} ${CONFIG_TYPES} RUNTIME_DEST bin ARCHIVE_DEST lib LIBRARY_DEST lib)
## endforeach()
##
macro(installPDB targetName configType)
cmake_parse_arguments(instpdb "" "COMPONENT" "ARCHIVE_DEST;LIBRARY_DEST;RUNTIME_DEST" ${ARGN}) ## both args are directory path
if(NOT MSVC)
return()
endif()
## Check if DESTINATION are provided according to the TYPE of the given target (see install command doc to see correspodances)
get_target_property(type ${targetName} TYPE)
if(${type} MATCHES "EXECUTABLE" AND instpdb_RUNTIME_DEST)
set(pdb_DESTINATION ${instpdb_RUNTIME_DEST})
elseif(${type} MATCHES "STATIC_LIBRARY" AND instpdb_ARCHIVE_DEST)
set(pdb_DESTINATION ${instpdb_ARCHIVE_DEST})
elseif(${type} MATCHES "MODULE_LIBRARY" AND instpdb_LIBRARY_DEST)
set(pdb_DESTINATION ${instpdb_LIBRARY_DEST})
elseif(${type} MATCHES "SHARED_LIBRARY")
if(WIN32 AND instpdb_RUNTIME_DEST)
set(pdb_DESTINATION ${instpdb_RUNTIME_DEST})
else()
set(pdb_DESTINATION ${instpdb_LIBRARY_DEST})
endif()
endif()
if(NOT pdb_DESTINATION)
set(pdb_DESTINATION bin) ## default destination of the pdb file
endif()
if(NOT instpdb_COMPONENT)
set(instpdb_COMPONENT )
else()
set(instpdb_COMPONENT COMPONENT ${instpdb_COMPONENT})
endif()
string(TOUPPER ${configType} CONFIG_TYPES_UC)
get_target_property(PDB_PATH ${targetName} PDB_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC})
get_target_property(confModePostfix ${targetName} ${CONFIG_TYPES_UC}_POSTFIX)
if(NOT confModePostfix)
set(confModePostfix "")
endif()
set_target_properties(${targetName} PROPERTIES PDB_NAME_${CONFIG_TYPES_UC} ${targetName}${confModePostfix})
get_target_property(PDB_NAME ${targetName} PDB_NAME_${CONFIG_TYPES_UC})# if not set, this is empty
if(EXISTS "${PDB_PATH}/${PDB_NAME}.pdb")
install(FILES "${PDB_PATH}/${PDB_NAME}.pdb" CONFIGURATIONS ${configType} DESTINATION ${pdb_DESTINATION} ${instpdb_COMPONENT} OPTIONAL)
endif()
endmacro()
##
## Add additional target to install a project independently and based on its component
## configMode is used to prevent default Release installation (we want also to install in other build/config type)
##
macro(installTargetProject targetOfProject targetOfInstallProject)
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
set(configMode ${CMAKE_BUILD_TYPE})
elseif(MSVC)
## $(Configuration) will be one of the following : Debug, Release, MinSizeRel, RelWithDebInfo
set(configMode $(Configuration))
endif()
if(configMode)
get_target_property(srcFiles ${targetOfProject} SOURCES)
add_custom_target( ${targetOfInstallProject} #ALL
${CMAKE_COMMAND} -DBUILD_TYPE=${configMode} -DCOMPONENT=${targetOfInstallProject} -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
DEPENDS ${srcFiles}
COMMENT "run the installation only for ${targetOfProject}" VERBATIM
)
add_dependencies(${targetOfInstallProject} ${targetOfProject})
get_target_property(INSTALL_BUILD_FOLDER ${targetOfProject} FOLDER)
set_target_properties(${targetOfInstallProject} PROPERTIES FOLDER ${INSTALL_BUILD_FOLDER})
endif()
endmacro()
# Collect all currently added targets in all subdirectories
#
# Parameters:
# - _result the list containing all found targets
# - _dir root directory to start looking from
function(get_all_targets _result _dir)
get_property(_subdirs DIRECTORY "${_dir}" PROPERTY SUBDIRECTORIES)
foreach(_subdir IN LISTS _subdirs)
get_all_targets(${_result} "${_subdir}")
endforeach()
get_directory_property(_sub_targets DIRECTORY "${_dir}" BUILDSYSTEM_TARGETS)
set(${_result} ${${_result}} ${_sub_targets} PARENT_SCOPE)
endfunction()
##
## Add targets for building and installing subdirectories
macro(subdirectory_target target directory build_folder)
add_custom_target(${target}
COMMENT "run build for all projects in this directory" VERBATIM
)
get_all_targets(ALL_TARGETS ${directory})
add_dependencies(${target} ${ALL_TARGETS})
add_custom_target(${target}_install
${CMAKE_COMMAND} -DBUILD_TYPE=$<CONFIG> -DCOMPONENT=${target}_install -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
COMMENT "run install for all projects in this directory" VERBATIM
)
add_dependencies(${target}_install ${target})
set_target_properties(${target} PROPERTIES FOLDER ${build_folder})
set_target_properties(${target}_install PROPERTIES FOLDER ${build_folder})
endmacro()
## CMAKE install all required dependencies for an application (included system OS files like msvc*.dll for example)
##
## install_runtime(<installedFilePathTargetAppToResolve>
## [TARGET name]
## [PLUGINS name [nameN ...] [PLUGIN_PATH_NAME currentPathName [FROM_REL_PATH matchDirFromCurrentPathName] [PLUGIN_PATH_DEST installDir] ]
## [PLUGINS ...]
## [DIRS path [pathN ...] ]
## [TARGET_LIBRARIES filePath [filePathN ...] ]
## [TARGET_PACKAGES packageName [packageNameN ...] ]
## [COMPONENT installComponentName]
## [PLAUSIBLES_POSTFIX Debug_postfix [MinSizeRel_postfix relWithDebInfo_postfix ...] ]
## [VERBOSE]
## )
##
## installedFilePathTargetAppToResolve : the final installed targetApp absolute full file path name you want to resolve
##
## TARGET : The target app we want to install. If given, it's used to look for link libraries paths (best choice to use, strongly advised to use it)
##
## PLUGINS : Some application built use/load some plugins which can't be detect inside its binary,
## so, here you can specify which plugins the application use/load in order to install them
## and resolve also there dependencies.
## With PLUGINS multi FLAGS :
## PLUGIN_PATH_NAME : The current plugin full file path we want to install
## FROM_REL_PATH : [optional: default only the file is kept] From which matching dir of the plugin path we want to install (keep the directories structure)
## PLUGIN_PATH_DEST : [optional: default relative to executable directory] Where (full path to the install directory) we will install the plugin file (or file path)
##
## DIRS : A list of directories to looking for dependencies
## TARGET_LIBRARIES : DEPRECATED (use TARGET flag instead) : The cmake content variables used for the target_link_libraries(<targetApp> ...)
## TARGET_PACKAGES : DEPRECATED (use TARGET flag instead) : The cmake package names used for the findPackage(...) for your targetApp
## ADVICE: This flag add entries in cache (like: <packageName>_DIR), it could be useful to fill these variable!
## COMPONENT : (default to runtime) Is the component name associated to the installation
## It is used when you want to install separatly some part of your projets (see install cmake doc)
## VERBOSE : For debug or to get more informations in the output console
##
## Usage:
## install_runtime(${CMAKE_INSTALL_PREFIX}/${EXECUTABLE_NAME}${CMAKE_EXECUTABLE_SUFFIX}
## VERBOSE
## TARGET ${PROJECT_NAME}
## PLAUSIBLES_POSTFIX _d
## PLUGINS
## PLUGIN_PATH_NAME ${PLUGIN_PATH_NAME}${CMAKE_SHARED_MODULE_SUFFIX} ## will be installed (default exec path if no PLUGINS_DEST) and then will be resolved
## FROM_REL_PATH plugins ## optional, used especially for keeping qt plugins tree structure
## PLUGIN_PATH_DEST ${CMAKE_INSTALL_PREFIX}/plugins ## (or relative path 'plugins' will be interpreted relative to installed executable)
## DIRS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}
## TARGET_LIBRARIES ${OPENGL_LIBRARIES} ## DEPRECATED (use TARGET flag instead)
## ${GLEW_LIBRARIES}
## ${GLUT_LIBRARIES}
## ${Boost_LIBRARIES}
## ${SuiteSparse_LIBRARIES}
## ${CGAL_LIBRARIES}
## TARGET_PACKAGES OPENGL ## DEPRECATED (use TARGET flag instead)
## GLEW
## GLUT
## CGAL
## Boost
## SuiteSparse
## )
##
## For plugins part, it use our internal parse_arguments_multi.cmake
##
function(install_runtime installedFilePathTargetAppToResolve)
set(optionsArgs "VERBOSE")
set(oneValueArgs "COMPONENT;INSTALL_FOLDER;CONFIG_TYPE")
set(multiValueArgs "DIRS;PLUGINS;TARGET_LIBRARIES;TARGET_PACKAGES;TARGET;PLAUSIBLES_POSTFIX")
cmake_parse_arguments(inst_run "${optionsArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
if(IS_ABSOLUTE ${installedFilePathTargetAppToResolve})
else()
set(installedFilePathTargetAppToResolve ${inst_run_INSTALL_FOLDER}/${installedFilePathTargetAppToResolve})
endif()
get_filename_component(EXEC_NAME ${installedFilePathTargetAppToResolve} NAME_WE)
get_filename_component(EXEC_PATH ${installedFilePathTargetAppToResolve} PATH)
if(NOT inst_run_COMPONENT)
set(inst_run_COMPONENT runtime)
endif()
## Try to append as more possible as possible paths to find dependencies (deprecated since we can use target_properties to get back paths)
set(libPaths )
foreach(libraryFileName ${inst_run_TARGET_LIBRARIES})
if(IS_DIRECTORY "${libraryFileName}")
list(APPEND libPaths "${libraryFileName}")
else()
get_filename_component(libpath "${libraryFileName}" PATH)
if(EXISTS "${libpath}")
list(APPEND libPaths "${libpath}")
endif()
endif()
endforeach()
## This macro is used internaly here to recursilvely get path of LINK_LIBRARIES of each non imported target
## Typically if you have 2 internal dependencies between cmake targets, we want cmake to be able to get back path where are these dependencies
macro(recurseDepList target)
get_target_property(linkLibs ${target} LINK_LIBRARIES)
foreach(lib ${linkLibs})
string(FIND ${lib} ">" strId) ## cmake is using generator-expression?
if(TARGET ${lib})
## Skipping interface libraries as they're system ones
get_target_property(type ${lib} TYPE)
get_target_property(imported ${lib} IMPORTED)
if(type STREQUAL "INTERFACE_LIBRARY")
get_target_property(imp_loc ${lib} INTERFACE_IMPORTED_LOCATION)
if(imp_loc)
get_filename_component(imp_loc ${imp_loc} PATH)
list(APPEND targetLibPath ${imp_loc})
endif()
get_target_property(loc ${lib} INTERFACE_LOCATION)
if(loc)
get_filename_component(loc ${loc} PATH)
list(APPEND targetLibPath ${loc})
endif()
## it's not a path but a single target name
## for build-target which are part of the current cmake configuration : nothing to do as cmake already know the output path
## for imported target, we need to look for theire imported location
elseif(imported)
get_target_property(imp_loc ${lib} IMPORTED_LOCATION)
if(imp_loc)
get_filename_component(imp_loc ${imp_loc} PATH)
list(APPEND targetLibPath ${imp_loc})
endif()
get_target_property(loc ${lib} LOCATION)
if(loc)
get_filename_component(loc ${loc} PATH)
list(APPEND targetLibPath ${loc})
endif()
else()
recurseDepList(${lib})
endif()
elseif(NOT ${strId} MATCHES -1) ## mean cmake use generator-expression (CMAKE VERSION > 3.0)
string(REGEX MATCH ">:[@A-Za-z_:/.0-9-]+" targetLibPath ${lib})
string(REGEX REPLACE ">:([@A-Za-z_:/.0-9-]+)" "\\1" targetLibPath ${targetLibPath})
get_filename_component(targetLibPath ${targetLibPath} PATH)
elseif(EXISTS ${lib})
set(targetLibPath ${lib})
get_filename_component(targetLibPath ${targetLibPath} PATH)
else()
#message(STATUS "[install_runtime] skip link library : ${lib} , of target ${target}")
endif()
if(targetLibPath)
list(APPEND targetLinkLibsPathList ${targetLibPath})
endif()
endforeach()
if(targetLinkLibsPathList)
list(REMOVE_DUPLICATES targetLinkLibsPathList)
endif()
endmacro()
if(inst_run_TARGET)
recurseDepList(${inst_run_TARGET})
if(targetLinkLibsPathList)
list(APPEND libPaths ${targetLinkLibsPathList})
endif()
endif()
if(libPaths)
list(REMOVE_DUPLICATES libPaths)
foreach(libPath ${libPaths})
get_filename_component(path ${libPath} PATH)
list(APPEND libPaths ${path})
endforeach()
endif()
## possible speciale dir(s) according to the build system and OS
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(BUILD_TYPES_FOR_DLL "x64")
if(WIN32)
list(APPEND BUILD_TYPES_FOR_DLL "Win64")
endif()
else()
set(BUILD_TYPES_FOR_DLL "x86")
if(WIN32)
list(APPEND BUILD_TYPES_FOR_DLL "Win32")
endif()
endif()
## Try to append as more as possible paths to find dependencies (here, mainly for *.dll)
foreach(dir ${inst_run_DIRS} ${libPaths})
if(EXISTS "${dir}/bin")
list(APPEND inst_run_DIRS "${dir}/bin")
elseif(EXISTS "${dir}")
list(APPEND inst_run_DIRS "${dir}")
endif()
endforeach()
list(REMOVE_DUPLICATES inst_run_DIRS)
foreach(dir ${inst_run_DIRS})
if(EXISTS "${dir}")
list(APPEND argDirs ${dir})
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${dir}/${BUILD_TYPE_FOR_DLL}")
list(APPEND argDirs "${dir}/${BUILD_TYPE_FOR_DLL}")
endif()
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) ## for windows multi-generator (MSVC)
if(EXISTS "${dir}/${BUILD_TYPE_FOR_DLL}/${OUTPUTCONFIG}")
list(APPEND argDirs "${dir}/${BUILD_TYPE_FOR_DLL}/${OUTPUTCONFIG}")
endif()
endforeach()
if(CMAKE_BUILD_TYPE) ## for single generator (makefiles)
if(EXISTS "${dir}/${BUILD_TYPE_FOR_DLL}/${CMAKE_BUILD_TYPE}")
list(APPEND argDirs "${dir}/${BUILD_TYPE_FOR_DLL}/${CMAKE_BUILD_TYPE}")
endif()
endif()
endforeach()
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) ## for windows multi-generator (MSVC)
if(EXISTS "${dir}/${OUTPUTCONFIG}")
list(APPEND argDirs "${dir}/${OUTPUTCONFIG}")
endif()
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${dir}/${OUTPUTCONFIG}/${BUILD_TYPE_FOR_DLL}")
list(APPEND argDirs "${dir}/${OUTPUTCONFIG}/${BUILD_TYPE_FOR_DLL}")
endif()
endforeach()
endforeach()
if(CMAKE_BUILD_TYPE) ## for single generator (makefiles)
if(EXISTS "${dir}/${CMAKE_BUILD_TYPE}")
list(APPEND argDirs "${dir}/${CMAKE_BUILD_TYPE}")
endif()
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${dir}/${CMAKE_BUILD_TYPE}/${BUILD_TYPE_FOR_DLL}")
list(APPEND argDirs "${dir}/${CMAKE_BUILD_TYPE}/${BUILD_TYPE_FOR_DLL}")
endif()
endforeach()
endif()
endif()
endforeach()
if(argDirs)
list(REMOVE_DUPLICATES argDirs)
endif()
## Try to append as more possible paths to find dependencies (here, mainly for *.dll)
foreach(packageName ${inst_run_TARGET_PACKAGES})
if(EXISTS "${${packageName}_DIR}")
list(APPEND packageDirs ${${packageName}_DIR})
list(APPEND packageDirs ${${packageName}_DIR}/bin)
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}")
endif()
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) ## for windows multi-generator (MSVC)
if(EXISTS "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}/${OUTPUTCONFIG}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}/${OUTPUTCONFIG}")
endif()
endforeach()
if(CMAKE_BUILD_TYPE) ## for single generator (makefiles)
if(EXISTS "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}/${CMAKE_BUILD_TYPE}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}/${CMAKE_BUILD_TYPE}")
endif()
endif()
endforeach()
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) ## for windows multi-generator (MSVC)
if(EXISTS "${${packageName}_DIR}/bin/${OUTPUTCONFIG}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${OUTPUTCONFIG}")
endif()
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${${packageName}_DIR}/bin/${OUTPUTCONFIG}/${BUILD_TYPE_FOR_DLL}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${OUTPUTCONFIG}/${BUILD_TYPE_FOR_DLL}")
endif()
endforeach()
endforeach()
if(CMAKE_BUILD_TYPE) ## for single generator (makefiles)
if(EXISTS "${${packageName}_DIR}/bin/${CMAKE_BUILD_TYPE}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${CMAKE_BUILD_TYPE}")
endif()
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${${packageName}_DIR}/bin/${CMAKE_BUILD_TYPE}/${BUILD_TYPE_FOR_DLL}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${CMAKE_BUILD_TYPE}/${BUILD_TYPE_FOR_DLL}")
endif()
endforeach()
endif()
else()
set(${packageName}_DIR "$ENV{${packageName}_DIR}" CACHE PATH "${packageName}_DIR root directory for looking for dirs containning *.dll")
endif()
endforeach()
if(packageDirs)
list(REMOVE_DUPLICATES packageDirs)
endif()
set(dirsToLookFor "${EXEC_PATH}")
if(packageDirs)
list(APPEND dirsToLookFor ${packageDirs})
endif()
if(argDirs)
list(APPEND dirsToLookFor ${argDirs})
endif()
get_property(used_LINK_DIRECTORIES DIRECTORY PROPERTY LINK_DIRECTORIES)
if (used_LINK_DIRECTORIES)
list(APPEND dirsToLookFor ${used_LINK_DIRECTORIES})
list(REMOVE_DUPLICATES dirsToLookFor)
endif()
## handle plugins
set(pluginsList "")
include(parse_arguments_multi) ## this function will process recursively items of the sub-list [default print messages]
function(parse_arguments_multi_function results)
cmake_parse_arguments(pamf "VERBOSE" "PLUGIN_PATH_DEST;FROM_REL_PATH;EXEC_PATH;COMPONENT" "" ${ARGN}) ## EXEC_PATH and COMPONENT are for exclusive internal use
list(REMOVE_DUPLICATES pamf_UNPARSED_ARGUMENTS)
foreach(PLUGIN_PATH_NAME ${pamf_UNPARSED_ARGUMENTS})
if(EXISTS ${PLUGIN_PATH_NAME})
if(IS_DIRECTORY ${PLUGIN_PATH_NAME})
if(pamf_VERBOSE)
message(WARNING "${PLUGIN_PATH_NAME} IS_DIRECTORY, cannot installed a directory, please give a path filename")
endif()
else()
if(NOT pamf_PLUGIN_PATH_DEST)
set(PLUGIN_PATH_DEST ${pamf_EXEC_PATH}) ## the default dest value
else()
set(PLUGIN_PATH_DEST ${pamf_PLUGIN_PATH_DEST})
endif()
if(pamf_FROM_REL_PATH)
file(TO_CMAKE_PATH ${PLUGIN_PATH_NAME} PLUGIN_PATH_NAME)
get_filename_component(PLUGIN_PATH ${PLUGIN_PATH_NAME} PATH)
unset(PLUGIN_PATH_LIST)
unset(PLUGIN_PATH_LIST_COUNT)
unset(PLUGIN_REL_PATH_LIST)
unset(PLUGIN_REL_PATH)
string(REPLACE "/" ";" PLUGIN_PATH_LIST ${PLUGIN_PATH}) ## create a list of dir
list(FIND PLUGIN_PATH_LIST ${pamf_FROM_REL_PATH} id)
list(LENGTH PLUGIN_PATH_LIST PLUGIN_PATH_LIST_COUNT)
if(${id} GREATER 0)
math(EXPR id "${id}+1") ## matches relative path not include
math(EXPR PLUGIN_PATH_LIST_COUNT "${PLUGIN_PATH_LIST_COUNT}-1") ## the end of the list
foreach(i RANGE ${id} ${PLUGIN_PATH_LIST_COUNT})
list(GET PLUGIN_PATH_LIST ${i} out)
list(APPEND PLUGIN_REL_PATH_LIST ${out})
endforeach()
foreach(dir ${PLUGIN_REL_PATH_LIST})
set(PLUGIN_REL_PATH "${PLUGIN_REL_PATH}/${dir}")
endforeach()
endif()
set(PLUGIN_PATH_DEST ${PLUGIN_PATH_DEST}${PLUGIN_REL_PATH})
endif()
install(FILES ${PLUGIN_PATH_NAME} CONFIGURATIONS ${inst_run_CONFIG_TYPE} DESTINATION ${PLUGIN_PATH_DEST} COMPONENT ${pamf_COMPONENT})
get_filename_component(pluginName ${PLUGIN_PATH_NAME} NAME)
if(IS_ABSOLUTE ${PLUGIN_PATH_DEST})
else()
set(PLUGIN_PATH_DEST ${inst_run_INSTALL_FOLDER}/${PLUGIN_PATH_DEST})
endif()
list(APPEND pluginsList ${PLUGIN_PATH_DEST}/${pluginName})
endif()
else()
message(WARNING "You need to provide a valid PLUGIN_PATH_NAME")
set(pluginsList )
endif()
endforeach()
set(${results} ${pluginsList} PARENT_SCOPE)
endfunction()
if(inst_run_VERBOSE)
list(APPEND extra_flags_to_add VERBOSE)
endif()
list(APPEND extra_flags_to_add EXEC_PATH ${EXEC_PATH} COMPONENT ${inst_run_COMPONENT}) ## for internal use inside overloaded function
list(LENGTH inst_run_PLUGINS inst_run_PLUGINS_count)
if(${inst_run_PLUGINS_count} GREATER 0)
parse_arguments_multi(PLUGIN_PATH_NAME inst_run_PLUGINS ${inst_run_PLUGINS} ## see internal overload parse_arguments_multi_function for processing each sub-list
NEED_RESULTS ${inst_run_PLUGINS_count} ## this is used to check when we are in the first loop (in order to reset parse_arguments_multi_results)
EXTRAS_FLAGS ${extra_flags_to_add} ## this is used to allow catching additional internal flags of our overloaded function
)
endif()
#message(parse_arguments_multi_results = ${parse_arguments_multi_results})
list(APPEND pluginsList ${parse_arguments_multi_results})
## Install rules for required system runtimes such as MSVCRxx.dll
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP ON)
include(InstallRequiredSystemLibraries)
if(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)
install(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
CONFIGURATIONS ${inst_run_CONFIG_TYPE}
DESTINATION ${EXEC_PATH}
COMPONENT ${inst_run_COMPONENT}
)
endif()
## print what we are doing to do
if(inst_run_VERBOSE)
message(STATUS "[install_runtime] On install target call, cmake will try to resolve dependencies for given app:\n ${installedFilePathTargetAppToResolve} (with plausible postfix: ${inst_run_PLAUSIBLES_POSTFIX})")
if(pluginsList)
message(STATUS " and also for plugins :")
foreach(plugin ${pluginsList})
message(STATUS " ${plugin}")
endforeach()
endif()
message(STATUS " Looking for dependencies into:")
foreach(dir ${dirsToLookFor})
message(STATUS " ${dir}")
endforeach()
endif()
## Install rules for required dependencies libs/plugins for the target app
## will resolve all installed target files with config modes postfixes
string(TOUPPER ${inst_run_CONFIG_TYPE} inst_run_CONFIG_TYPE_UC)
get_target_property(postfix ${inst_run_TARGET} "${inst_run_CONFIG_TYPE_UC}_POSTFIX")
install(CODE "set(target \"${inst_run_TARGET}\")" COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE})
install(CODE "set(inst_run_CONFIG_TYPE \"${inst_run_CONFIG_TYPE}\")" COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE})
install(CODE "set(inst_run_INSTALL_FOLDER \"${inst_run_INSTALL_FOLDER}\")" COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE})
install(CODE "set(app \"${EXEC_PATH}/${EXEC_NAME}${postfix}${CMAKE_EXECUTABLE_SUFFIX}\")" COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE})
install(CODE "set(dirsToLookFor \"${dirsToLookFor}\")" COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE})
install(CODE
[[
if("${CMAKE_INSTALL_CONFIG_NAME}" STREQUAL "${inst_run_CONFIG_TYPE}")
message(STATUS "Installing ${target} dependencies...")
file(GET_RUNTIME_DEPENDENCIES
EXECUTABLES ${app}
RESOLVED_DEPENDENCIES_VAR _r_deps
UNRESOLVED_DEPENDENCIES_VAR _u_deps
CONFLICTING_DEPENDENCIES_PREFIX _c_deps
DIRECTORIES ${dirsToLookFor}
PRE_EXCLUDE_REGEXES "api-ms-*"
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll" ".*SysWOW64/.*\\.dll"
)
if(_u_deps)
message(WARNING "There were unresolved dependencies for executable ${EXEC_FILE}: \"${_u_deps}\"!")
endif()
if(_c_deps_FILENAMES)
message(WARNING "There were conflicting dependencies for executable ${EXEC_FILE}: \"${_c_deps_FILENAMES}\"!")
endif()
foreach(_file ${_r_deps})
file(INSTALL
DESTINATION "${inst_run_INSTALL_FOLDER}/bin"
TYPE SHARED_LIBRARY
FOLLOW_SYMLINK_CHAIN
FILES "${_file}"
)
endforeach()
endif()
]]
COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE}
)
endfunction()
## High level macro to install resources in the correct folder
##
## EXECUTABLE: [opt] option to copy files as programs
## RELATIVE : [opt] copy files relatively to current folder
## TYPE : [opt] type and folder where to store the files
## FOLDER : [opt] subfolder to use
## FILES : [opt] contains a list of resources files to copy to install folder
macro(ibr_install_rsc target)
cmake_parse_arguments(install_rsc_${target} "EXECUTABLE;RELATIVE" "TYPE;FOLDER" "FILES" ${ARGN})
set(rsc_target "${target}_${install_rsc_${target}_TYPE}")
if(install_rsc_${target}_FOLDER)
set(rsc_folder "${install_rsc_${target}_TYPE}/${install_rsc_${target}_FOLDER}")
else()
set(rsc_folder "${install_rsc_${target}_TYPE}")
endif()
add_custom_target(${rsc_target}
COMMENT "run the ${install_rsc_${target}_TYPE} installation only for ${target} (component ${rsc_target})"
VERBATIM)
foreach(scriptFile ${install_rsc_${target}_FILES})
if(install_rsc_${target}_RELATIVE)
file(RELATIVE_PATH relativeFilename ${CMAKE_CURRENT_SOURCE_DIR} ${scriptFile})
else()
get_filename_component(relativeFilename ${scriptFile} NAME)
endif()
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
add_custom_command(TARGET ${rsc_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different ${scriptFile} ${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}/${rsc_folder}/${relativeFilename})
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
add_custom_command(TARGET ${rsc_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different ${scriptFile} ${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}/${rsc_folder}/${relativeFilename})
endforeach()
endforeach()
get_target_property(INSTALL_RSC_BUILD_FOLDER ${target} FOLDER)
set_target_properties(${rsc_target} PROPERTIES FOLDER ${INSTALL_RSC_BUILD_FOLDER})
add_dependencies(${target} ${rsc_target})
add_dependencies(PREBUILD ${rsc_target})
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
resourceFile(ADD ${rsc_folder} CONFIG_TYPE ${CMAKE_BUILD_TYPE} FILE_PATH "${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}/ibr_resources.ini")
if(install_rsc_${target}_EXECUTABLE)
install(
PROGRAMS ${install_rsc_${target}_FILES}
CONFIGURATIONS ${CMAKE_BUILD_TYPE}
DESTINATION "${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}/${rsc_folder}"
)
else()
install(
FILES ${install_rsc_${target}_FILES}
CONFIGURATIONS ${CMAKE_BUILD_TYPE}
DESTINATION "${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}/${rsc_folder}"
)
endif()
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
resourceFile(ADD ${rsc_folder} CONFIG_TYPE ${CONFIG_TYPES} FILE_PATH "${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}/ibr_resources.ini")
if(install_rsc_${target}_EXECUTABLE)
install(
PROGRAMS ${install_rsc_${target}_FILES}
CONFIGURATIONS ${CONFIG_TYPES}
DESTINATION "${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}/${rsc_folder}"
)
else()
install(
FILES ${install_rsc_${target}_FILES}
CONFIGURATIONS ${CONFIG_TYPES}
DESTINATION "${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}/${rsc_folder}"
)
endif()
endforeach()
endmacro()
## High level macro to install in an homogen way all our ibr targets (it use some functions inside this file)
##
## RSC_FILE_ADD : [opt] is used to auto write/append relative paths of target resources into a common file
## INSTALL_PDB : [opt] is used to auto install PDB file (when using MSVC according to the target type)
## STANDALONE : [opt] bool ON/OFF var to call install_runtime or not (for bundle resolution)
## DIRS : [opt] used if STANDALONE set to ON, see install_runtime doc
## PLUGINS: [opt] used if STANDALONE set to ON, see install_runtime doc
## MSVC_CMD : [opt] used to specify an absolute filePathName application to launch with the MSVC IDE Debugger associated to this target (project file)
## MSVC_ARGS : [opt] load the MSVC debugger with correct settings (app path, args, working dir)
##
macro(ibr_install_target target)
cmake_parse_arguments(ibrInst${target} "VERBOSE;INSTALL_PDB" "COMPONENT;MSVC_ARGS;STANDALONE;RSC_FOLDER" "SHADERS;RESOURCES;SCRIPTS;DIRS;PLUGINS" ${ARGN})
if(ibrInst${target}_RSC_FOLDER)
set(rsc_folder "${ibrInst${target}_RSC_FOLDER}")
else()
set(rsc_folder "${target}")
endif()
if(ibrInst${target}_SHADERS)
ibr_install_rsc(${target} EXECUTABLE TYPE "shaders" FOLDER ${rsc_folder} FILES "${ibrInst${target}_SHADERS}")
endif()
if(ibrInst${target}_RESOURCES)
ibr_install_rsc(${target} TYPE "resources" FOLDER ${rsc_folder} FILES "${ibrInst${target}_RESOURCES}")
endif()
if(ibrInst${target}_SCRIPTS)
ibr_install_rsc(${target} EXECUTABLE TYPE "scripts" FOLDER ${rsc_folder} FILES "${ibrInst${target}_SCRIPTS}")
endif()
if(ibrInst${target}_COMPONENT)
set(installCompArg COMPONENT ${ibrInst${target}_COMPONENT})
## Create a custom install target based on COMPONENT
installTargetProject(${target} ${ibrInst${target}_COMPONENT})
endif()
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
set_target_properties(${target} PROPERTIES ${CMAKE_BUILD_TYPE}_POSTFIX "${CMAKE_${CMAKE_BUILD_TYPE}_POSTFIX}")
get_target_property(CURRENT_TARGET_BUILD_TYPE_POSTFIX ${target} ${CMAKE_BUILD_TYPE}_POSTFIX)
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
set_target_properties(${target} PROPERTIES ${CONFIG_TYPES_UC}_POSTFIX "${CMAKE_${CONFIG_TYPES_UC}_POSTFIX}")
get_target_property(CURRENT_TARGET_BUILD_TYPE_POSTFIX ${target} ${CONFIG_TYPES_UC}_POSTFIX)
endforeach()
## Specify default installation rules
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
install(TARGETS ${target}
CONFIGURATIONS ${CMAKE_BUILD_TYPE}
LIBRARY DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}} ${installCompArg}
ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}} ${installCompArg}
RUNTIME DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}} ${installCompArg}
)
install(TARGETS ${target}
CONFIGURATIONS ${CMAKE_BUILD_TYPE}
LIBRARY DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}} ${installCompArg}
ARCHIVE DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}} ${installCompArg}
)
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
install(TARGETS ${target}
CONFIGURATIONS ${CONFIG_TYPES}
LIBRARY DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}} ${installCompArg}
ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}} ${installCompArg}
RUNTIME DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}} ${installCompArg}
)
install(TARGETS ${target}
CONFIGURATIONS ${CONFIG_TYPES}
LIBRARY DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}} ${installCompArg}
ARCHIVE DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}} ${installCompArg}
)
endforeach()
if(ibrInst${target}_INSTALL_PDB)
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
installPDB(${target} ${CMAKE_BUILD_TYPE}
LIBRARY_DEST ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}}
ARCHIVE_DEST ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}}
RUNTIME_DEST ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}}
)
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
installPDB(${target} ${CONFIG_TYPES}
LIBRARY_DEST ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}}
ARCHIVE_DEST ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}}
RUNTIME_DEST ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}}
)
endforeach()
endif()
## install dynamic necessary dependencies
if(ibrInst${target}_STANDALONE)
get_target_property(type ${target} TYPE)
if(${type} MATCHES "EXECUTABLE")
if(ibrInst${target}_VERBOSE)
set(VERBOSE VERBOSE)
else()
set(VERBOSE )
endif()
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
install_runtime(bin/${target}${CMAKE_EXECUTABLE_SUFFIX} ## default relative to CMAKE_INSTALL_PREFIX
INSTALL_FOLDER "${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}"
CONFIG_TYPE ${CMAKE_BUILD_TYPE}
${VERBOSE}
TARGET ${target}
${installCompArg}
PLUGINS ## will be installed
${ibrInst${target}_PLUGINS}
DIRS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}}
${ibrInst${target}_DIRS}
)
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
install_runtime(bin/${target}${CMAKE_EXECUTABLE_SUFFIX} ## default relative to CMAKE_INSTALL_PREFIX
INSTALL_FOLDER "${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}"
CONFIG_TYPE ${CONFIG_TYPES}
${VERBOSE}
TARGET ${target}
${installCompArg}
PLUGINS ## will be installed
${ibrInst${target}_PLUGINS}
DIRS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}}
${ibrInst${target}_DIRS}
)
endforeach()
else()
message(WARNING "STANDALONE option is only compatible with EXECUTABLES target type. Skip the STANDALONE installation process.")
endif()
endif()
## Provide a way to directly load the MSVC debugger with correct settings
if(MSVC)
if(ibrInst${target}_MSVC_CMD) ## command absolute filePathName is optional as the default is to use the installed target file application
set(msvcCmdArg COMMAND ${ibrInst${target}_MSVC_CMD}) ## flag following by the value (both to pass to the MSVCsetUserCommand function)
endif()
if(ibrInst${target}_MSVC_ARGS) ## args (between quotes) are optional
set(msvcArgsArg ARGS ${ibrInst${target}_MSVC_ARGS}) ## flag following by the value (both to pass to the MSVCsetUserCommand function)
endif()
get_target_property(type ${target} TYPE)
if( (ibrInst${target}_MSVC_CMD OR ibrInst${target}_MSVC_ARGS) OR (${type} MATCHES "EXECUTABLE") )
include(MSVCsetUserCommand)
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
MSVCsetUserCommand( ${target}
PATH ${CMAKE_OUTPUT_BIN_${CMAKE_BUILD_TYPE}} ##FILE option not necessary since it deduced from targetName
ARGS "${SIBR_PROGRAMARGS}"
${msvcCmdArg}
#${msvcArgsArg}
WORKING_DIR ${CMAKE_OUTPUT_BIN_${CMAKE_BUILD_TYPE}}
)
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
MSVCsetUserCommand( ${target}
PATH ${CMAKE_OUTPUT_BIN_${CONFIG_TYPES_UC}} ##FILE option not necessary since it deduced from targetName
ARGS "${SIBR_PROGRAMARGS}"
${msvcCmdArg}
#${msvcArgsArg}
WORKING_DIR ${CMAKE_OUTPUT_BIN_${CONFIG_TYPES_UC}}
)
endforeach()
elseif(NOT ${type} MATCHES "EXECUTABLE")
#message("Cannot set MSVCsetUserCommand with target ${target} without COMMAND parameter as it is not an executable (skip it)")
endif()
endif()
endmacro()

View File

@ -0,0 +1,304 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
if(NOT WIN32 OR __parse_arguments_multi_cmake_INCLUDED__)
return()
else()
set(__parse_arguments_multi_cmake_INCLUDED__ ON)
endif()
## This macro allow to process repeating multi value args from a given function which use cmake_parse_arguments module.
##
## cmake_parse_arguments multi args standard behavior:
## function(foo)
## cmake_parse_arguments(arg "" "" "MULTI" ${ARGN})
## foreach(item IN LISTS arg_MULTI)
## message(STATUS "${item}")
## endforeach()
## endfunction()
## foo(MULTI x y MULTI z w)
## The above code outputs 'z' and 'w'. It originally expected it to output all of 'x' 'y' 'z' 'w'.
##
## Using this macro inside a function which want to handle repeating multi args values
## will recursively iterate onto the multi tags list to process each sub list.
## It take as 1st argument the subTag flag to separate sub list from the main multi list.
## It take as 2nd argument the nameList of the main multi list (the multiValuesArgs from cmake_parse_arguments: here it is MULTI in the example)
## and that's why it is important that it should be a macro and not a function (to get access to external variable).
## Then you give the content of this list allowing to be processed by the macro.
##
## parse_arguments_multi macro call a parse_arguments_multi_function which do actually the process from the given sub-list.
## By default this function only print infos about what variables you are trying to pass/process (only verbose messages),
## but, by overloading this cmake function, you will be able to externalize the process of your multi argument list.
##
## Usage (into a function) :
## parse_arguments_multi(<multiArgsSubTag> <multiArgsList> <multiArgsListContent>
## [NEED_RESULTS <multiArgsListSize>] [EXTRAS_FLAGS <...> <...> ...]
## )
##
## Simple usage example [user point of view]:
## foo(MULTI
## SUB_MULTI x y
## SUB_MULTI z w
## )
##
## Simple usage example [inside a function]:
## function(foo)
## cmake_parse_arguments(arg "" "" "MULTI" ${ARGN})
## include(parse_arguments_multi)
## function(parse_arguments_multi_function )
## #message("I'm an overloaded cmake function used by parse_arguments_multi")
## #message("I'm processing first part of my sub list: ${ARGN}")
## message("ARGV0=${ARGV0}")
## message("ARGV1=${ARGV1}")
## endfunction()
## parse_arguments_multi(SUB_MULTI arg_MULTI ${arg_MULTI}) ## this function will process recusively items of the sub-list [default print messages]
## endfunction()
##
## Will print:
## ARGV0=z
## ARGV1=w
## ARGV0=x
## ARGV1=y
##
## WARNING : DO NEVER ADD EXTRA THINGS TO parse_arguments_multi MACRO :
## parse_arguments_multi(SUB_MULTI arg_MULTI ${arg_MULTI} EXTRAS foo bar SOMTHING) => will failed !!
## use EXTRAS_FLAGS instead !!
##
## Advanced usage example [user point of view]:
## bar(C:/prout/test.exe VERBOSE
## PLUGINS
## PLUGIN_PATH_NAME x PLUGIN_PATH_DEST w
## PLUGIN_PATH_NAME a b PLUGIN_PATH_DEST y
## PLUGIN_PATH_NAME c
## )
##
## Advanced usage example [inside a function]:
## function(bar execFilePathName)
## cmake_parse_arguments(arg "VERBOSE" "" "PLUGINS" ${ARGN})
##
## include(parse_arguments_multi)
## function(parse_arguments_multi_function results)
## cmake_parse_arguments(pamf "VERBOSE" "PLUGIN_PATH_DEST;EXEC_PATH" "" ${ARGN}) ## EXEC_PATH is for internal use
## message("")
## message("I'm an overloaded cmake function used by parse_arguments_multi from install_runtime function")
## message("I'm processing first part of my sub list: ${ARGN}")
## message("PLUGIN_PATH_NAME = ${pamf_UNPARSED_ARGUMENTS}")
## message(pamf_VERBOSE = ${pamf_VERBOSE})
## message("pamf_PLUGIN_PATH_DEST = ${pamf_PLUGIN_PATH_DEST}")
## message(pamf_EXEC_PATH = ${pamf_EXEC_PATH})
## if(NOT ${pamf_PLUGIN_PATH_DEST})
## set(pamf_PLUGIN_PATH_DEST ${pamf_EXEC_PATH})
## endif()
## foreach(plugin ${pamf_UNPARSED_ARGUMENTS})
## get_filename_component(pluginName ${plugin} NAME)
## list(APPEND pluginsList ${pamf_PLUGIN_PATH_DEST}/${pluginName})
## endforeach()
## set(${results} ${pluginsList} PARENT_SCOPE)
## endfunction()
##
## if(arg_VERBOSE)
## list(APPEND extra_flags_to_add VERBOSE) ## here we transmit the VERNOSE flag
## endif()
## get_filename_component(EXEC_PATH ${execFilePathName} PATH) ## will be the default value if PLUGIN_PATH_DEST option is not provided
## list(APPEND extra_flags_to_add EXEC_PATH ${EXEC_PATH})
## list(LENGTH arg_PLUGINS arg_PLUGINS_count)
## parse_arguments_multi(PLUGIN_PATH_NAME arg_PLUGINS ${arg_PLUGINS}
## NEED_RESULTS ${arg_PLUGINS_count} ## this is used to check when we are in the first loop (in order to reset parse_arguments_multi_results)
## EXTRAS_FLAGS ${extra_flags_to_add} ## this is used to allow catching VERBOSE and PLUGIN_PATH_DEST flags of our overloaded function
## )
## endfunction()
## message(parse_arguments_multi_results = ${parse_arguments_multi_results}) ## list of the whole pluginsList
## #Will print w/x;a/y;b/y;C:/prout/c
##
## NOTE that here, since our overloaded function need to provide a result list, we use the other parse_arguments_multi_function signature (the which one with a results arg)
##
function(parse_arguments_multi_function_default) ## used in case of you want to reset the default behavior of this function process
message("[default function] parse_arguments_multi_function(ARGC=${ARGC} ARGV=${ARGV} ARGN=${ARGN})")
message("This function is used by parse_arguments_multi and have to be overloaded to process sub list of multi values args")
endfunction()
function(parse_arguments_multi_function ) ## => the function to overload
parse_arguments_multi_function_default(${ARGN})
endfunction()
## first default signature above
##------------------------------
## second results signature behind
function(parse_arguments_multi_function_default result) ## used in case of you want to reset the default behavior of this function process
message("[default function] parse_arguments_multi_function(ARGC=${ARGC} ARGV=${ARGV} ARGN=${ARGN})")
message("This function is used by parse_arguments_multi and have to be overloaded to process sub list of muluti values args")
endfunction()
function(parse_arguments_multi_function result) ## => the function to overload
parse_arguments_multi_function_default(result ${ARGN})
endfunction()
## => the macro to use inside your function which use cmake_parse_arguments
# NOTE: entry point of parse_arguments_multi, which is called from win3rdPart)
macro(parse_arguments_multi multiArgsSubTag multiArgsList #<${multiArgsList}> the content of the list
)
# message (STATUS "")
# message(STATUS "calling parse_arguemnts_multi defined in parse_arguments_multi.cmake:141")
# message(STATUS "multiArgsSubTag = ${multiArgsSubTag}") # CHECK_CACHED_VAR
# message(STATUS "multiArgsList = ${multiArgsList}") # it contains the name of the variable which is holding the list i.e w3p_MULTI_SET
# message(STATUS "value of ${multiArgsList} = ${${multiArgsList}}") # a semicolon separated list of values passed to SET or MULTISET keyword in win3rdParty
# message(STATUS "actual values ARGN = ${ARGN}") # the same as ${${multiArgsList}}
## INFO
## starting from CMake 3.5 cmake_parse_arguments is not a module anymore and now is a native CMake command.
## the behaviour is different though
## In CMake 3.4, if you pass multiple times a multi_value_keyword, CMake returns the values of the LAST match
## In CMake 3.5 and above, CMake returns the whole list of values that were following that multi_value_keyword
## example:
## cmake_parse_arguments(
## <prefix>
## "" # options
## "" # one value keywords
## "MY_MULTI_VALUE_TAG"
## MY_MULTI_VALUE_TAG value1 value2
## MY_MULTI_VALUE_TAG value3 value4
## MY_MULTI_VALUE_TAG value5 value6
## )
## result in CMake 3.4
## <prefix>_MY_MULTI_VALUE_TAG = "value5;value6"
##
## result in CMake 3.8
## <prefix>_MY_MULTI_VALUE_TAG = "value5;value6"
#include(CMakeParseArguments) #module CMakeParseArguments is obsolete since cmake 3.5
# cmake_parse_arguments (<prefix> <options> <one_value_keywords> <multi_value_keywords> args)
# <options> : options (flags) pass to the macro
# <one_value_keywords> : options that neeed a value
# <multi_value_keywords> : options that neeed more than one value
cmake_parse_arguments(_pam "" "NEED_RESULTS" "${multiArgsSubTag};EXTRAS_FLAGS" ${ARGN})
## multiArgsList is the name of the list used by the multiValuesOption flag from the cmake_parse_arguments of the user function
## that's why we absolutly need to use MACRO here (and also for passing parse_arguments_multi_results when NEED_RESULTS flag is set)
## for debugging
#message("")
#message("[parse_arguments_multi] => ARGN = ${ARGN}")
#message("_pam_NEED_RESULTS=${_pam_NEED_RESULTS}")
#message("_pam_EXTRAS_FLAGS=${_pam_EXTRAS_FLAGS}")
# foreach(var ${_pam_${multiArgsSubTag}})
# message("arg=${var}")
# endforeach()
if (${CMAKE_VERSION} VERSION_GREATER "3.5")
# lets make ${_pam_${multiArgsSubTag}} behave as it is in version 3.4
# that means, cmake_parse_arguments should have only the last values of a multi set for a given keyword
# message("")
# message("values in multiArgsList")
# foreach(val ${${multiArgsList}})
# message(STATUS ${val})
# endforeach()
# message("end values in multiArgsList")
set(lastIndexFound OFF)
list(LENGTH ${multiArgsList} argnLength)
# message(${argnLength})
math(EXPR argnLength "${argnLength}-1") # make last index a valid one
set(recordIndex 0)
set(records "") # clear records list
set(record0 "") # clear first record list
foreach(iter RANGE ${argnLength})
list(GET ${multiArgsList} ${iter} value)
# message(STATUS "index=${iter} value=${value}")
if (${value} STREQUAL ${multiArgsSubTag})
if (lastIndexFound)
list(APPEND records ${recordIndex}) # records store the list NAMES
math(EXPR recordIndex "${recordIndex}+1")
set(record${recordIndex} "") # clear record list
else ()
set(lastIndexFound ON)
endif()
set(lastIndex ${iter})
else ()
if (lastIndexFound)
# message(${value})
list(APPEND record${recordIndex} ${value})
endif()
endif()
endforeach()
# save the last list of values
if (lastIndexFound)
list(APPEND records ${recordIndex}) # records store the list NAMES
endif()
# set multiArgsList to make it behave like CMake 3.4
# message("")
# message("using my records")
foreach(recordName ${records})
# message(${recordName})
# foreach(value ${record${recordName}})
# message(${value})
# endforeach()
# message("")
set(_pam_${multiArgsSubTag} ${record${recordName}})
endforeach()
# message(${_pam_${multiArgsSubTag}})
# message("")
# message("using argn")
# foreach(value ${ARGN})
# message(${value})
# endforeach()
endif() # end if cmake > 3.5
# message("values with pam ${_pam_${multiArgsSubTag}}")
## check and init
list(LENGTH ${multiArgsList} globalListCount) # GLUT_TRACE: globalListCound=16 in CMake3.4 and CMake3.8
# message(STATUS "nr items in multiArgsList: ${globalListCount}")
math(EXPR globalListCount "${globalListCount}-1") ## because it will contain [multiArgsSubTag + ${multiArgsList}]
if(_pam_NEED_RESULTS)
if(${globalListCount} EQUAL ${_pam_NEED_RESULTS})
## first time we enter into this macro (because we call it recursively)
unset(parse_arguments_multi_results)
endif()
endif()
## process the part of the multi agrs list
## ${ARGN} shouldn't be passed to the function in order to avoid missmatch size list ${multiArgsList} and _pam_${multiArgsSubTag}
## if you want to pass extra internal flags from your function to this callback, use EXTRAS_FLAGS
if(_pam_NEED_RESULTS)
parse_arguments_multi_function(parse_arguments_multi_function_result ${_pam_${multiArgsSubTag}} ${_pam_EXTRAS_FLAGS})
list(APPEND parse_arguments_multi_results ${parse_arguments_multi_function_result})
else()
# message(STATUS "about to call parse_arguments_multi_function in parse_arguments_multi.cmake:177 ${_pam_${multiArgsSubTag}} and extra flags ${_pam_EXTRAS_FLAGS}")
parse_arguments_multi_function(${_pam_${multiArgsSubTag}} ${_pam_EXTRAS_FLAGS})
endif()
## remove just processed items from the main list to process (multiArgsList)
list(REVERSE ${multiArgsList})
list(LENGTH _pam_${multiArgsSubTag} subTagListCount)
unset(ids)
foreach(id RANGE ${subTagListCount})
list(APPEND ids ${id})
endforeach()
list(REMOVE_AT ${multiArgsList} ${ids})
list(REVERSE ${multiArgsList})
## test if remain sub multi list to process (recursive call) or finish the process
list(LENGTH ${multiArgsList} mainTagListCount)
if(${mainTagListCount} GREATER 1)
## do not pass ${ARGN} just because it will re pass the initial 2 inputs args and we wont as they was consumed (in order to avoir conflicts)
# message(STATUS "about to call a parse_arguments_multi but without knowing where the definition is going to be taken from")
parse_arguments_multi(${multiArgsSubTag} ${multiArgsList} ${${multiArgsList}}
NEED_RESULTS ${_pam_NEED_RESULTS} EXTRAS_FLAGS ${_pam_EXTRAS_FLAGS}
)
endif()
endmacro()

View File

@ -0,0 +1,174 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
# NOTE
# This feature is used to easily download, store and link external dependencies. This
# requires to prepare pre-compiled libraries (to download). For now, packages have
# only be prepare for Windows 64-bit with Visual Studio 2012. (You should re-build
# everything if you want to use another version of Visual Studio/ another compiler).
# NOTE ABOUT UNIX SYSTEMS
# There is no need for "searching mechanism". This function is discard and your
# libraries should be installed is the standard folders that are:
#
# /usr/include/
# /usr/lib/
# /usr/lib64/
# for packages downloaded using apt-get/yum
#
# /usr/local/include/
# /usr/local/lib/
# /usr/local/lib64/
# for packages manually installed ("make install")
#
# if you encounter problems when linking (e.g. lib not found even if it is installed),
# please check these folders are in your search PATH environment variables.
set(EXTLIBS_PACKAGE_FOLDER "${CMAKE_SOURCE_DIR}/extlibs")
function(sibr_addlibrary)
if(NOT WIN32)
return()
endif()
file(MAKE_DIRECTORY ${EXTLIBS_PACKAGE_FOLDER})
cmake_parse_arguments(args "VCID" "VERBOSE;TIMEOUT;DEFAULT_USE;NAME;VERSION;MSVC11;MSVC12;MSVC14;MSVC17" "MULTI_SET;SET" ${ARGN})
if (NOT "${args_VERSION}" MATCHES "")
message(WARNING "VERSION is not implemented yet")
endif()
set(lcname "")
set(ucname "")
string(TOLOWER "${args_NAME}" lcname)
string(TOUPPER "${args_NAME}" ucname)
set(LIB_PACKAGE_FOLDER "${EXTLIBS_PACKAGE_FOLDER}/${lcname}")
win3rdParty(${ucname}
$<args_VCID:VCID>
VERBOSE ${args_VERBOSE}
TIMEOUT ${args_TIMEOUT}
DEFAULT_USE ${args_DEFAULT_USE}
MSVC11 "${LIB_PACKAGE_FOLDER}" "${args_MSVC11}"
MSVC12 "${LIB_PACKAGE_FOLDER}" "${args_MSVC12}"
MSVC14 "${LIB_PACKAGE_FOLDER}" "${args_MSVC14}" # TODO SV: make sure to build this library if required
MSVC17 "${LIB_PACKAGE_FOLDER}" "${args_MSVC17}"
SET ${args_SET}
MULTI_SET ${args_MULTI_SET}
)
# Add include/ directory
# and lib/ directories
# TODO SV: paths not matching with current hierarchy. example: libraw/libraw-0.17.1/include
# SR: The link directories will also be used to lookup for dependency DLLs to copy in the install directory.
# Some libraries put the DLLs in the bin/ directory, so we include those.
file(GLOB subdirs RELATIVE ${LIB_PACKAGE_FOLDER} ${LIB_PACKAGE_FOLDER}/*)
set(dirlist "")
foreach(dir ${subdirs})
if(IS_DIRECTORY ${LIB_PACKAGE_FOLDER}/${dir})
# message("adding ${LIB_PACKAGE_FOLDER}/${dir}/include/ to the include directories")
include_directories("${LIB_PACKAGE_FOLDER}/${dir}/include/")
# message("adding ${LIB_PACKAGE_FOLDER}/${dir}/lib[64] to the link directories")
link_directories("${LIB_PACKAGE_FOLDER}/${dir}/")
link_directories("${LIB_PACKAGE_FOLDER}/${dir}/lib/")
link_directories("${LIB_PACKAGE_FOLDER}/${dir}/lib64/")
link_directories("${LIB_PACKAGE_FOLDER}/${dir}/bin/")
endif()
endforeach()
endfunction()
include(FetchContent)
include(git_describe)
include(install_runtime)
function(sibr_gitlibrary)
cmake_parse_arguments(args "" "TARGET;GIT_REPOSITORY;GIT_TAG;ROOT_DIR;SOURCE_DIR" "INCLUDE_DIRS" ${ARGN})
if(NOT args_TARGET)
message(FATAL "Error on sibr_gitlibrary : please define your target name.")
return()
endif()
if(NOT args_ROOT_DIR)
set(args_ROOT_DIR ${args_TARGET})
endif()
if(NOT args_SOURCE_DIR)
set(args_SOURCE_DIR ${args_TARGET})
endif()
if(args_GIT_REPOSITORY AND args_GIT_TAG)
if(EXISTS ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/${args_SOURCE_DIR}/.git)
git_describe(
PATH ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/${args_SOURCE_DIR}
GIT_URL SIBR_GITLIBRARY_URL
GIT_BRANCH SIBR_GITLIBRARY_BRANCH
GIT_COMMIT_HASH SIBR_GITLIBRARY_COMMIT_HASH
GIT_TAG SIBR_GITLIBRARY_TAG
)
if((SIBR_GITLIBRARY_URL STREQUAL args_GIT_REPOSITORY) AND
((SIBR_GITLIBRARY_BRANCH STREQUAL args_GIT_TAG) OR
(SIBR_GITLIBRARY_TAG STREQUAL args_GIT_TAG) OR
(SIBR_GITLIBRARY_COMMIT_HASH STREQUAL args_GIT_TAG)))
message(STATUS "Library ${args_TARGET} already available, skipping.")
set(SIBR_GITLIBRARY_DECLARED ON)
else()
message(STATUS "Adding library ${args_TARGET} from git...")
endif()
endif()
FetchContent_Declare(${args_TARGET}
GIT_REPOSITORY ${args_GIT_REPOSITORY}
GIT_TAG ${args_GIT_TAG}
GIT_SHALLOW ON
SOURCE_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/${args_SOURCE_DIR}
SUBBUILD_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/subbuild
BINARY_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/build
)
FetchContent_GetProperties(${args_TARGET})
string(TOLOWER "<name>" lcTargetName)
if((NOT SIBR_GITLIBRARY_DECLARED) AND (NOT ${lcTargetName}_POPULATED))
message(STATUS "Populating library ${args_TARGET}...")
FetchContent_Populate(${args_TARGET} QUIET
GIT_REPOSITORY ${args_GIT_REPOSITORY}
GIT_TAG ${args_GIT_TAG}
SOURCE_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/${args_SOURCE_DIR}
SUBBUILD_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/subbuild
BINARY_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/build
)
endif()
add_subdirectory(${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/${args_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/build)
get_target_property(type ${args_TARGET} TYPE)
if(NOT (type STREQUAL "INTERFACE_LIBRARY"))
set_target_properties(${args_TARGET} PROPERTIES FOLDER "extlibs")
ibr_install_target(${args_TARGET}
COMPONENT ${args_TARGET}_install ## will create custom target to install only this project
)
endif()
list(APPEND ${args_TARGET}_INCLUDE_DIRS ${EXTLIBS_PACKAGE_FOLDER}/${args_ROOT_DIR})
list(APPEND ${args_TARGET}_INCLUDE_DIRS ${EXTLIBS_PACKAGE_FOLDER}/${args_ROOT_DIR}/${args_SOURCE_DIR})
foreach(args_INCLUDE_DIR ${args_INCLUDE_DIRS})
list(APPEND ${args_TARGET}_INCLUDE_DIRS ${EXTLIBS_PACKAGE_FOLDER}/${args_ROOT_DIR}/${args_SOURCE_DIR}/${args_INCLUDE_DIR})
endforeach()
include_directories(${${args_TARGET}_INCLUDE_DIRS})
else()
message(FATAL "Error on sibr_gitlibrary for target ${args_TARGET}: missing git tag or git url.")
endif()
endfunction()

View File

@ -0,0 +1,149 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
if(__MSVCsetUserCommand_cmake_INCLUDED__)
return()
else()
set(__MSVCsetUserCommand_cmake_INCLUDED__ ON)
endif()
## Allow to configure the Debugger settings of visual studio
## Note: Using this command under linux doesn't affect anything
## On run Debug Windows local : visual will try to load a specific COMMAND with ARGS in the provided WORKING_DIR
##
## usage:
## MSVCsetUserCommand( <targetName>
## [COMMAND <myCustomAppToLaunch> | [ PATH <myCustomDirWhereIsDefaultTargetFileNameToLaunch> [FILE <myCustomExecFileToLaunch>] ] ]
## ARGS <associatedArguments>
## WORKING_DIR <whereStartTheProgram>
## )
##
## Warning 1 : All arugments () must be passed under quotes
## Warning 2 : WORKING_DIR path arg have to finish with remain slah '/'
## Warning 3 : use COMMAND for external app OR PATH (optionaly with FILE) option(s) to set your built/installed/moved target
##
## Example 1:
## include(MSVCsetUserCommand)
## MSVCsetUserCommand( UnityRenderingPlugin
## COMMAND "C:/Program Files (x86)/Unity/Editor/Unity.exe"
## ARGS "-force-opengl -projectPath \"${CMAKE_HOME_DIRECTORY}/UnityPlugins/RenderingPluginExample/UnityProject\""
## WORKING_DIR "${CMAKE_HOME_DIRECTORY}/UnityPlugins/RenderingPluginExample/UnityProject"
## VERBOSE
## )
##
## Example 2:
## include(MSVCsetUserCommand)
## MSVCsetUserCommand( ibrApp
## PATH "C:/Program Files (x86)/workspace/IBR/install"
## FILE "ibrApp${CMAKE_EXECUTABLE_SUFFIX}" ## this option line is optional since the target name didn't change between build and install step
## ARGS "-path \"${CMAKE_HOME_DIRECTORY}/dataset\""
## WORKING_DIR "${CMAKE_HOME_DIRECTORY}"
## VERBOSE
## )
##
function(MSVCsetUserCommand targetName)
cmake_parse_arguments(MSVCsuc "VERBOSE" "PATH;FILE;COMMAND;ARGS;WORKING_DIR" "" ${ARGN} )
## If no arguments are given, do not create an unecessary .vcxproj.user file
set(MSVCsuc_DEFAULT OFF)
if(MSVCsuc_PATH AND MSVCsuc_DEFAULT)
set(MSVCsuc_DEFAULT OFF)
endif()
if(MSVCsuc_FILE AND MSVCsuc_DEFAULT)
set(MSVCsuc_DEFAULT OFF)
endif()
if(NOT MSVCsuc_COMMAND)
if(MSVCsuc_PATH AND MSVCsuc_FILE)
set(MSVCsuc_COMMAND "${MSVCsuc_PATH}\\${MSVCsuc_FILE}")
elseif(MSVCsuc_PATH)
set(MSVCsuc_COMMAND "${MSVCsuc_PATH}\\$(TargetFileName)")
else()
set(MSVCsuc_COMMAND "$(TargetPath)") ## => $(TargetDir)\$(TargetName)$(TargetExt)
endif()
elseif(MSVCsuc_DEFAULT)
set(MSVCsuc_DEFAULT OFF)
endif()
# NOTE: there was a typo here. there is an else if written after else statement
# changing the order of the else if statement
if(MSVCsuc_WORKING_DIR)
file(TO_NATIVE_PATH ${MSVCsuc_WORKING_DIR} MSVCsuc_WORKING_DIR)
elseif(MSVCsuc_DEFAULT)
set(MSVCsuc_DEFAULT OFF)
else()
set(MSVCsuc_WORKING_DIR "$(ProjectDir)")
endif()
if(NOT MSVCsuc_ARGS)
set(MSVCsuc_ARGS "")
elseif(MSVCsuc_DEFAULT)
set(MSVCsuc_DEFAULT OFF)
endif()
if(MSVC10 OR (MSVC AND MSVC_VERSION GREATER 1600)) # 2010 or newer
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(PLATEFORM_BITS x64)
else()
set(PLATEFORM_BITS Win32)
endif()
if(NOT MSVCsuc_DEFAULT AND PLATEFORM_BITS)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${targetName}.vcxproj.user"
"<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|${PLATEFORM_BITS}'\">
<LocalDebuggerCommand>${MSVCsuc_COMMAND}</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>${MSVCsuc_ARGS}</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerWorkingDirectory>${MSVCsuc_WORKING_DIR}</LocalDebuggerWorkingDirectory>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|${PLATEFORM_BITS}'\">
<LocalDebuggerCommand>${MSVCsuc_COMMAND}</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>${MSVCsuc_ARGS}</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerWorkingDirectory>${MSVCsuc_WORKING_DIR}</LocalDebuggerWorkingDirectory>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='MinSizeRel|${PLATEFORM_BITS}'\">
<LocalDebuggerCommand>${MSVCsuc_COMMAND}</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>${MSVCsuc_ARGS}</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerWorkingDirectory>${MSVCsuc_WORKING_DIR}</LocalDebuggerWorkingDirectory>
</PropertyGroup>
<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='RelWithDebInfo|${PLATEFORM_BITS}'\">
<LocalDebuggerCommand>${MSVCsuc_COMMAND}</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>${MSVCsuc_ARGS}</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerWorkingDirectory>${MSVCsuc_WORKING_DIR}</LocalDebuggerWorkingDirectory>
</PropertyGroup>
</Project>"
)
if(MSVCsuc_VERBOSE)
message(STATUS "[MSVCsetUserCommand] Write ${CMAKE_CURRENT_BINARY_DIR}/${targetName}.vcxproj.user file")
message(STATUS " to execute ${MSVCsuc_COMMAND} ${MSVCsuc_ARGS}")
message(STATUS " from derectory ${MSVCsuc_WORKING_DIR}")
message(STATUS " on visual studio run debugger button")
endif()
else()
message(WARNING "PLATEFORM_BITS is undefined...")
endif()
else()
if(MSVCsuc_VERBOSE)
message(WARNING "MSVCsetUserCommand is disable because too old MSVC is used (need MSVC10 2010 or newer)")
endif()
endif()
endfunction()

View File

@ -0,0 +1,104 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## Try to find the ASSIMP library
## Once done this will define
##
## ASSIMP_FOUND - system has ASSIMP
## ASSIMP_INCLUDE_DIR - The ASSIMP include directory
## ASSIMP_LIBRARIES - The libraries needed to use ASSIMP
## ASSIMP_CMD - the full path of ASSIMP executable
## ASSIMP_DYNAMIC_LIB - the Assimp dynamic lib (available only on windows as .dll file for the moment)
##
## Edited for using a bugfixed version of Assimp
if(NOT ASSIMP_DIR)
set(ASSIMP_DIR "$ENV{ASSIMP_DIR}" CACHE PATH "ASSIMP root directory")
endif()
if(ASSIMP_DIR)
file(TO_CMAKE_PATH ${ASSIMP_DIR} ASSIMP_DIR)
endif()
## set the LIB POSTFIX to find in a right directory according to what kind of compiler we use (32/64bits)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ASSIMP_SEARCH_LIB "lib64")
set(ASSIMP_SEARCH_BIN "bin64")
set(ASSIMP_SEARCH_LIB_PATHSUFFIXE "x64")
else()
set(ASSIMP_SEARCH_LIB "lib32")
set(ASSIMP_SEARCH_BIN "bin32")
set(ASSIMP_SEARCH_LIB_PATHSUFFIXE "x86")
endif()
set(PROGRAMFILESx86 "PROGRAMFILES(x86)")
FIND_PATH(ASSIMP_INCLUDE_DIR
NAMES assimp/config.h
PATHS
${ASSIMP_DIR}
## linux
/usr
/usr/local
/opt/local
## windows
"$ENV{PROGRAMFILES}/Assimp"
"$ENV{${PROGRAMFILESx86}}/Assimp"
"$ENV{ProgramW6432}/Assimp"
PATH_SUFFIXES include
)
FIND_LIBRARY(ASSIMP_LIBRARY
NAMES assimp-vc140-mt
PATHS
${ASSIMP_DIR}/${ASSIMP_SEARCH_LIB}
${ASSIMP_DIR}/lib
${ASSIMP_DIR}/lib64
## linux
/usr/${ASSIMP_SEARCH_LIB}
/usr/local/${ASSIMP_SEARCH_LIB}
/opt/local/${ASSIMP_SEARCH_LIB}
/usr/lib
/usr/local/lib
/opt/local/lib
## windows
"$ENV{PROGRAMFILES}/Assimp/${ASSIMP_SEARCH_LIB}"
"$ENV{${PROGRAMFILESx86}}/Assimp/${ASSIMP_SEARCH_LIB}"
"$ENV{ProgramW6432}/Assimp/${ASSIMP_SEARCH_LIB}"
"$ENV{PROGRAMFILES}/Assimp/lib"
"$ENV{${PROGRAMFILESx86}}/Assimp/lib"
"$ENV{ProgramW6432}/Assimp/lib"
PATH_SUFFIXES ${ASSIMP_SEARCH_LIB_PATHSUFFIXE}
)
set(ASSIMP_LIBRARIES ${ASSIMP_LIBRARY})
if(ASSIMP_LIBRARY)
get_filename_component(ASSIMP_LIBRARY_DIR ${ASSIMP_LIBRARY} PATH)
file(GLOB ASSIMP_DYNAMIC_LIB "${ASSIMP_LIBRARY_DIR}/assimp*.dll")
if(NOT ASSIMP_DYNAMIC_LIB)
message("ASSIMP_DYNAMIC_LIB is missing... at ${ASSIMP_LIBRARY_DIR}")
endif()
set(ASSIMP_DYNAMIC_LIB ${ASSIMP_DYNAMIC_LIB} CACHE PATH "Windows dll location")
endif()
MARK_AS_ADVANCED(ASSIMP_DYNAMIC_LIB ASSIMP_INCLUDE_DIR ASSIMP_LIBRARIES)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ASSIMP
REQUIRED_VARS ASSIMP_INCLUDE_DIR ASSIMP_LIBRARIES
FAIL_MESSAGE "ASSIMP wasn't found correctly. Set ASSIMP_DIR to the root SDK installation directory."
)
if(NOT ASSIMP_FOUND)
set(ASSIMP_DIR "" CACHE STRING "Path to ASSIMP install directory")
endif()

View File

@ -0,0 +1,95 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## Important Note:
## This is not an official Find*cmake. It has been written for searching through
## a custom path (EMBREE_DIR) before checking elsewhere.
##
## FindEMBREE.cmake
## Find EMBREE's includes and library
##
## This module defines :
## [in] EMBREE_DIR, The base directory to search for EMBREE (as cmake var or env var)
## [out] EMBREE_INCLUDE_DIR where to find EMBREE.h
## [out] EMBREE_LIBRARIES, EMBREE_LIBRARY, libraries to link against to use EMBREE
## [out] EMBREE_FOUND, If false, do not try to use EMBREE.
##
if(NOT EMBREE_DIR)
set(EMBREE_DIR "$ENV{EMBREE_DIR}" CACHE PATH "EMBREE root directory")
endif()
if(EMBREE_DIR)
file(TO_CMAKE_PATH ${EMBREE_DIR} EMBREE_DIR)
endif()
## set the LIB POSTFIX to find in a right directory according to what kind of compiler we use (32/64bits)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(EMBREE_SEARCH_LIB "lib64")
set(EMBREE_SEARCH_BIN "bin64")
set(EMBREE_SEARCH_LIB_PATHSUFFIXE "x64")
else()
set(EMBREE_SEARCH_LIB "lib32")
set(EMBREE_SEARCH_BIN "bin32")
set(EMBREE_SEARCH_LIB_PATHSUFFIXE "x86")
endif()
set(PROGRAMFILESx86 "PROGRAMFILES(x86)")
FIND_PATH(EMBREE_INCLUDE_DIR
NAMES embree3/rtcore_geometry.h
PATHS
${EMBREE_DIR}
## linux
/usr
/usr/local
/opt/local
## windows
"$ENV{PROGRAMFILES}/EMBREE"
"$ENV{${PROGRAMFILESx86}}/EMBREE"
"$ENV{ProgramW6432}/EMBREE"
PATH_SUFFIXES include
)
FIND_LIBRARY(EMBREE_LIBRARY
NAMES embree3
PATHS
${EMBREE_DIR}/${EMBREE_SEARCH_LIB}
${EMBREE_DIR}/lib
## linux
/usr/${EMBREE_SEARCH_LIB}
/usr/local/${EMBREE_SEARCH_LIB}
/opt/local/${EMBREE_SEARCH_LIB}
/usr/lib
/usr/local/lib
/opt/local/lib
## windows
"$ENV{PROGRAMFILES}/EMBREE/${EMBREE_SEARCH_LIB}"
"$ENV{${PROGRAMFILESx86}}/EMBREE/${EMBREE_SEARCH_LIB}"
"$ENV{ProgramW6432}/EMBREE/${EMBREE_SEARCH_LIB}"
"$ENV{PROGRAMFILES}/EMBREE/lib"
"$ENV{${PROGRAMFILESx86}}/EMBREE/lib"
"$ENV{ProgramW6432}/EMBREE/lib"
PATH_SUFFIXES ${EMBREE_SEARCH_LIB_PATHSUFFIXE}
)
set(EMBREE_LIBRARIES ${EMBREE_LIBRARY})
MARK_AS_ADVANCED(EMBREE_INCLUDE_DIR EMBREE_LIBRARIES)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(EMBREE
REQUIRED_VARS EMBREE_INCLUDE_DIR EMBREE_LIBRARIES
FAIL_MESSAGE "EMBREE wasn't found correctly. Set EMBREE_DIR to the root SDK installation directory."
)
if(NOT EMBREE_FOUND)
set(EMBREE_DIR "" CACHE STRING "Path to EMBREE install directory")
endif()

View File

@ -0,0 +1,104 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## Try to find the FFMPEG library
## Once done this will define
##
## FFMPEG_FOUND - system has FFmpeg
## FFMPEG_INCLUDE_DIR - The FFmpeg include directory
## FFMPEG_LIBRARIES - The libraries needed to use FFmpeg
## FFMPEG_DYNAMIC_LIBS - DLLs for windows
if(NOT FFMPEG_DIR)
set(FFMPEG_DIR "$ENV{FFMPEG_DIR}" CACHE PATH "FFMPEG_DIR root directory")
endif()
if(FFMPEG_DIR)
file(TO_CMAKE_PATH ${FFMPEG_DIR} FFMPEG_DIR)
endif()
MACRO(FFMPEG_FIND varname shortname headername)
# Path to include dirs
FIND_PATH(FFMPEG_${varname}_INCLUDE_DIRS
NAMES "lib${shortname}/${headername}"
PATHS
"${FFMPEG_DIR}/include" # modify this to adapt according to OS/compiler
)
#Add libraries
IF(${FFMPEG_${varname}_INCLUDE_DIRS} STREQUAL "FFMPEG_${varname}_INCLUDE_DIR-NOTFOUND")
MESSAGE(STATUS "Can't find includes for ${shortname}...")
ELSE()
FIND_LIBRARY(FFMPEG_${varname}_LIBRARIES
NAMES ${shortname}
PATHS
${FFMPEG_DIR}/lib
)
# set libraries and other variables
SET(FFMPEG_${varname}_FOUND 1)
SET(FFMPEG_${varname}_INCLUDE_DIRS ${FFMPEG_${varname}_INCLUDE_DIR})
SET(FFMPEG_${varname}_LIBS ${FFMPEG_${varname}_LIBRARIES})
ENDIF()
ENDMACRO(FFMPEG_FIND)
#Calls to ffmpeg_find to get librarires ------------------------------
FFMPEG_FIND(LIBAVFORMAT avformat avformat.h)
FFMPEG_FIND(LIBAVDEVICE avdevice avdevice.h)
FFMPEG_FIND(LIBAVCODEC avcodec avcodec.h)
FFMPEG_FIND(LIBAVUTIL avutil avutil.h)
FFMPEG_FIND(LIBSWSCALE swscale swscale.h)
# check if libs are found and set FFMPEG related variables
#SET(FFMPEG_FOUND "NO")
IF(FFMPEG_LIBAVFORMAT_FOUND
AND FFMPEG_LIBAVDEVICE_FOUND
AND FFMPEG_LIBAVCODEC_FOUND
AND FFMPEG_LIBAVUTIL_FOUND
AND FFMPEG_LIBSWSCALE_FOUND)
# All ffmpeg libs are here
SET(FFMPEG_FOUND "YES")
SET(FFMPEG_INCLUDE_DIR ${FFMPEG_LIBAVFORMAT_INCLUDE_DIRS})
SET(FFMPEG_LIBRARY_DIRS ${FFMPEG_LIBAVFORMAT_LIBRARY_DIRS})
SET(FFMPEG_LIBRARIES
${FFMPEG_LIBAVFORMAT_LIBS}
${FFMPEG_LIBAVDEVICE_LIBS}
${FFMPEG_LIBAVCODEC_LIBS}
${FFMPEG_LIBAVUTIL_LIBS}
${FFMPEG_LIBSWSCALE_LIBS} )
# add dynamic libraries
if(WIN32)
file(GLOB FFMPEG_DYNAMIC_LIBS "${FFMPEG_DIR}/bin/*.dll")
if(NOT FFMPEG_DYNAMIC_LIBS)
message("FFMPEG_DYNAMIC_LIBS is missing...")
endif()
set(FFMPEG_DYNAMIC_LIBS ${FFMPEG_DYNAMIC_LIBS} CACHE PATH "Windows dll location")
endif()
mark_as_advanced(FFMPEG_INCLUDE_DIR FFMPEG_LIBRARY_DIRS FFMPEG_LIBRARIES FFMPEG_DYNAMIC_LIBS)
ELSE ()
MESSAGE(STATUS "Could not find FFMPEG")
ENDIF()
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFMPEG
REQUIRED_VARS FFMPEG_INCLUDE_DIR FFMPEG_LIBRARIES
FAIL_MESSAGE "FFmpeg wasn't found correctly. Set FFMPEG_DIR to the root SDK installation directory."
)
if(NOT FFMPEG_FOUND)
set(FFMPEG_DIR "" CACHE STRING "Path to FFmpeg install directory")
endif()

View File

@ -0,0 +1,337 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## This file should be include and use only on WIN32 OS and once
## It allow to auto check/download and use a preconfigured 3rdParty binaries for cmake usage
## It use the downloadAndExtractZipFile cmake module to work.
##
if(__Win3rdParty_cmake_INCLUDED__)
return()
else()
set(__Win3rdParty_cmake_INCLUDED__ ON)
endif()
##
## To be sure to reset an empty cached variable but keep any other kind of variables
##
## Usage:
## check_cached_var(<var> <resetedCachedValue> <cacheType> <cacheDoc> [FORCE])
##
## <var> is the cached cmake variable you need to reset
## <resetedCachedValue> is the new default value of the reseted cached cmake variable
## <cacheType> is the kind of GUI cache input can be : FILEPATH; PATH; STRING or BOOL
## <cacheDoc> is the associated GUI cache input documentation display in the GUI
## FORCE option could be use to reset a cached variable even if it is not empty.
##
macro(check_cached_var var resetedCachedValue cacheType cacheDoc)
# message(STATUS "inside check_cached_var macro. argn=${ARGN}")
cmake_parse_arguments(ccv "FORCE" "" "" ${ARGN})
if(ccv_FORCE)
set(FORCE FORCE)
else()
set(FORCE )
endif()
if(NOT ${var} OR ccv_FORCE)
unset(${var} CACHE)
# message(STATUS "setting new cache value. var ${var} = ${resetedCachedValue}")
set(${var} "${resetedCachedValue}" CACHE ${cacheType} "${cacheDoc}" ${FORCE})
endif()
endmacro()
##
## Win3rdParty function allow to specify a directory which contain all necessary windows dependenties.
## By uploading 3rdParty directory (which contain dependencies, *.lib, *.dll... for a specific version of compiler) onto Gforge file tab,
## you get back an URL of download you can give to this function with a directory name. So you can provide multiple 3rdParty version of same dependencies (MSVC11, MSVC12...).
## By providing a prefix to this function, you allow to use different kind of 3rdParty which can be handled by CMAKE OPTIONS depending on what your framework need for example.
##
## Usage 1:
## Win3rdParty(<prefix> MSVC<XX> <DirName> <URL>
## [MSVC<XX> <DirName> <URL>] [...]
## [VCID] [DEFAULT_USE] [VERBOSE] )
##
## * <prefix> allow to identify which 3rdParty you process (prefix name)
## * MSVC<XX> flag could be MSVC11 or MSVC12 (any element of the MSVC_VERSIONS_LIST) and refer to a 3rdParty compiler with :
## * <DirName> which will be the local pathName of the downloaded 3rdParty : relative to CMAKE_BINARY_DIR
## * <URL> which is the link location of the 3rdParty zip
## * VCID flag will make available a cache variable ${prefix}_WIN3RDPARTY_VCID
## * DEFAULT_USE flag [ON|OFF] may be used to set default value of cmake cached variable : <prefix>_WIN3RDPARTY_USE [default to ON]
##
## WARNING:
## This function define CACHE variables you can use after :
## * ${prefix}_WIN3RDPARTY_USE : allow to check/downloaded win3rdParty dir (it will force the cached variables for this dependency folder generally <prefix>_DIR>)
## * ${prefix}_WIN3RDPARTY_DIR : where is your local win3rdParty dir (the PATH)
## * ${prefix}_WIN3RDPARTY_VCID : [if VCID flag is used] the MSVC id (commonly used to prefix/suffix library name, see boost or CGAL)
##
## If you want to add a win3rdParty version, please:
## 1- build dependencies on your local side with the compiler you want
## 2- build your own zip with your built dependencies
## 3- upload it (onto the forge where the project is stored) and copy the link location in order to use it for this function
## 4- if you just introduced a new MSVC version, add it to the MSVC_VERSIONS_LIST bellow
##
## In a second pass, you can also use this function to set necessary cmake cached variables in order to let cmake find packages of these 3rdParty.
##
## Usage 2:
## win3rdParty(<prefix> [VERBOSE] MULTI_SET|SET
## CHECK_CACHED_VAR <cmakeVar> <cmakeCacheType> [LIST] <cmakeValue> [DOC <stringToolTips>]
## [ CHECK_CACHED_VAR <cmakeVar> <cmakeCacheType> [LIST] <cmakeValue> [DOC <stringToolTips>] ] [...]
##
## * MULTI_SET or SET flags are used to tell cmake that all next arguments will use repeated flags with differents entries (SET mean we will provide only one set of arguments, without repetition)
## * CHECK_CACHED_VAR are the repeated flag which contain differents entries
## * <cmakeVar> is the cmake variable you want to be cached for the project
## * <cmakeCacheType> is the kind of cmake variable (couble be: FILEPATH; PATH; STRING or BOOL) => see check_cached_var.
## * LIST optional flag could be used with CHECK_CACHED_VAR when <cmakeCacheType> = STRING. It allow to handle multiple STRINGS value list.
## * <cmakeValue> is the value of the variable (if FILEPATH, PATH or STRING: use quotes, if BOOL : use ON/OFF)
## * DOC optional flag is used to have a tooltips info about this new cmake variable entry into the GUI (use quotes).
##
## Full example 1 :
## win3rdParty(COMMON MSVC11 "win3rdParty-MSVC11" "https://path.to/an.archive.7z"
## SET CHECK_CACHED_VAR SuiteSparse_DIR PATH "SuiteSparse-4.2.1" DOC "default empty doc"
## )
##
## WARNING:
## For the 2nd usage (with MULTI_SET), if you planned to set some CACHED_VAR using/composed by ${prefix}_WIN3RDPARTY_* just set in this macro (usage 1),
## then (due to the not yet existing var) you will need to call this function 2 times :
## One for the 1st usage (downloading of the current compiler 3rdParty).
## One for the MLUTI_SET flag which will use existsing ${prefix}_WIN3RDPARTY_* cached var.
##
## Full example 2 :
## win3rdParty(COMMON MSVC11 "win3rdParty-MSVC11" "https://path.to/an.archive.7z")
## win3rdParty(COMMON MULTI_SET
## CHECK_CACHED_VAR CGAL_INCLUDE_DIR PATH "CGAL-4.3/include" DOC "default empty doc"
## CHECK_CACHED_VAR CGAL_LIBRARIES STRING LIST "debug;CGAL-4.3/lib${LIB_POSTFIX}/CGAL-${WIN3RDPARTY_COMMON_VCID}-mt-gd-4.3.lib;optimized;CGAL-4.3/lib${LIB_POSTFIX}/CGAL-${WIN3RDPARTY_COMMON_VCID}-mt-4.3.lib"
##
##
## WARNING: This function use internaly :
## * downloadAndExtractZipFile.cmake
## * parse_arguments_multi.cmake
## * check_cached_var macro
##
function(win3rdParty prefix )
# ARGV: list of all arguments given to the macro/function
# ARGN: list of remaining arguments
if(NOT WIN32)
return()
endif()
## set the handled version of MSVC
## if you plan to add a win3rdParty dir to download with a new MSVC version: build the win3rdParty dir and add the MSCV entry here.
set(MSVC_VERSIONS_LIST "MSVC17;MSVC11;MSVC12;MSVC14")
#include(CMakeParseArguments) # CMakeParseArguments is obsolete since cmake 3.5
# cmake_parse_arguments (<prefix> <options> <one_value_keywords> <multi_value_keywords> args)
# <options> : options (flags) pass to the macro
# <one_value_keywords> : options that neeed a value
# <multi_value_keywords> : options that neeed more than one value
cmake_parse_arguments(w3p "VCID" "VERBOSE;TIMEOUT;DEFAULT_USE" "${MSVC_VERSIONS_LIST};MULTI_SET;SET" ${ARGN})
# message(STATUS "value of w3p_VCID = ${w3p_VCID}")
# message(STATUS "value of w3p_VERBOSE = ${w3p_VERBOSE}")
# message(STATUS "value of w3p_TIMEOUT = ${w3p_TIMEOUT}")
# message(STATUS "value of w3p_DEFAULT_USE = ${w3p_DEFAULT_USE}")
# foreach (loop_var ${MSVC_VERSIONS_LIST})
# message(STATUS "value of w3p_${loop_var} = ${w3p_${loop_var}}")
# endforeach(loop_var)
# message(STATUS "value of w3p_MULTI_SET = ${w3p_MULTI_SET}")
# message(STATUS "value of w3p_SET = ${w3p_SET}")
# message("values for MSVC = ${w3p_MSVC14}")
if(NOT w3p_TIMEOUT)
set(w3p_TIMEOUT 300)
endif()
if(NOT DEFINED w3p_DEFAULT_USE)
set(w3p_DEFAULT_USE ON)
endif()
## 1st use (check/update|download) :
set(${prefix}_WIN3RDPARTY_USE ${w3p_DEFAULT_USE} CACHE BOOL "Use required 3rdParty binaries from ${prefix}_WIN3RDPARTY_DIR or download it if not exist")
## We want to test if each version of MSVC was filled by the function (see associated parameters)
## As CMake is running only for one version of MSVC, if that MSVC version was filled, we get back associated parameters,
## otherwise we can't use the downloadAndExtractZipFile with win3rdParty.
set(enableWin3rdParty OFF)
foreach(MSVC_VER ${MSVC_VERSIONS_LIST})
if(${MSVC_VER} AND w3p_${MSVC_VER} OR ${MSVC_TOOLSET_VERSION} EQUAL 143 AND ${MSVC_VER} STREQUAL "MSVC17")
list(LENGTH w3p_${MSVC_VER} count)
if("${count}" LESS "2")
#message(WARNING "You are using ${MSVC_VER} with ${prefix}_WIN3RDPARTY_USE=${${prefix}_WIN3RDPARTY_USE}, but win3rdParty function isn't filled for ${MSVC_VER}!")
else()
list(GET w3p_${MSVC_VER} 0 Win3rdPartyName)
list(GET w3p_${MSVC_VER} 1 Win3rdPartyUrl)
if(w3p_VCID)
## try to get the VcId of MSVC. See also MSVC_VERSION cmake var in the doc.
string(REGEX REPLACE "MS([A-Za-z_0-9-]+)" "\\1" vcId ${MSVC_VER})
string(TOLOWER ${vcId} vcId)
set(${prefix}_WIN3RDPARTY_VCID "${vcId}0" CACHE STRING "the MSVC id (commonly used to prefix/suffix library name, see boost or CGAL)")
mark_as_advanced(${prefix}_WIN3RDPARTY_VCID)
endif()
set(enableWin3rdParty ON)
set(suffixCompilerID ${MSVC_VER})
break()
endif()
endif()
endforeach()
## If previous step succeed to get MSVC dirname and URL of the current MSVC version, use it to auto download/update the win3rdParty dir
if(enableWin3rdParty AND ${prefix}_WIN3RDPARTY_USE)
if(IS_ABSOLUTE "${Win3rdPartyName}")
else()
set(Win3rdPartyName "${CMAKE_BINARY_DIR}/${Win3rdPartyName}")
endif()
if(NOT EXISTS "${Win3rdPartyName}")
file(MAKE_DIRECTORY ${Win3rdPartyName})
endif()
include(downloadAndExtractZipFile)
downloadAndExtractZipFile( "${Win3rdPartyUrl}" ## URL link location
"Win3rdParty-${prefix}-${suffixCompilerID}.7z" ## where download it: relative path, so default to CMAKE_BINARY_DIR
"${Win3rdPartyName}" ## where extract it : fullPath (default relative to CMAKE_BINARY_DIR)
CHECK_DIRTY_URL "${Win3rdPartyName}/Win3rdPartyUrl" ## last downloaded url file : fullPath (default relative to CMAKE_BINARY_DIR)
TIMEOUT ${w3p_TIMEOUT}
VERBOSE ${w3p_VERBOSE}
)
file(GLOB checkDl "${Win3rdPartyName}/*")
list(LENGTH checkDl checkDlCount)
if("${checkDlCount}" GREATER "1")
else()
message("The downloadAndExtractZipFile didn't work...?")
set(enableWin3rdParty OFF)
endif()
endif()
## Try to auto set ${prefix}_WIN3RDPARTY_DIR or let user set it manually
set(${prefix}_WIN3RDPARTY_DIR "" CACHE PATH "windows ${Win3rdPartyName} dir to ${prefix} dependencies of the project")
if(NOT ${prefix}_WIN3RDPARTY_DIR AND ${prefix}_WIN3RDPARTY_USE)
if(EXISTS "${Win3rdPartyName}")
unset(${prefix}_WIN3RDPARTY_DIR CACHE)
set(${prefix}_WIN3RDPARTY_DIR "${Win3rdPartyName}" CACHE PATH "dir to ${prefix} dependencies of the project")
endif()
endif()
if(EXISTS ${${prefix}_WIN3RDPARTY_DIR})
message(STATUS "Found a 3rdParty ${prefix} dir : ${${prefix}_WIN3RDPARTY_DIR}.")
set(enableWin3rdParty ON)
elseif(${prefix}_WIN3RDPARTY_USE)
message(WARNING "${prefix}_WIN3RDPARTY_USE=${${prefix}_WIN3RDPARTY_USE} but ${prefix}_WIN3RDPARTY_DIR=${${prefix}_WIN3RDPARTY_DIR}.")
set(enableWin3rdParty OFF)
endif()
## Final check
if(NOT enableWin3rdParty)
message("Disable ${prefix}_WIN3RDPARTY_USE (cmake cached var will be not set), due to a win3rdParty problem.")
message("You still can set ${prefix}_WIN3RDPARTY_DIR to an already downloaded Win3rdParty directory location.")
set(${prefix}_WIN3RDPARTY_USE OFF CACHE BOOL "Use required 3rdParty binaries from ${prefix}_WIN3RDPARTY_DIR or download it if not exist" FORCE)
endif()
## 2nd use : handle multi values args to set cached cmake variables in order to ease the next find_package call
if(${prefix}_WIN3RDPARTY_USE AND ${prefix}_WIN3RDPARTY_DIR)
if(w3p_VERBOSE)
message(STATUS "Try to set cmake cached variables for ${prefix} required libraries directly from : ${${prefix}_WIN3RDPARTY_DIR}.")
endif()
include(parse_arguments_multi)
# message (STATUS "before defining an override of parse_arguments_multi_function")
function(parse_arguments_multi_function ) ## overloaded function to handle all CHECK_CACHED_VAR values list (see: parse_arguments_multi)
# message(STATUS "inside overloaded parse_arguments_multi_function defined in Win3rdParty.cmake")
# message(STATUS ${ARGN})
## we know the function take 3 args : var cacheType resetedCachedValue (see check_cached_var)
cmake_parse_arguments(pamf "" "DOC" "LIST" ${ARGN})
## var and cacheType are mandatory (with the resetedCachedValue)
set(var ${ARGV0})
set(cacheType ${ARGV1})
# message(STATUS "var=${var} and cacheType=${cacheType} list=${pamf_LIST}")
if(pamf_DOC)
set(cacheDoc ${pamf_DOC})
else()
set(cacheDoc "")
endif()
if(pamf_LIST)
set(value ${pamf_LIST})
else()
# message("USING ARGV2 with value ${ARGV2}")
set(value ${ARGV2})
endif()
# message("inside override function in Win3rdparty.cmake value+ ${value}")
if("${cacheType}" MATCHES "PATH" AND EXISTS "${${prefix}_WIN3RDPARTY_DIR}/${value}")
# message("math with path")
set(resetedCachedValue "${${prefix}_WIN3RDPARTY_DIR}/${value}") ## path relative to ${prefix}_WIN3RDPARTY_DIR
elseif ("${cacheType}" MATCHES "PATH" AND EXISTS "${${prefix}_WIN3RDPARTY_DIR}")
set(resetedCachedValue "${${prefix}_WIN3RDPARTY_DIR}") ## path relative to ${prefix}_WIN3RDPARTY_DIR
elseif("${cacheType}" MATCHES "STRING")
foreach(var IN LISTS value)
if(EXISTS "${${prefix}_WIN3RDPARTY_DIR}/${var}")
list(APPEND resetedCachedValue "${${prefix}_WIN3RDPARTY_DIR}/${var}") ## string item of the string list is a path => make relative to ${prefix}_WIN3RDPARTY_DIR
else()
list(APPEND resetedCachedValue ${var}) ## string item of the string list is not an existing path => simply use the item
endif()
endforeach()
else()
set(resetedCachedValue "${value}") ## could be a BOOL or a STRING
endif()
## call our macro to reset cmake cache variable if empty
check_cached_var(${var} "${resetedCachedValue}" ${cacheType} "${cacheDoc}" FORCE)
endfunction()
# message (STATUS "after defining an override of parse_arguments_multi_function")
if(w3p_MULTI_SET)
parse_arguments_multi(CHECK_CACHED_VAR w3p_MULTI_SET ${w3p_MULTI_SET}) ## internaly will call our overloaded parse_arguments_multi_function
elseif(w3p_SET)
# message("calling set version of parse_arguments_multi with w3p_set = ${w3p_SET}")
parse_arguments_multi(CHECK_CACHED_VAR w3p_SET ${w3p_SET})
endif()
endif()
endfunction()
## cmake variables introspection to globally activate/deactivate ${prefix}_WIN3RDPARTY_USE
## This "one shot" call (only one for the next cmake configure) will automatically then reset the global variable WIN3RDPARTY_USE to UserDefined (do nothing).
## use (call it) before and after the call of all your win3rdParty functions
function(Win3rdPartyGlobalCacheAction )
set(WIN3RDPARTY_USE "UserDefined" CACHE STRING "Choose how to handle all cmake cached *_WIN3RDPARTY_USE for the next configure.\nCould be:\nUserDefined [default]\nActivateAll\nDesactivateAll" )
set_property(CACHE WIN3RDPARTY_USE PROPERTY STRINGS "UserDefined;ActivateAll;DesactivateAll" )
if(${WIN3RDPARTY_USE} MATCHES "UserDefined")
else()
if(${WIN3RDPARTY_USE} MATCHES "ActivateAll")
set(win3rdPvalue ON)
elseif(${WIN3RDPARTY_USE} MATCHES "DesactivateAll")
set(win3rdPvalue OFF)
endif()
get_cmake_property(_variableNames CACHE_VARIABLES)
foreach (_variableName ${_variableNames})
string(REGEX MATCH "[A-Za-z_0-9-]+_WIN3RDPARTY_USE" win3rdpartyUseCacheVar ${_variableName})
if(win3rdpartyUseCacheVar)
string(REGEX REPLACE "([A-Za-z_0-9-]+_WIN3RDPARTY_USE)" "\\1" win3rdpartyUseCacheVar ${_variableName})
set(${win3rdpartyUseCacheVar} ${win3rdPvalue} CACHE BOOL "Use required 3rdParty binaries from ${prefix}_WIN3RDPARTY_DIR or download it if not exist" FORCE)
message(STATUS "${win3rdpartyUseCacheVar} cached variable set to ${win3rdPvalue}.")
endif()
endforeach()
set(WIN3RDPARTY_USE "UserDefined" CACHE STRING "Choose how to handle all cmake cached *_WIN3RDPARTY_USE for the next configure.\nCould be:\nUserDefined [default]\nActivateAll\nDesactivateAll" FORCE)
message(STATUS "reset WIN3RDPARTY_USE to UserDefined.")
endif()
mark_as_advanced(WIN3RDPARTY_USE)
endfunction()

View File

@ -0,0 +1,19 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
if(__set_policies_INCLUDED__)
return()
else()
set(__set_policies_INCLUDED__ ON)
endif()
macro(setPolicies)
# No more policies to enforce
endmacro()

View File

@ -0,0 +1,292 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## Included once for all sub project.
## It contain the whole cmake instructions to find necessary common dependencies.
## 3rdParty (provided by sibr_addlibrary win3rdParty or from external packages) are then available in cmake sub projects.
##
## Do not include this file more than once but you can modify it to fit to your own project.
## So please, read it carefully because you can use on of these dependencies for your project or appen new one.
##
## As it is included after camke options, you can use conditional if(<CMAKE_PROJ_OPT>)/endif() to encapsulate your 3rdParty.
##
## win3rdParty function allowing to auto check/download/update binaries dependencies for current windows compiler
## Please open this file in order to get more documentation and usage examples.
include(Win3rdParty)
include(sibr_library)
Win3rdPartyGlobalCacheAction()
find_package(OpenGL REQUIRED)
############
## Find GLEW
############
if (MSVC11 OR MSVC12)
set(glew_multiset_arguments
CHECK_CACHED_VAR GLEW_INCLUDE_DIR PATH "glew-1.10.0/include" DOC "default empty doc"
CHECK_CACHED_VAR GLEW_LIBRARIES STRING LIST "debug;glew-1.10.0/${LIB_BUILT_DIR}/glew32d.lib;optimized;glew-1.10.0/${LIB_BUILT_DIR}/glew32.lib" DOC "default empty doc"
)
elseif (MSVC14)
set(glew_multiset_arguments
CHECK_CACHED_VAR GLEW_INCLUDE_DIR PATH "glew-2.0.0/include" DOC "default empty doc"
CHECK_CACHED_VAR GLEW_SHARED_LIBRARY_RELEASE PATH "glew-2.0.0/${LIB_BUILT_DIR}/glew32.lib"
CHECK_CACHED_VAR GLEW_STATIC_LIBRARY_RELEASE PATH "glew-2.0.0/${LIB_BUILT_DIR}/glew32s.lib"
CHECK_CACHED_VAR GLEW_SHARED_LIBRARY_DEBUG PATH "glew-2.0.0/${LIB_BUILT_DIR}/glew32d.lib"
CHECK_CACHED_VAR GLEW_STATIC_LIBRARY_DEBUG PATH "glew-2.0.0/${LIB_BUILT_DIR}/glew32sd.lib"
)
else ()
message("There is no provided GLEW library for your version of MSVC")
endif()
sibr_addlibrary(NAME GLEW #VERBOSE ON
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/glew-1.10.0.7z"
MSVC12 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/glew-1.10.0.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/glew-2.0.0.7z" # using recompiled version of glew
MULTI_SET ${glew_multiset_arguments}
)
set(GLEW_VERBOSE ON)
FIND_PACKAGE(GLEW REQUIRED)
IF(GLEW_FOUND)
INCLUDE_DIRECTORIES(${GLEW_INCLUDE_DIR})
ELSE(GLEW_FOUND)
MESSAGE("GLEW not found. Set GLEW_DIR to base directory of GLEW.")
ENDIF(GLEW_FOUND)
##############
## Find ASSIMP
##############
if (MSVC11 OR MSVC12)
set(assimp_set_arguments
CHECK_CACHED_VAR ASSIMP_DIR PATH "Assimp_3.1_fix"
)
elseif (MSVC14)
set(assimp_set_arguments
CHECK_CACHED_VAR ASSIMP_DIR PATH "Assimp-4.1.0"
)
else ()
message("There is no provided ASSIMP library for your version of MSVC")
endif()
sibr_addlibrary(NAME ASSIMP #VERBOSE ON
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/Assimp_3.1_fix.7z"
MSVC12 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/Assimp_3.1_fix.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/Assimp-4.1.0.7z"
MULTI_SET
${assimp_set_arguments}
)
find_package(ASSIMP REQUIRED)
include_directories(${ASSIMP_INCLUDE_DIR})
################
## Find FFMPEG
################
sibr_addlibrary(NAME FFMPEG
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/ffmpeg.zip"
MSVC12 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/ffmpeg.zip"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/ffmpeg-4.0.2-win64-win3rdParty.7z"
SET CHECK_CACHED_VAR FFMPEG_DIR PATH ${FFMPEG_WIN3RDPARTY_DIR}
)
find_package(FFMPEG QUIET)
include_directories(${FFMPEG_INCLUDE_DIR})
###################
## Find embree3
###################
sibr_addlibrary(
NAME embree3
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/embree2.7.0.x64.windows.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/embree-3.6.1.x64.vc14.windows.7z" # TODO SV: provide a valid version if required
)
###################
## Find eigen3
###################
sibr_addlibrary(
NAME eigen3
#MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/eigen-eigen-dc6cfdf9bcec.7z"
#MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/eigen-eigen-dc6cfdf9bcec.7z" # TODO SV: provide a valid version if required
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/eigen3.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/eigen3.7z"
SET CHECK_CACHED_VAR eigen3_DIR PATH "eigen/share/eigen3/cmake"
)
include_directories(/usr/include/eigen3)
add_definitions(-DEIGEN_INITIALIZE_MATRICES_BY_ZERO)
#############
## Find Boost
#############
set(Boost_REQUIRED_COMPONENTS "system;chrono;filesystem;date_time" CACHE INTERNAL "Boost Required Components")
if (WIN32)
# boost multiset arguments
if (MSVC11 OR MSVC12)
set(boost_multiset_arguments
CHECK_CACHED_VAR BOOST_ROOT PATH "boost_1_55_0"
CHECK_CACHED_VAR BOOST_INCLUDEDIR PATH "boost_1_55_0"
CHECK_CACHED_VAR BOOST_LIBRARYDIR PATH "boost_1_55_0/${LIB_BUILT_DIR}"
#CHECK_CACHED_VAR Boost_COMPILER STRING "-${Boost_WIN3RDPARTY_VCID}" DOC "vcid (eg: -vc110 for MSVC11)"
CHECK_CACHED_VAR Boost_COMPILER STRING "-vc110" DOC "vcid (eg: -vc110 for MSVC11)" # NOTE: if it doesnt work, uncomment this option and set the right value for VisualC id
)
elseif (MSVC14)
set(boost_multiset_arguments
CHECK_CACHED_VAR BOOST_ROOT PATH "boost-1.71"
CHECK_CACHED_VAR BOOST_INCLUDEDIR PATH "boost-1.71"
CHECK_CACHED_VAR BOOST_LIBRARYDIR PATH "boost-1.71/${LIB_BUILT_DIR}"
CHECK_CACHED_VAR Boost_COMPILER STRING "-vc141" DOC "vcid (eg: -vc110 for MSVC11)" # NOTE: if it doesnt work, uncomment this option and set the right value for VisualC id
)
option(BOOST_MINIMAL_VERSION "Only get minimal Boost dependencies" ON)
if(${BOOST_MINIMAL_VERSION})
set(BOOST_MSVC14_ZIP "boost-1.71-ibr-minimal.7z")
else()
set(BOOST_MSVC14_ZIP "boost-1.71.7z")
endif()
else ()
message("There is no provided Boost library for your version of MSVC")
endif()
sibr_addlibrary(NAME Boost VCID TIMEOUT 600 #VERBOSE ON
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/boost_1_55_0.7z"
MSVC12 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC11-splitted%20version/boost_1_55_0.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/${BOOST_MSVC14_ZIP}" # boost compatible with msvc14
MULTI_SET ${boost_multiset_arguments}
CHECK_CACHED_VAR Boost_NO_SYSTEM_PATHS BOOL ON DOC "Set to ON to disable searching in locations not specified by these boost cached hint variables"
CHECK_CACHED_VAR Boost_NO_BOOST_CMAKE BOOL ON DOC "Set to ON to disable the search for boost-cmake (package cmake config file if boost was built with cmake)"
)
if(NOT Boost_COMPILER AND Boost_WIN3RDPARTY_USE)
message(WARNING "Boost_COMPILER is not set and it's needed.")
endif()
endif()
find_package(Boost 1.71.0 REQUIRED COMPONENTS ${Boost_REQUIRED_COMPONENTS})
if(WIN32)
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/EHsc>")
#add_definitions(/EHsc)
endif()
if(Boost_LIB_DIAGNOSTIC_DEFINITIONS)
add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
endif()
#if(WIN32)
add_definitions(-DBOOST_ALL_DYN_LINK -DBOOST_ALL_NO_LIB)
#endif()
include_directories(${BOOST_INCLUDEDIR} ${Boost_INCLUDE_DIRS})
link_directories(${BOOST_LIBRARYDIR} ${Boost_LIBRARY_DIRS})
##############
## Find OpenMP
##############
find_package(OpenMP)
sibr_addlibrary(
NAME NativeFileDialog
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/sibr/~0.9/nfd.7z"
)
##############
## Find OpenCV
##############
if (WIN32)
if (${MSVC_TOOLSET_VERSION} EQUAL 143)
MESSAGE("SPECIAL OPENCV HANDLING")
set(opencv_set_arguments
CHECK_CACHED_VAR OpenCV_DIR PATH "install" ## see OpenCVConfig.cmake
)
elseif (MSVC11 OR MSVC12)
set(opencv_set_arguments
CHECK_CACHED_VAR OpenCV_DIR PATH "opencv/build" ## see OpenCVConfig.cmake
)
elseif (MSVC14)
set(opencv_set_arguments
CHECK_CACHED_VAR OpenCV_DIR PATH "opencv-4.5.0/build" ## see OpenCVConfig.cmake
)
else ()
message("There is no provided OpenCV library for your compiler, relying on find_package to find it")
endif()
else()
message("There is no provided OpenCV library for your compiler, relying on find_package to find it")
endif()
sibr_addlibrary(NAME OpenCV #VERBOSE ON
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/sibr/~0.9/opencv.7z"
MSVC12 "https://repo-sam.inria.fr/fungraph/dependencies/sibr/~0.9/opencv.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/sibr/~0.9/opencv-4.5.0.7z" # opencv compatible with msvc14 and with contribs
MSVC17 "https://repo-sam.inria.fr/fungraph/dependencies/sibr/~0.9/opencv4-8.7z"
SET ${opencv_set_arguments}
)
find_package(OpenCV REQUIRED) ## Use directly the OpenCVConfig.cmake provided
##https://stackoverflow.com/questions/24262081/cmake-relwithdebinfo-links-to-debug-libs
set_target_properties(${OpenCV_LIBS} PROPERTIES MAP_IMPORTED_CONFIG_RELWITHDEBINFO RELEASE)
add_definitions(-DOPENCV_TRAITS_ENABLE_DEPRECATED)
if(OpenCV_INCLUDE_DIRS)
foreach(inc ${OpenCV_INCLUDE_DIRS})
if(NOT EXISTS ${inc})
set(OpenCV_INCLUDE_DIR "" CACHE PATH "additional custom include DIR (in case of trouble to find it (fedora 17 opencv package))")
endif()
endforeach()
if(OpenCV_INCLUDE_DIR)
list(APPEND OpenCV_INCLUDE_DIRS ${OpenCV_INCLUDE_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
endif()
endif()
###################
## Find GLFW
###################
sibr_addlibrary(
NAME GLFW
MSVC11 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/glfw-3.2.1.7z"
MSVC14 "https://repo-sam.inria.fr/fungraph/dependencies/ibr-common/win3rdParty-MSVC15-splitted%20version/glfw-3.2.1.7z" # TODO SV: provide a valid version if required
)
sibr_gitlibrary(TARGET imgui
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/imgui.git"
GIT_TAG "e7f0fa31b9fa3ee4ecd2620b9951f131b4e377c6"
)
sibr_gitlibrary(TARGET mrf
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/mrf.git"
GIT_TAG "564e5e0b395c788d2f8b2cf4f879fed2493faea7"
)
sibr_gitlibrary(TARGET nanoflann
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/nanoflann.git"
GIT_TAG "7a20a9ac0a1d34850fc3a9e398fc4a7618e8a69a"
)
sibr_gitlibrary(TARGET picojson
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/picojson.git"
GIT_TAG "7cf8feee93c8383dddbcb6b64cf40b04e007c49f"
)
sibr_gitlibrary(TARGET rapidxml
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/rapidxml.git"
GIT_TAG "069e87f5ec5ce1745253bd64d89644d6b894e516"
)
sibr_gitlibrary(TARGET xatlas
GIT_REPOSITORY "https://gitlab.inria.fr/sibr/libs/xatlas.git"
GIT_TAG "0fbe06a5368da13fcdc3ee48d4bdb2919ed2a249"
INCLUDE_DIRS "source/xatlas"
)
Win3rdPartyGlobalCacheAction()

View File

@ -0,0 +1,243 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## downloadAndExtractZipFile cmake function
## Provide a way to download zip file from public internet ZIP_URL host
## and to extract it in a specific EXCTRATED_ZIP_PATH destination.
## This function use 7-Zip external tool to maximize the compatibles formats.
## This will be not download again if the EXCTRATED_ZIP_PATH already exist and DL_FORCE is set to OFF.
## This will try to unzip file if already exist in the ZIP_DL_PATH.
##
## If EXCTRATED_ZIP_PATH and/or ZIP_DL_PATH are not full path,
## it will be interpreted relative to CMAKE_BINARY_DIR
##
## Usage example :
## include(downloadAndExtractZipFile)
## downloadAndExtractZipFile(
## http://www.cs.cornell.edu/~snavely/bundler/distr/bundler-v0.4-source.zip
## ${CMAKE_BINARY_DIR}/Bundler/bundler-v0.4-source.zip
## ${CMAKE_BINARY_DIR}/Bundler
## [DL_FORCE ON|OFF]
## [TIMEOUT]
## [CHECK_DIRTY_URL]
## )
##
## option DL_FORCE will redownload the zip file [deafult to OFF]
## option TIMEOUT will end the unzip process after this period of time [default to 600s]
## option CHECK_DIRTY_URL will write into the given file the downloaded URL and then,
## next time, if the URL was updated, it detect it with this file
## and will download the last version. This prevent to alway set manually DL_FORCE to ON...
##
if(__downloadAndExtractZipFile_cmake_INCLUDED__)
return()
else()
set(__downloadAndExtractZipFile_cmake_INCLUDED__ ON)
endif()
function(downloadAndExtractZipFile ZIP_URL ZIP_DL_PATH EXCTRATED_ZIP_PATH)
# message(STATUS "zipUrl=${ZIP_URL} zipDlPath=${ZIP_DL_PATH} extractedZipPath=${EXCTRATED_ZIP_PATH}")
cmake_parse_arguments(dwnlezf "" "VERBOSE;DL_FORCE;TIMEOUT;CHECK_DIRTY_URL" "" ${ARGN})
set(PROGRAMFILESx86 "PROGRAMFILES(x86)")
## Check entries mandatory args
if(IS_ABSOLUTE "${ZIP_DL_PATH}")
else()
set(ZIP_DL_PATH "${CMAKE_BINARY_DIR}/${ZIP_DL_PATH}")
endif()
if(IS_ABSOLUTE "${EXCTRATED_ZIP_PATH}")
else()
set(EXCTRATED_ZIP_PATH "${CMAKE_BINARY_DIR}/${EXCTRATED_ZIP_PATH}")
endif()
if(NOT EXISTS "${EXCTRATED_ZIP_PATH}")
file(MAKE_DIRECTORY ${EXCTRATED_ZIP_PATH})
endif()
# SB: Once, one of downloaded zip was corrupted by an error message coming from the server.
if(EXISTS "${ZIP_DL_PATH}")
# So I check for removing such corrupted files
message("Removing previous ${ZIP_DL_PATH} (might be corrupted)")
file(REMOVE "${ZIP_DL_PATH}")
if(EXISTS "${dwnlezf_CHECK_DIRTY_URL}")
# and remove the previous (corrupted) made 'Win3rdPartyUrl' file
file(REMOVE "${dwnlezf_CHECK_DIRTY_URL}")
endif()
endif()
## Check entries optional args
macro(readDirtyUrl )
if(dwnlezf_CHECK_DIRTY_URL)
if(IS_ABSOLUTE "${dwnlezf_CHECK_DIRTY_URL}")
else()
set(dwnlezf_CHECK_DIRTY_URL "${CMAKE_BINARY_DIR}/${dwnlezf_CHECK_DIRTY_URL}")
endif()
get_filename_component(unzipDir ${EXCTRATED_ZIP_PATH} NAME)
get_filename_component(unzipPath ${EXCTRATED_ZIP_PATH} PATH)
message(STATUS "Checking ${unzipDir} [from ${unzipPath}]...")
if(EXISTS "${dwnlezf_CHECK_DIRTY_URL}")
get_filename_component(CHECK_DIRTY_URL_FILENAME ${dwnlezf_CHECK_DIRTY_URL} NAME)
file(STRINGS "${dwnlezf_CHECK_DIRTY_URL}" contents)
list(GET contents 0 downloadURL)
list(REMOVE_AT contents 0)
if("${downloadURL}" MATCHES "${ZIP_URL}")
if(dwnlezf_VERBOSE)
message(STATUS "Your downloaded version (URL) seems to be up to date. Let me check if nothing is missing... (see ${dwnlezf_CHECK_DIRTY_URL}).")
endif()
file(GLOB PATHNAME_PATTERN_LIST "${EXCTRATED_ZIP_PATH}/*") ## is there something inside the downloaded destination ?
unset(NAME_PATTERN_LIST)
foreach(realPathPattern ${PATHNAME_PATTERN_LIST})
get_filename_component(itemName ${realPathPattern} NAME)
list(APPEND NAME_PATTERN_LIST ${itemName})
endforeach()
if(NAME_PATTERN_LIST)
foreach(item ${contents})
list(FIND NAME_PATTERN_LIST ${item} id)
if(${id} MATCHES "-1")
message(STATUS "${item} is missing, your downloaded version content changed, need to redownload it.")
set(ZIP_DL_FORCE ON)
break()
else()
list(REMOVE_AT NAME_PATTERN_LIST ${id})
set(ZIP_DL_FORCE OFF)
endif()
endforeach()
if(NOT ZIP_DL_FORCE AND NAME_PATTERN_LIST)
message("Yours seems to be up to date (regarding to ${CHECK_DIRTY_URL_FILENAME})!\nBut there are additional files/folders into your downloaded destination (feel free to clean it if you want).")
foreach(item ${NAME_PATTERN_LIST})
if(item)
message("${item}")
endif()
endforeach()
endif()
endif()
else()
set(ZIP_DL_FORCE ON)
message(STATUS "Your downloaded version is dirty (too old).")
endif()
else()
file(GLOB PATHNAME_PATTERN_LIST "${EXCTRATED_ZIP_PATH}/*") ## is there something inside the downloaded destination ?
if(NOT PATHNAME_PATTERN_LIST)
message("We found nothing into ${EXCTRATED_ZIP_PATH}, we will try to download it for you now.")
endif()
set(ZIP_DL_FORCE ON)
endif()
endif()
endmacro()
readDirtyUrl()
if(NOT ZIP_DL_FORCE)
return() ## do not need to further (as we are up to date, just exit the function
endif()
macro(writeDirtyUrl )
if(dwnlezf_CHECK_DIRTY_URL)
file(WRITE "${dwnlezf_CHECK_DIRTY_URL}" "${ZIP_URL}\n")
file(GLOB PATHNAME_PATTERN_LIST "${EXCTRATED_ZIP_PATH}/*") ## is there something inside the downloaded destination ?
unset(NAME_PATTERN_LIST)
foreach(realPathPattern ${PATHNAME_PATTERN_LIST})
get_filename_component(itemName ${realPathPattern} NAME)
list(APPEND NAME_PATTERN_LIST ${itemName})
endforeach()
if(NAME_PATTERN_LIST)
foreach(item ${NAME_PATTERN_LIST})
file(APPEND "${dwnlezf_CHECK_DIRTY_URL}" "${item}\n")
endforeach()
endif()
endif()
endmacro()
if(dwnlezf_DL_FORCE)
set(ZIP_DL_FORCE ON)
endif()
if(NOT dwnlezf_TIMEOUT)
set(dwnlezf_TIMEOUT 600)
endif()
math(EXPR dwnlezf_TIMEOUT_MIN "${dwnlezf_TIMEOUT}/60")
macro(unzip whichZipFile)
if(NOT SEVEN_ZIP_CMD)
find_program(SEVEN_ZIP_CMD NAMES 7z 7za p7zip DOC "7-zip executable" PATHS "$ENV{PROGRAMFILES}/7-Zip" "$ENV{${PROGRAMFILESx86}}/7-Zip" "$ENV{ProgramW6432}/7-Zip")
endif()
if(SEVEN_ZIP_CMD)
if(dwnlezf_VERBOSE)
message(STATUS "UNZIP: please, WAIT UNTIL ${SEVEN_ZIP_CMD} finished...\n(no more than ${dwnlezf_TIMEOUT_MIN} min)")
else()
message(STATUS "UNZIP...wait...")
endif()
execute_process( COMMAND ${SEVEN_ZIP_CMD} x ${whichZipFile} -y
WORKING_DIRECTORY ${EXCTRATED_ZIP_PATH} TIMEOUT ${dwnlezf_TIMEOUT}
RESULT_VARIABLE resVar OUTPUT_VARIABLE outVar ERROR_VARIABLE errVar
)
if(${resVar} MATCHES "0")
if(dwnlezf_VERBOSE)
message(STATUS "SUCESS to unzip in ${EXCTRATED_ZIP_PATH}. Now we can remove the downloaded zip file.")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${whichZipFile})
mark_as_advanced(SEVEN_ZIP_CMD)
else()
message(WARNING "something wrong in ${EXCTRATED_ZIP_PATH}\n with \"${SEVEN_ZIP_CMD} x ${whichZipFile} -y\", redo or try to unzip by yourself...")
message("unzip: resVar=${resVar}")
message("unzip: outVar=${outVar}")
message("unzip: errVar=${errVar}")
message("unzip: failed or canceled or timeout")
endif()
else()
message(WARNING "You need 7zip (http://www.7-zip.org/download.html) to unzip the downloaded dir.")
set(SEVEN_ZIP_CMD "" CACHE FILEPATH "7-zip executable")
mark_as_advanced(CLEAR SEVEN_ZIP_CMD)
endif()
endmacro()
if(dwnlezf_VERBOSE)
message(STATUS "Trying to look ${ZIP_DL_PATH} if a zip file exist...")
endif()
if(EXISTS "${ZIP_DL_PATH}")
## already downloaded, so just unzip it
unzip(${ZIP_DL_PATH})
writeDirtyUrl()
elseif(ZIP_DL_FORCE)
## the download part (+ unzip)
message(STATUS "Let me try to download package for you : ${ZIP_URL}")
if(dwnlezf_VERBOSE)
message(STATUS "Downloading...\n SRC=${ZIP_URL}\n DEST=${ZIP_DL_PATH}.tmp\n INACTIVITY_TIMEOUT=180s")
endif()
file(DOWNLOAD ${ZIP_URL} ${ZIP_DL_PATH}.tmp INACTIVITY_TIMEOUT 360 STATUS status SHOW_PROGRESS)
list(GET status 0 numResult)
if(${numResult} MATCHES "0")
if(dwnlezf_VERBOSE)
message(STATUS "Download succeed, so let me rename the tmp file to unzip it")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} -E rename ${ZIP_DL_PATH}.tmp ${ZIP_DL_PATH})
unzip(${ZIP_DL_PATH})
writeDirtyUrl()
else()
list(GET status 1 errMsg)
message(WARNING "DOWNLOAD ${ZIP_URL} to ${ZIP_DL_PATH} failed\n:${errMsg}")
message(WARNING "OK, you need to download the ${ZIP_URL} manually and put it into ${ZIP_DL_PATH}")
message("Take a look at the project website page to check available URL.")
endif()
endif()
## clean up the tmp downloaded file
if(EXISTS "${ZIP_DL_PATH}.tmp")
execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${ZIP_DL_PATH}.tmp)
endif()
endfunction()

View File

@ -0,0 +1,114 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
if(__git_describe_INCLUDED__)
return()
else()
set(__git_describe_INCLUDED__ ON)
endif()
find_package(Git)
if(Git_FOUND)
message(STATUS "Git found: ${GIT_EXECUTABLE}")
else()
message(FATAL_ERROR "Git not found. Aborting")
endif()
macro(git_describe)
cmake_parse_arguments(GIT_DESCRIBE "" "GIT_URL;GIT_BRANCH;GIT_COMMIT_HASH;GIT_TAG;GIT_VERSION;PATH" "" ${ARGN})
if(NOT GIT_DESCRIBE_PATH)
set(GIT_DESCRIBE_PATH ${CMAKE_SOURCE_DIR})
endif()
if(GIT_DESCRIBE_GIT_URL)
# Get the current remote
execute_process(
COMMAND git remote
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE GIT_DESCRIBE_GIT_REMOTE
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
# Get the current remote
execute_process(
COMMAND git remote get-url ${GIT_DESCRIBE_GIT_REMOTE}
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE ${GIT_DESCRIBE_GIT_URL}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if(GIT_DESCRIBE_GIT_BRANCH)
# Get the current working branch
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE ${GIT_DESCRIBE_GIT_BRANCH}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if(GIT_DESCRIBE_GIT_COMMIT_HASH)
# Get the latest abbreviated commit hash of the working branch
execute_process(
COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE ${GIT_DESCRIBE_GIT_COMMIT_HASH}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if(GIT_DESCRIBE_GIT_TAG)
# Get the tag
execute_process(
COMMAND git describe --tags --exact-match
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE ${GIT_DESCRIBE_GIT_TAG}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()
if(GIT_DESCRIBE_GIT_VERSION)
# Get the version from git describe
execute_process(
COMMAND git describe
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE ${GIT_DESCRIBE_GIT_VERSION}
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
if(${GIT_DESCRIBE_GIT_VERSION} STREQUAL "")
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE GIT_DESCRIBE_GIT_VERSION_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
execute_process(
COMMAND git log -1 --format=%h
WORKING_DIRECTORY ${GIT_DESCRIBE_PATH}
OUTPUT_VARIABLE GIT_DESCRIBE_GIT_VERSION_COMMIT
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
set(${GIT_DESCRIBE_GIT_VERSION} "${GIT_DESCRIBE_GIT_VERSION_BRANCH}-${GIT_DESCRIBE_GIT_VERSION_COMMIT}")
endif()
endif()
endmacro()

View File

@ -0,0 +1,22 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
macro(include_once file)
get_filename_component(INCLUDE_ONCE_FILEPATH ${file} REALPATH)
string(REGEX REPLACE "(\\.|\\/+|\\:|\\\\+)" "_" INCLUDE_ONCE_FILEPATH ${INCLUDE_ONCE_FILEPATH})
get_property(INCLUDED_${INCLUDE_ONCE_FILEPATH}_LOCAL GLOBAL PROPERTY INCLUDED_${INCLUDE_ONCE_FILEPATH})
if (INCLUDED_${INCLUDE_ONCE_FILEPATH}_LOCAL)
return()
else()
set_property(GLOBAL PROPERTY INCLUDED_${INCLUDE_ONCE_FILEPATH} true)
include(${file})
endif()
endmacro()

View File

@ -0,0 +1,880 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
## This file is mainly used to allow runtime installation
## There are some utilities cmake functions to ease the generic deployement (abstract common usage of cmake)...
##
## You cannot run your programm automaticaly from your CNAKE_BINARY_DIR when you build
## as it will miss all dependencies and ressources files...
## You have to run install target in order to test your programm.
##
## The only one function/macros you may use inside your sub-CMakeLists.txt (sub-project) is :
## ******************
## ibr_install_target macro => see documentation at the end of this file
## ******************
## It use these utilities cmake functions to abstract the installation in an uniform way for all sub-projects.
##
if(__install_runtime_cmake_INCLUDED__)
return()
else()
set(__install_runtime_cmake_INCLUDED__ ON)
endif()
##
## Allow to write a resource config file which contain additional ressource paths
## (used by IBR_Common Resource system to load shaders and potentialy images, plugins and so on)
##
## ADD option list all the paths to add in the file (relative paths are interpreted relative to working dir of the executable)
## INSTALL option to specify where we want to install this file
##
## Example usage:
## resourceFile(ADD "shaders" "${PROJECT_NAME}_rsc" INSTALL bin)
##
macro(resourceFile)
cmake_parse_arguments(rsc "" "INSTALL;FILE_PATH;CONFIG_TYPE" "ADD" ${ARGN}) ## both args are directory path
if(rsc_ADD)
unset(IBR_RSC_FILE_CONTENT_LIST)
if(EXISTS "${rsc_FILE_PATH}")
file(READ "${rsc_FILE_PATH}" IBR_RSC_FILE_CONTENT)
string(REGEX REPLACE "\n" ";" IBR_RSC_FILE_CONTENT_LIST "${IBR_RSC_FILE_CONTENT}")
endif()
list(APPEND IBR_RSC_FILE_CONTENT_LIST "${rsc_ADD}")
list(REMOVE_DUPLICATES IBR_RSC_FILE_CONTENT_LIST)
file(WRITE "${rsc_FILE_PATH}" "")
foreach(rscDir ${IBR_RSC_FILE_CONTENT_LIST})
file(APPEND "${rsc_FILE_PATH}" "${rscDir}\n")
endforeach()
unset(rsc_ADD)
endif()
if(rsc_INSTALL)
install(FILES ${rsc_FILE_PATH} CONFIGURATIONS ${rsc_CONFIG_TYPE} DESTINATION ${rsc_INSTALL})
unset(rsc_INSTALL)
endif()
endmacro()
##
## Install *.pdb generated file for the current cmake project
## assuming the output target name is the cmake project name.
## This macro is useful for crossplateform multi config mode.
##
## Usage Example:
##
## if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
## installPDB(${PROJECT_NAME} ${CMAKE_BUILD_TYPE} RUNTIME_DEST bin ARCHIVE_DEST lib LIBRARY_DEST lib)
## endif()
## foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
## installPDB(${PROJECT_NAME} ${CONFIG_TYPES} RUNTIME_DEST bin ARCHIVE_DEST lib LIBRARY_DEST lib)
## endforeach()
##
macro(installPDB targetName configType)
cmake_parse_arguments(instpdb "" "COMPONENT" "ARCHIVE_DEST;LIBRARY_DEST;RUNTIME_DEST" ${ARGN}) ## both args are directory path
if(NOT MSVC)
return()
endif()
## Check if DESTINATION are provided according to the TYPE of the given target (see install command doc to see correspodances)
get_target_property(type ${targetName} TYPE)
if(${type} MATCHES "EXECUTABLE" AND instpdb_RUNTIME_DEST)
set(pdb_DESTINATION ${instpdb_RUNTIME_DEST})
elseif(${type} MATCHES "STATIC_LIBRARY" AND instpdb_ARCHIVE_DEST)
set(pdb_DESTINATION ${instpdb_ARCHIVE_DEST})
elseif(${type} MATCHES "MODULE_LIBRARY" AND instpdb_LIBRARY_DEST)
set(pdb_DESTINATION ${instpdb_LIBRARY_DEST})
elseif(${type} MATCHES "SHARED_LIBRARY")
if(WIN32 AND instpdb_RUNTIME_DEST)
set(pdb_DESTINATION ${instpdb_RUNTIME_DEST})
else()
set(pdb_DESTINATION ${instpdb_LIBRARY_DEST})
endif()
endif()
if(NOT pdb_DESTINATION)
set(pdb_DESTINATION bin) ## default destination of the pdb file
endif()
if(NOT instpdb_COMPONENT)
set(instpdb_COMPONENT )
else()
set(instpdb_COMPONENT COMPONENT ${instpdb_COMPONENT})
endif()
string(TOUPPER ${configType} CONFIG_TYPES_UC)
get_target_property(PDB_PATH ${targetName} PDB_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC})
get_target_property(confModePostfix ${targetName} ${CONFIG_TYPES_UC}_POSTFIX)
if(NOT confModePostfix)
set(confModePostfix "")
endif()
set_target_properties(${targetName} PROPERTIES PDB_NAME_${CONFIG_TYPES_UC} ${targetName}${confModePostfix})
get_target_property(PDB_NAME ${targetName} PDB_NAME_${CONFIG_TYPES_UC})# if not set, this is empty
if(EXISTS "${PDB_PATH}/${PDB_NAME}.pdb")
install(FILES "${PDB_PATH}/${PDB_NAME}.pdb" CONFIGURATIONS ${configType} DESTINATION ${pdb_DESTINATION} ${instpdb_COMPONENT} OPTIONAL)
endif()
endmacro()
##
## Add additional target to install a project independently and based on its component
## configMode is used to prevent default Release installation (we want also to install in other build/config type)
##
macro(installTargetProject targetOfProject targetOfInstallProject)
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
set(configMode ${CMAKE_BUILD_TYPE})
elseif(MSVC)
## $(Configuration) will be one of the following : Debug, Release, MinSizeRel, RelWithDebInfo
set(configMode $(Configuration))
endif()
if(configMode)
get_target_property(srcFiles ${targetOfProject} SOURCES)
add_custom_target( ${targetOfInstallProject} #ALL
${CMAKE_COMMAND} -DBUILD_TYPE=${configMode} -DCOMPONENT=${targetOfInstallProject} -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
DEPENDS ${srcFiles}
COMMENT "run the installation only for ${targetOfProject}" VERBATIM
)
add_dependencies(${targetOfInstallProject} ${targetOfProject})
get_target_property(INSTALL_BUILD_FOLDER ${targetOfProject} FOLDER)
set_target_properties(${targetOfInstallProject} PROPERTIES FOLDER ${INSTALL_BUILD_FOLDER})
endif()
endmacro()
# Collect all currently added targets in all subdirectories
#
# Parameters:
# - _result the list containing all found targets
# - _dir root directory to start looking from
function(get_all_targets _result _dir)
get_property(_subdirs DIRECTORY "${_dir}" PROPERTY SUBDIRECTORIES)
foreach(_subdir IN LISTS _subdirs)
get_all_targets(${_result} "${_subdir}")
endforeach()
get_directory_property(_sub_targets DIRECTORY "${_dir}" BUILDSYSTEM_TARGETS)
set(${_result} ${${_result}} ${_sub_targets} PARENT_SCOPE)
endfunction()
##
## Add targets for building and installing subdirectories
macro(subdirectory_target target directory build_folder)
add_custom_target(${target}
COMMENT "run build for all projects in this directory" VERBATIM
)
get_all_targets(ALL_TARGETS ${directory})
add_dependencies(${target} ${ALL_TARGETS})
add_custom_target(${target}_install
${CMAKE_COMMAND} -DBUILD_TYPE=$<CONFIG> -DCOMPONENT=${target}_install -P ${CMAKE_BINARY_DIR}/cmake_install.cmake
COMMENT "run install for all projects in this directory" VERBATIM
)
add_dependencies(${target}_install ${target})
set_target_properties(${target} PROPERTIES FOLDER ${build_folder})
set_target_properties(${target}_install PROPERTIES FOLDER ${build_folder})
endmacro()
## CMAKE install all required dependencies for an application (included system OS files like msvc*.dll for example)
##
## install_runtime(<installedFilePathTargetAppToResolve>
## [TARGET name]
## [PLUGINS name [nameN ...] [PLUGIN_PATH_NAME currentPathName [FROM_REL_PATH matchDirFromCurrentPathName] [PLUGIN_PATH_DEST installDir] ]
## [PLUGINS ...]
## [DIRS path [pathN ...] ]
## [TARGET_LIBRARIES filePath [filePathN ...] ]
## [TARGET_PACKAGES packageName [packageNameN ...] ]
## [COMPONENT installComponentName]
## [PLAUSIBLES_POSTFIX Debug_postfix [MinSizeRel_postfix relWithDebInfo_postfix ...] ]
## [VERBOSE]
## )
##
## installedFilePathTargetAppToResolve : the final installed targetApp absolute full file path name you want to resolve
##
## TARGET : The target app we want to install. If given, it's used to look for link libraries paths (best choice to use, strongly advised to use it)
##
## PLUGINS : Some application built use/load some plugins which can't be detect inside its binary,
## so, here you can specify which plugins the application use/load in order to install them
## and resolve also there dependencies.
## With PLUGINS multi FLAGS :
## PLUGIN_PATH_NAME : The current plugin full file path we want to install
## FROM_REL_PATH : [optional: default only the file is kept] From which matching dir of the plugin path we want to install (keep the directories structure)
## PLUGIN_PATH_DEST : [optional: default relative to executable directory] Where (full path to the install directory) we will install the plugin file (or file path)
##
## DIRS : A list of directories to looking for dependencies
## TARGET_LIBRARIES : DEPRECATED (use TARGET flag instead) : The cmake content variables used for the target_link_libraries(<targetApp> ...)
## TARGET_PACKAGES : DEPRECATED (use TARGET flag instead) : The cmake package names used for the findPackage(...) for your targetApp
## ADVICE: This flag add entries in cache (like: <packageName>_DIR), it could be useful to fill these variable!
## COMPONENT : (default to runtime) Is the component name associated to the installation
## It is used when you want to install separatly some part of your projets (see install cmake doc)
## VERBOSE : For debug or to get more informations in the output console
##
## Usage:
## install_runtime(${CMAKE_INSTALL_PREFIX}/${EXECUTABLE_NAME}${CMAKE_EXECUTABLE_SUFFIX}
## VERBOSE
## TARGET ${PROJECT_NAME}
## PLAUSIBLES_POSTFIX _d
## PLUGINS
## PLUGIN_PATH_NAME ${PLUGIN_PATH_NAME}${CMAKE_SHARED_MODULE_SUFFIX} ## will be installed (default exec path if no PLUGINS_DEST) and then will be resolved
## FROM_REL_PATH plugins ## optional, used especially for keeping qt plugins tree structure
## PLUGIN_PATH_DEST ${CMAKE_INSTALL_PREFIX}/plugins ## (or relative path 'plugins' will be interpreted relative to installed executable)
## DIRS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}
## TARGET_LIBRARIES ${OPENGL_LIBRARIES} ## DEPRECATED (use TARGET flag instead)
## ${GLEW_LIBRARIES}
## ${GLUT_LIBRARIES}
## ${Boost_LIBRARIES}
## ${SuiteSparse_LIBRARIES}
## ${CGAL_LIBRARIES}
## TARGET_PACKAGES OPENGL ## DEPRECATED (use TARGET flag instead)
## GLEW
## GLUT
## CGAL
## Boost
## SuiteSparse
## )
##
## For plugins part, it use our internal parse_arguments_multi.cmake
##
function(install_runtime installedFilePathTargetAppToResolve)
set(optionsArgs "VERBOSE")
set(oneValueArgs "COMPONENT;INSTALL_FOLDER;CONFIG_TYPE")
set(multiValueArgs "DIRS;PLUGINS;TARGET_LIBRARIES;TARGET_PACKAGES;TARGET;PLAUSIBLES_POSTFIX")
cmake_parse_arguments(inst_run "${optionsArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
if(IS_ABSOLUTE ${installedFilePathTargetAppToResolve})
else()
set(installedFilePathTargetAppToResolve ${inst_run_INSTALL_FOLDER}/${installedFilePathTargetAppToResolve})
endif()
get_filename_component(EXEC_NAME ${installedFilePathTargetAppToResolve} NAME_WE)
get_filename_component(EXEC_PATH ${installedFilePathTargetAppToResolve} PATH)
if(NOT inst_run_COMPONENT)
set(inst_run_COMPONENT runtime)
endif()
## Try to append as more possible as possible paths to find dependencies (deprecated since we can use target_properties to get back paths)
set(libPaths )
foreach(libraryFileName ${inst_run_TARGET_LIBRARIES})
if(IS_DIRECTORY "${libraryFileName}")
list(APPEND libPaths "${libraryFileName}")
else()
get_filename_component(libpath "${libraryFileName}" PATH)
if(EXISTS "${libpath}")
list(APPEND libPaths "${libpath}")
endif()
endif()
endforeach()
## This macro is used internaly here to recursilvely get path of LINK_LIBRARIES of each non imported target
## Typically if you have 2 internal dependencies between cmake targets, we want cmake to be able to get back path where are these dependencies
macro(recurseDepList target)
get_target_property(linkLibs ${target} LINK_LIBRARIES)
foreach(lib ${linkLibs})
string(FIND ${lib} ">" strId) ## cmake is using generator-expression?
if(TARGET ${lib})
## Skipping interface libraries as they're system ones
get_target_property(type ${lib} TYPE)
get_target_property(imported ${lib} IMPORTED)
if(type STREQUAL "INTERFACE_LIBRARY")
get_target_property(imp_loc ${lib} INTERFACE_IMPORTED_LOCATION)
if(imp_loc)
get_filename_component(imp_loc ${imp_loc} PATH)
list(APPEND targetLibPath ${imp_loc})
endif()
get_target_property(loc ${lib} INTERFACE_LOCATION)
if(loc)
get_filename_component(loc ${loc} PATH)
list(APPEND targetLibPath ${loc})
endif()
## it's not a path but a single target name
## for build-target which are part of the current cmake configuration : nothing to do as cmake already know the output path
## for imported target, we need to look for theire imported location
elseif(imported)
get_target_property(imp_loc ${lib} IMPORTED_LOCATION)
if(imp_loc)
get_filename_component(imp_loc ${imp_loc} PATH)
list(APPEND targetLibPath ${imp_loc})
endif()
get_target_property(loc ${lib} LOCATION)
if(loc)
get_filename_component(loc ${loc} PATH)
list(APPEND targetLibPath ${loc})
endif()
else()
recurseDepList(${lib})
endif()
elseif(NOT ${strId} MATCHES -1) ## mean cmake use generator-expression (CMAKE VERSION > 3.0)
string(REGEX MATCH ">:[@A-Za-z_:/.0-9-]+" targetLibPath ${lib})
string(REGEX REPLACE ">:([@A-Za-z_:/.0-9-]+)" "\\1" targetLibPath ${targetLibPath})
get_filename_component(targetLibPath ${targetLibPath} PATH)
elseif(EXISTS ${lib})
set(targetLibPath ${lib})
get_filename_component(targetLibPath ${targetLibPath} PATH)
else()
#message(STATUS "[install_runtime] skip link library : ${lib} , of target ${target}")
endif()
if(targetLibPath)
list(APPEND targetLinkLibsPathList ${targetLibPath})
endif()
endforeach()
if(targetLinkLibsPathList)
list(REMOVE_DUPLICATES targetLinkLibsPathList)
endif()
endmacro()
if(inst_run_TARGET)
recurseDepList(${inst_run_TARGET})
if(targetLinkLibsPathList)
list(APPEND libPaths ${targetLinkLibsPathList})
endif()
endif()
if(libPaths)
list(REMOVE_DUPLICATES libPaths)
foreach(libPath ${libPaths})
get_filename_component(path ${libPath} PATH)
list(APPEND libPaths ${path})
endforeach()
endif()
## possible speciale dir(s) according to the build system and OS
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(BUILD_TYPES_FOR_DLL "x64")
if(WIN32)
list(APPEND BUILD_TYPES_FOR_DLL "Win64")
endif()
else()
set(BUILD_TYPES_FOR_DLL "x86")
if(WIN32)
list(APPEND BUILD_TYPES_FOR_DLL "Win32")
endif()
endif()
## Try to append as more as possible paths to find dependencies (here, mainly for *.dll)
foreach(dir ${inst_run_DIRS} ${libPaths})
if(EXISTS "${dir}/bin")
list(APPEND inst_run_DIRS "${dir}/bin")
elseif(EXISTS "${dir}")
list(APPEND inst_run_DIRS "${dir}")
endif()
endforeach()
list(REMOVE_DUPLICATES inst_run_DIRS)
foreach(dir ${inst_run_DIRS})
if(EXISTS "${dir}")
list(APPEND argDirs ${dir})
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${dir}/${BUILD_TYPE_FOR_DLL}")
list(APPEND argDirs "${dir}/${BUILD_TYPE_FOR_DLL}")
endif()
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) ## for windows multi-generator (MSVC)
if(EXISTS "${dir}/${BUILD_TYPE_FOR_DLL}/${OUTPUTCONFIG}")
list(APPEND argDirs "${dir}/${BUILD_TYPE_FOR_DLL}/${OUTPUTCONFIG}")
endif()
endforeach()
if(CMAKE_BUILD_TYPE) ## for single generator (makefiles)
if(EXISTS "${dir}/${BUILD_TYPE_FOR_DLL}/${CMAKE_BUILD_TYPE}")
list(APPEND argDirs "${dir}/${BUILD_TYPE_FOR_DLL}/${CMAKE_BUILD_TYPE}")
endif()
endif()
endforeach()
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) ## for windows multi-generator (MSVC)
if(EXISTS "${dir}/${OUTPUTCONFIG}")
list(APPEND argDirs "${dir}/${OUTPUTCONFIG}")
endif()
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${dir}/${OUTPUTCONFIG}/${BUILD_TYPE_FOR_DLL}")
list(APPEND argDirs "${dir}/${OUTPUTCONFIG}/${BUILD_TYPE_FOR_DLL}")
endif()
endforeach()
endforeach()
if(CMAKE_BUILD_TYPE) ## for single generator (makefiles)
if(EXISTS "${dir}/${CMAKE_BUILD_TYPE}")
list(APPEND argDirs "${dir}/${CMAKE_BUILD_TYPE}")
endif()
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${dir}/${CMAKE_BUILD_TYPE}/${BUILD_TYPE_FOR_DLL}")
list(APPEND argDirs "${dir}/${CMAKE_BUILD_TYPE}/${BUILD_TYPE_FOR_DLL}")
endif()
endforeach()
endif()
endif()
endforeach()
if(argDirs)
list(REMOVE_DUPLICATES argDirs)
endif()
## Try to append as more possible paths to find dependencies (here, mainly for *.dll)
foreach(packageName ${inst_run_TARGET_PACKAGES})
if(EXISTS "${${packageName}_DIR}")
list(APPEND packageDirs ${${packageName}_DIR})
list(APPEND packageDirs ${${packageName}_DIR}/bin)
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}")
endif()
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) ## for windows multi-generator (MSVC)
if(EXISTS "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}/${OUTPUTCONFIG}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}/${OUTPUTCONFIG}")
endif()
endforeach()
if(CMAKE_BUILD_TYPE) ## for single generator (makefiles)
if(EXISTS "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}/${CMAKE_BUILD_TYPE}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${BUILD_TYPE_FOR_DLL}/${CMAKE_BUILD_TYPE}")
endif()
endif()
endforeach()
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) ## for windows multi-generator (MSVC)
if(EXISTS "${${packageName}_DIR}/bin/${OUTPUTCONFIG}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${OUTPUTCONFIG}")
endif()
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${${packageName}_DIR}/bin/${OUTPUTCONFIG}/${BUILD_TYPE_FOR_DLL}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${OUTPUTCONFIG}/${BUILD_TYPE_FOR_DLL}")
endif()
endforeach()
endforeach()
if(CMAKE_BUILD_TYPE) ## for single generator (makefiles)
if(EXISTS "${${packageName}_DIR}/bin/${CMAKE_BUILD_TYPE}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${CMAKE_BUILD_TYPE}")
endif()
foreach(BUILD_TYPE_FOR_DLL ${BUILD_TYPES_FOR_DLL})
if(EXISTS "${${packageName}_DIR}/bin/${CMAKE_BUILD_TYPE}/${BUILD_TYPE_FOR_DLL}")
list(APPEND packageDirs "${${packageName}_DIR}/bin/${CMAKE_BUILD_TYPE}/${BUILD_TYPE_FOR_DLL}")
endif()
endforeach()
endif()
else()
set(${packageName}_DIR "$ENV{${packageName}_DIR}" CACHE PATH "${packageName}_DIR root directory for looking for dirs containning *.dll")
endif()
endforeach()
if(packageDirs)
list(REMOVE_DUPLICATES packageDirs)
endif()
set(dirsToLookFor "${EXEC_PATH}")
if(packageDirs)
list(APPEND dirsToLookFor ${packageDirs})
endif()
if(argDirs)
list(APPEND dirsToLookFor ${argDirs})
endif()
get_property(used_LINK_DIRECTORIES DIRECTORY PROPERTY LINK_DIRECTORIES)
if (used_LINK_DIRECTORIES)
list(APPEND dirsToLookFor ${used_LINK_DIRECTORIES})
list(REMOVE_DUPLICATES dirsToLookFor)
endif()
## handle plugins
set(pluginsList "")
include(parse_arguments_multi) ## this function will process recursively items of the sub-list [default print messages]
function(parse_arguments_multi_function results)
cmake_parse_arguments(pamf "VERBOSE" "PLUGIN_PATH_DEST;FROM_REL_PATH;EXEC_PATH;COMPONENT" "" ${ARGN}) ## EXEC_PATH and COMPONENT are for exclusive internal use
list(REMOVE_DUPLICATES pamf_UNPARSED_ARGUMENTS)
foreach(PLUGIN_PATH_NAME ${pamf_UNPARSED_ARGUMENTS})
if(EXISTS ${PLUGIN_PATH_NAME})
if(IS_DIRECTORY ${PLUGIN_PATH_NAME})
if(pamf_VERBOSE)
message(WARNING "${PLUGIN_PATH_NAME} IS_DIRECTORY, cannot installed a directory, please give a path filename")
endif()
else()
if(NOT pamf_PLUGIN_PATH_DEST)
set(PLUGIN_PATH_DEST ${pamf_EXEC_PATH}) ## the default dest value
else()
set(PLUGIN_PATH_DEST ${pamf_PLUGIN_PATH_DEST})
endif()
if(pamf_FROM_REL_PATH)
file(TO_CMAKE_PATH ${PLUGIN_PATH_NAME} PLUGIN_PATH_NAME)
get_filename_component(PLUGIN_PATH ${PLUGIN_PATH_NAME} PATH)
unset(PLUGIN_PATH_LIST)
unset(PLUGIN_PATH_LIST_COUNT)
unset(PLUGIN_REL_PATH_LIST)
unset(PLUGIN_REL_PATH)
string(REPLACE "/" ";" PLUGIN_PATH_LIST ${PLUGIN_PATH}) ## create a list of dir
list(FIND PLUGIN_PATH_LIST ${pamf_FROM_REL_PATH} id)
list(LENGTH PLUGIN_PATH_LIST PLUGIN_PATH_LIST_COUNT)
if(${id} GREATER 0)
math(EXPR id "${id}+1") ## matches relative path not include
math(EXPR PLUGIN_PATH_LIST_COUNT "${PLUGIN_PATH_LIST_COUNT}-1") ## the end of the list
foreach(i RANGE ${id} ${PLUGIN_PATH_LIST_COUNT})
list(GET PLUGIN_PATH_LIST ${i} out)
list(APPEND PLUGIN_REL_PATH_LIST ${out})
endforeach()
foreach(dir ${PLUGIN_REL_PATH_LIST})
set(PLUGIN_REL_PATH "${PLUGIN_REL_PATH}/${dir}")
endforeach()
endif()
set(PLUGIN_PATH_DEST ${PLUGIN_PATH_DEST}${PLUGIN_REL_PATH})
endif()
install(FILES ${PLUGIN_PATH_NAME} CONFIGURATIONS ${inst_run_CONFIG_TYPE} DESTINATION ${PLUGIN_PATH_DEST} COMPONENT ${pamf_COMPONENT})
get_filename_component(pluginName ${PLUGIN_PATH_NAME} NAME)
if(IS_ABSOLUTE ${PLUGIN_PATH_DEST})
else()
set(PLUGIN_PATH_DEST ${inst_run_INSTALL_FOLDER}/${PLUGIN_PATH_DEST})
endif()
list(APPEND pluginsList ${PLUGIN_PATH_DEST}/${pluginName})
endif()
else()
message(WARNING "You need to provide a valid PLUGIN_PATH_NAME")
set(pluginsList )
endif()
endforeach()
set(${results} ${pluginsList} PARENT_SCOPE)
endfunction()
if(inst_run_VERBOSE)
list(APPEND extra_flags_to_add VERBOSE)
endif()
list(APPEND extra_flags_to_add EXEC_PATH ${EXEC_PATH} COMPONENT ${inst_run_COMPONENT}) ## for internal use inside overloaded function
list(LENGTH inst_run_PLUGINS inst_run_PLUGINS_count)
if(${inst_run_PLUGINS_count} GREATER 0)
parse_arguments_multi(PLUGIN_PATH_NAME inst_run_PLUGINS ${inst_run_PLUGINS} ## see internal overload parse_arguments_multi_function for processing each sub-list
NEED_RESULTS ${inst_run_PLUGINS_count} ## this is used to check when we are in the first loop (in order to reset parse_arguments_multi_results)
EXTRAS_FLAGS ${extra_flags_to_add} ## this is used to allow catching additional internal flags of our overloaded function
)
endif()
#message(parse_arguments_multi_results = ${parse_arguments_multi_results})
list(APPEND pluginsList ${parse_arguments_multi_results})
## Install rules for required system runtimes such as MSVCRxx.dll
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP ON)
include(InstallRequiredSystemLibraries)
if(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)
install(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
CONFIGURATIONS ${inst_run_CONFIG_TYPE}
DESTINATION ${EXEC_PATH}
COMPONENT ${inst_run_COMPONENT}
)
endif()
## print what we are doing to do
if(inst_run_VERBOSE)
message(STATUS "[install_runtime] On install target call, cmake will try to resolve dependencies for given app:\n ${installedFilePathTargetAppToResolve} (with plausible postfix: ${inst_run_PLAUSIBLES_POSTFIX})")
if(pluginsList)
message(STATUS " and also for plugins :")
foreach(plugin ${pluginsList})
message(STATUS " ${plugin}")
endforeach()
endif()
message(STATUS " Looking for dependencies into:")
foreach(dir ${dirsToLookFor})
message(STATUS " ${dir}")
endforeach()
endif()
## Install rules for required dependencies libs/plugins for the target app
## will resolve all installed target files with config modes postfixes
string(TOUPPER ${inst_run_CONFIG_TYPE} inst_run_CONFIG_TYPE_UC)
get_target_property(postfix ${inst_run_TARGET} "${inst_run_CONFIG_TYPE_UC}_POSTFIX")
install(CODE "set(target \"${inst_run_TARGET}\")" COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE})
install(CODE "set(inst_run_CONFIG_TYPE \"${inst_run_CONFIG_TYPE}\")" COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE})
install(CODE "set(inst_run_INSTALL_FOLDER \"${inst_run_INSTALL_FOLDER}\")" COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE})
install(CODE "set(app \"${EXEC_PATH}/${EXEC_NAME}${postfix}${CMAKE_EXECUTABLE_SUFFIX}\")" COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE})
install(CODE "set(dirsToLookFor \"${dirsToLookFor}\")" COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE})
install(CODE
[[
if("${CMAKE_INSTALL_CONFIG_NAME}" STREQUAL "${inst_run_CONFIG_TYPE}")
message(STATUS "Installing ${target} dependencies...")
file(GET_RUNTIME_DEPENDENCIES
EXECUTABLES ${app}
RESOLVED_DEPENDENCIES_VAR _r_deps
UNRESOLVED_DEPENDENCIES_VAR _u_deps
CONFLICTING_DEPENDENCIES_PREFIX _c_deps
DIRECTORIES ${dirsToLookFor}
PRE_EXCLUDE_REGEXES "api-ms-*"
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll" ".*SysWOW64/.*\\.dll"
)
if(_u_deps)
message(WARNING "There were unresolved dependencies for executable ${EXEC_FILE}: \"${_u_deps}\"!")
endif()
if(_c_deps_FILENAMES)
message(WARNING "There were conflicting dependencies for executable ${EXEC_FILE}: \"${_c_deps_FILENAMES}\"!")
endif()
foreach(_file ${_r_deps})
file(INSTALL
DESTINATION "${inst_run_INSTALL_FOLDER}/bin"
TYPE SHARED_LIBRARY
FOLLOW_SYMLINK_CHAIN
FILES "${_file}"
)
endforeach()
endif()
]]
COMPONENT ${inst_run_COMPONENT} CONFIGURATIONS ${CONFIG_TYPE}
)
endfunction()
## High level macro to install resources in the correct folder
##
## EXECUTABLE: [opt] option to copy files as programs
## RELATIVE : [opt] copy files relatively to current folder
## TYPE : [opt] type and folder where to store the files
## FOLDER : [opt] subfolder to use
## FILES : [opt] contains a list of resources files to copy to install folder
macro(ibr_install_rsc target)
cmake_parse_arguments(install_rsc_${target} "EXECUTABLE;RELATIVE" "TYPE;FOLDER" "FILES" ${ARGN})
set(rsc_target "${target}_${install_rsc_${target}_TYPE}")
if(install_rsc_${target}_FOLDER)
set(rsc_folder "${install_rsc_${target}_TYPE}/${install_rsc_${target}_FOLDER}")
else()
set(rsc_folder "${install_rsc_${target}_TYPE}")
endif()
add_custom_target(${rsc_target}
COMMENT "run the ${install_rsc_${target}_TYPE} installation only for ${target} (component ${rsc_target})"
VERBATIM)
foreach(scriptFile ${install_rsc_${target}_FILES})
if(install_rsc_${target}_RELATIVE)
file(RELATIVE_PATH relativeFilename ${CMAKE_CURRENT_SOURCE_DIR} ${scriptFile})
else()
get_filename_component(relativeFilename ${scriptFile} NAME)
endif()
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
add_custom_command(TARGET ${rsc_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different ${scriptFile} ${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}/${rsc_folder}/${relativeFilename})
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
add_custom_command(TARGET ${rsc_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different ${scriptFile} ${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}/${rsc_folder}/${relativeFilename})
endforeach()
endforeach()
get_target_property(INSTALL_RSC_BUILD_FOLDER ${target} FOLDER)
set_target_properties(${rsc_target} PROPERTIES FOLDER ${INSTALL_RSC_BUILD_FOLDER})
add_dependencies(${target} ${rsc_target})
add_dependencies(PREBUILD ${rsc_target})
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
resourceFile(ADD ${rsc_folder} CONFIG_TYPE ${CMAKE_BUILD_TYPE} FILE_PATH "${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}/ibr_resources.ini")
if(install_rsc_${target}_EXECUTABLE)
install(
PROGRAMS ${install_rsc_${target}_FILES}
CONFIGURATIONS ${CMAKE_BUILD_TYPE}
DESTINATION "${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}/${rsc_folder}"
)
else()
install(
FILES ${install_rsc_${target}_FILES}
CONFIGURATIONS ${CMAKE_BUILD_TYPE}
DESTINATION "${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}/${rsc_folder}"
)
endif()
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
resourceFile(ADD ${rsc_folder} CONFIG_TYPE ${CONFIG_TYPES} FILE_PATH "${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}/ibr_resources.ini")
if(install_rsc_${target}_EXECUTABLE)
install(
PROGRAMS ${install_rsc_${target}_FILES}
CONFIGURATIONS ${CONFIG_TYPES}
DESTINATION "${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}/${rsc_folder}"
)
else()
install(
FILES ${install_rsc_${target}_FILES}
CONFIGURATIONS ${CONFIG_TYPES}
DESTINATION "${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}/${rsc_folder}"
)
endif()
endforeach()
endmacro()
## High level macro to install in an homogen way all our ibr targets (it use some functions inside this file)
##
## RSC_FILE_ADD : [opt] is used to auto write/append relative paths of target resources into a common file
## INSTALL_PDB : [opt] is used to auto install PDB file (when using MSVC according to the target type)
## STANDALONE : [opt] bool ON/OFF var to call install_runtime or not (for bundle resolution)
## DIRS : [opt] used if STANDALONE set to ON, see install_runtime doc
## PLUGINS: [opt] used if STANDALONE set to ON, see install_runtime doc
## MSVC_CMD : [opt] used to specify an absolute filePathName application to launch with the MSVC IDE Debugger associated to this target (project file)
## MSVC_ARGS : [opt] load the MSVC debugger with correct settings (app path, args, working dir)
##
macro(ibr_install_target target)
cmake_parse_arguments(ibrInst${target} "VERBOSE;INSTALL_PDB" "COMPONENT;MSVC_ARGS;STANDALONE;RSC_FOLDER" "SHADERS;RESOURCES;SCRIPTS;DIRS;PLUGINS" ${ARGN})
if(ibrInst${target}_RSC_FOLDER)
set(rsc_folder "${ibrInst${target}_RSC_FOLDER}")
else()
set(rsc_folder "${target}")
endif()
if(ibrInst${target}_SHADERS)
ibr_install_rsc(${target} EXECUTABLE TYPE "shaders" FOLDER ${rsc_folder} FILES "${ibrInst${target}_SHADERS}")
endif()
if(ibrInst${target}_RESOURCES)
ibr_install_rsc(${target} TYPE "resources" FOLDER ${rsc_folder} FILES "${ibrInst${target}_RESOURCES}")
endif()
if(ibrInst${target}_SCRIPTS)
ibr_install_rsc(${target} EXECUTABLE TYPE "scripts" FOLDER ${rsc_folder} FILES "${ibrInst${target}_SCRIPTS}")
endif()
if(ibrInst${target}_COMPONENT)
set(installCompArg COMPONENT ${ibrInst${target}_COMPONENT})
## Create a custom install target based on COMPONENT
installTargetProject(${target} ${ibrInst${target}_COMPONENT})
endif()
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
string(TOUPPER ${CMAKE_BUILD_TYPE} CONFIG_TYPES_UC)
set_target_properties(${target} PROPERTIES ${CONFIG_TYPES_UC}_POSTFIX "${CMAKE_${CONFIG_TYPES_UC}_POSTFIX}")
get_target_property(CURRENT_TARGET_BUILD_TYPE_POSTFIX ${target} ${CONFIG_TYPES_UC}_POSTFIX)
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
set_target_properties(${target} PROPERTIES ${CONFIG_TYPES_UC}_POSTFIX "${CMAKE_${CONFIG_TYPES_UC}_POSTFIX}")
get_target_property(CURRENT_TARGET_BUILD_TYPE_POSTFIX ${target} ${CONFIG_TYPES_UC}_POSTFIX)
endforeach()
## Specify default installation rules
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
string(TOUPPER ${CMAKE_BUILD_TYPE} CONFIG_TYPES_UC)
install(TARGETS ${target}
CONFIGURATIONS ${CMAKE_BUILD_TYPE}
LIBRARY DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}} ${installCompArg}
ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}} ${installCompArg}
RUNTIME DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}} ${installCompArg}
)
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
install(TARGETS ${target}
CONFIGURATIONS ${CONFIG_TYPES}
LIBRARY DESTINATION ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}} ${installCompArg}
ARCHIVE DESTINATION ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}} ${installCompArg}
RUNTIME DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}} ${installCompArg}
)
endforeach()
if(ibrInst${target}_INSTALL_PDB)
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
installPDB(${target} ${CMAKE_BUILD_TYPE}
LIBRARY_DEST ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}}
ARCHIVE_DEST ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}}
RUNTIME_DEST ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CMAKE_BUILD_TYPE}}
)
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
installPDB(${target} ${CONFIG_TYPES}
LIBRARY_DEST ${CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}}
ARCHIVE_DEST ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}}
RUNTIME_DEST ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}}
)
endforeach()
endif()
## install dynamic necessary dependencies
if(ibrInst${target}_STANDALONE)
get_target_property(type ${target} TYPE)
if(${type} MATCHES "EXECUTABLE")
if(ibrInst${target}_VERBOSE)
set(VERBOSE VERBOSE)
else()
set(VERBOSE )
endif()
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
install_runtime(bin/${target}${CMAKE_EXECUTABLE_SUFFIX} ## default relative to CMAKE_INSTALL_PREFIX
INSTALL_FOLDER "${CMAKE_INSTALL_PREFIX_${CMAKE_BUILD_TYPE}}"
CONFIG_TYPE ${CMAKE_BUILD_TYPE}
${VERBOSE}
TARGET ${target}
${installCompArg}
PLUGINS ## will be installed
${ibrInst${target}_PLUGINS}
DIRS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}}
${ibrInst${target}_DIRS}
)
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
install_runtime(bin/${target}${CMAKE_EXECUTABLE_SUFFIX} ## default relative to CMAKE_INSTALL_PREFIX
INSTALL_FOLDER "${CMAKE_INSTALL_PREFIX_${CONFIG_TYPES_UC}}"
CONFIG_TYPE ${CONFIG_TYPES}
${VERBOSE}
TARGET ${target}
${installCompArg}
PLUGINS ## will be installed
${ibrInst${target}_PLUGINS}
DIRS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CONFIG_TYPES_UC}}
${ibrInst${target}_DIRS}
)
endforeach()
else()
message(WARNING "STANDALONE option is only compatible with EXECUTABLES target type. Skip the STANDALONE installation process.")
endif()
endif()
## Provide a way to directly load the MSVC debugger with correct settings
if(MSVC)
if(ibrInst${target}_MSVC_CMD) ## command absolute filePathName is optional as the default is to use the installed target file application
set(msvcCmdArg COMMAND ${ibrInst${target}_MSVC_CMD}) ## flag following by the value (both to pass to the MSVCsetUserCommand function)
endif()
if(ibrInst${target}_MSVC_ARGS) ## args (between quotes) are optional
set(msvcArgsArg ARGS ${ibrInst${target}_MSVC_ARGS}) ## flag following by the value (both to pass to the MSVCsetUserCommand function)
endif()
get_target_property(type ${target} TYPE)
if( (ibrInst${target}_MSVC_CMD OR ibrInst${target}_MSVC_ARGS) OR (${type} MATCHES "EXECUTABLE") )
include(MSVCsetUserCommand)
if(DEFINED CMAKE_BUILD_TYPE) ## for make/nmake based
MSVCsetUserCommand( ${target}
PATH ${CMAKE_OUTPUT_BIN_${CMAKE_BUILD_TYPE}} ##FILE option not necessary since it deduced from targetName
ARGS "${SIBR_PROGRAMARGS}"
${msvcCmdArg}
#${msvcArgsArg}
WORKING_DIR ${CMAKE_OUTPUT_BIN_${CMAKE_BUILD_TYPE}}
)
endif()
foreach(CONFIG_TYPES ${CMAKE_CONFIGURATION_TYPES}) ## for multi config types (MSVC based)
string(TOUPPER ${CONFIG_TYPES} CONFIG_TYPES_UC)
MSVCsetUserCommand( ${target}
PATH ${CMAKE_OUTPUT_BIN_${CONFIG_TYPES_UC}} ##FILE option not necessary since it deduced from targetName
ARGS "${SIBR_PROGRAMARGS}"
${msvcCmdArg}
#${msvcArgsArg}
WORKING_DIR ${CMAKE_OUTPUT_BIN_${CONFIG_TYPES_UC}}
)
endforeach()
elseif(NOT ${type} MATCHES "EXECUTABLE")
#message("Cannot set MSVCsetUserCommand with target ${target} without COMMAND parameter as it is not an executable (skip it)")
endif()
endif()
endmacro()

View File

@ -0,0 +1,304 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
if(NOT WIN32 OR __parse_arguments_multi_cmake_INCLUDED__)
return()
else()
set(__parse_arguments_multi_cmake_INCLUDED__ ON)
endif()
## This macro allow to process repeating multi value args from a given function which use cmake_parse_arguments module.
##
## cmake_parse_arguments multi args standard behavior:
## function(foo)
## cmake_parse_arguments(arg "" "" "MULTI" ${ARGN})
## foreach(item IN LISTS arg_MULTI)
## message(STATUS "${item}")
## endforeach()
## endfunction()
## foo(MULTI x y MULTI z w)
## The above code outputs 'z' and 'w'. It originally expected it to output all of 'x' 'y' 'z' 'w'.
##
## Using this macro inside a function which want to handle repeating multi args values
## will recursively iterate onto the multi tags list to process each sub list.
## It take as 1st argument the subTag flag to separate sub list from the main multi list.
## It take as 2nd argument the nameList of the main multi list (the multiValuesArgs from cmake_parse_arguments: here it is MULTI in the example)
## and that's why it is important that it should be a macro and not a function (to get access to external variable).
## Then you give the content of this list allowing to be processed by the macro.
##
## parse_arguments_multi macro call a parse_arguments_multi_function which do actually the process from the given sub-list.
## By default this function only print infos about what variables you are trying to pass/process (only verbose messages),
## but, by overloading this cmake function, you will be able to externalize the process of your multi argument list.
##
## Usage (into a function) :
## parse_arguments_multi(<multiArgsSubTag> <multiArgsList> <multiArgsListContent>
## [NEED_RESULTS <multiArgsListSize>] [EXTRAS_FLAGS <...> <...> ...]
## )
##
## Simple usage example [user point of view]:
## foo(MULTI
## SUB_MULTI x y
## SUB_MULTI z w
## )
##
## Simple usage example [inside a function]:
## function(foo)
## cmake_parse_arguments(arg "" "" "MULTI" ${ARGN})
## include(parse_arguments_multi)
## function(parse_arguments_multi_function )
## #message("I'm an overloaded cmake function used by parse_arguments_multi")
## #message("I'm processing first part of my sub list: ${ARGN}")
## message("ARGV0=${ARGV0}")
## message("ARGV1=${ARGV1}")
## endfunction()
## parse_arguments_multi(SUB_MULTI arg_MULTI ${arg_MULTI}) ## this function will process recusively items of the sub-list [default print messages]
## endfunction()
##
## Will print:
## ARGV0=z
## ARGV1=w
## ARGV0=x
## ARGV1=y
##
## WARNING : DO NEVER ADD EXTRA THINGS TO parse_arguments_multi MACRO :
## parse_arguments_multi(SUB_MULTI arg_MULTI ${arg_MULTI} EXTRAS foo bar SOMTHING) => will failed !!
## use EXTRAS_FLAGS instead !!
##
## Advanced usage example [user point of view]:
## bar(C:/prout/test.exe VERBOSE
## PLUGINS
## PLUGIN_PATH_NAME x PLUGIN_PATH_DEST w
## PLUGIN_PATH_NAME a b PLUGIN_PATH_DEST y
## PLUGIN_PATH_NAME c
## )
##
## Advanced usage example [inside a function]:
## function(bar execFilePathName)
## cmake_parse_arguments(arg "VERBOSE" "" "PLUGINS" ${ARGN})
##
## include(parse_arguments_multi)
## function(parse_arguments_multi_function results)
## cmake_parse_arguments(pamf "VERBOSE" "PLUGIN_PATH_DEST;EXEC_PATH" "" ${ARGN}) ## EXEC_PATH is for internal use
## message("")
## message("I'm an overloaded cmake function used by parse_arguments_multi from install_runtime function")
## message("I'm processing first part of my sub list: ${ARGN}")
## message("PLUGIN_PATH_NAME = ${pamf_UNPARSED_ARGUMENTS}")
## message(pamf_VERBOSE = ${pamf_VERBOSE})
## message("pamf_PLUGIN_PATH_DEST = ${pamf_PLUGIN_PATH_DEST}")
## message(pamf_EXEC_PATH = ${pamf_EXEC_PATH})
## if(NOT ${pamf_PLUGIN_PATH_DEST})
## set(pamf_PLUGIN_PATH_DEST ${pamf_EXEC_PATH})
## endif()
## foreach(plugin ${pamf_UNPARSED_ARGUMENTS})
## get_filename_component(pluginName ${plugin} NAME)
## list(APPEND pluginsList ${pamf_PLUGIN_PATH_DEST}/${pluginName})
## endforeach()
## set(${results} ${pluginsList} PARENT_SCOPE)
## endfunction()
##
## if(arg_VERBOSE)
## list(APPEND extra_flags_to_add VERBOSE) ## here we transmit the VERNOSE flag
## endif()
## get_filename_component(EXEC_PATH ${execFilePathName} PATH) ## will be the default value if PLUGIN_PATH_DEST option is not provided
## list(APPEND extra_flags_to_add EXEC_PATH ${EXEC_PATH})
## list(LENGTH arg_PLUGINS arg_PLUGINS_count)
## parse_arguments_multi(PLUGIN_PATH_NAME arg_PLUGINS ${arg_PLUGINS}
## NEED_RESULTS ${arg_PLUGINS_count} ## this is used to check when we are in the first loop (in order to reset parse_arguments_multi_results)
## EXTRAS_FLAGS ${extra_flags_to_add} ## this is used to allow catching VERBOSE and PLUGIN_PATH_DEST flags of our overloaded function
## )
## endfunction()
## message(parse_arguments_multi_results = ${parse_arguments_multi_results}) ## list of the whole pluginsList
## #Will print w/x;a/y;b/y;C:/prout/c
##
## NOTE that here, since our overloaded function need to provide a result list, we use the other parse_arguments_multi_function signature (the which one with a results arg)
##
function(parse_arguments_multi_function_default) ## used in case of you want to reset the default behavior of this function process
message("[default function] parse_arguments_multi_function(ARGC=${ARGC} ARGV=${ARGV} ARGN=${ARGN})")
message("This function is used by parse_arguments_multi and have to be overloaded to process sub list of multi values args")
endfunction()
function(parse_arguments_multi_function ) ## => the function to overload
parse_arguments_multi_function_default(${ARGN})
endfunction()
## first default signature above
##------------------------------
## second results signature behind
function(parse_arguments_multi_function_default result) ## used in case of you want to reset the default behavior of this function process
message("[default function] parse_arguments_multi_function(ARGC=${ARGC} ARGV=${ARGV} ARGN=${ARGN})")
message("This function is used by parse_arguments_multi and have to be overloaded to process sub list of muluti values args")
endfunction()
function(parse_arguments_multi_function result) ## => the function to overload
parse_arguments_multi_function_default(result ${ARGN})
endfunction()
## => the macro to use inside your function which use cmake_parse_arguments
# NOTE: entry point of parse_arguments_multi, which is called from win3rdPart)
macro(parse_arguments_multi multiArgsSubTag multiArgsList #<${multiArgsList}> the content of the list
)
# message (STATUS "")
# message(STATUS "calling parse_arguemnts_multi defined in parse_arguments_multi.cmake:141")
# message(STATUS "multiArgsSubTag = ${multiArgsSubTag}") # CHECK_CACHED_VAR
# message(STATUS "multiArgsList = ${multiArgsList}") # it contains the name of the variable which is holding the list i.e w3p_MULTI_SET
# message(STATUS "value of ${multiArgsList} = ${${multiArgsList}}") # a semicolon separated list of values passed to SET or MULTISET keyword in win3rdParty
# message(STATUS "actual values ARGN = ${ARGN}") # the same as ${${multiArgsList}}
## INFO
## starting from CMake 3.5 cmake_parse_arguments is not a module anymore and now is a native CMake command.
## the behaviour is different though
## In CMake 3.4, if you pass multiple times a multi_value_keyword, CMake returns the values of the LAST match
## In CMake 3.5 and above, CMake returns the whole list of values that were following that multi_value_keyword
## example:
## cmake_parse_arguments(
## <prefix>
## "" # options
## "" # one value keywords
## "MY_MULTI_VALUE_TAG"
## MY_MULTI_VALUE_TAG value1 value2
## MY_MULTI_VALUE_TAG value3 value4
## MY_MULTI_VALUE_TAG value5 value6
## )
## result in CMake 3.4
## <prefix>_MY_MULTI_VALUE_TAG = "value5;value6"
##
## result in CMake 3.8
## <prefix>_MY_MULTI_VALUE_TAG = "value5;value6"
#include(CMakeParseArguments) #module CMakeParseArguments is obsolete since cmake 3.5
# cmake_parse_arguments (<prefix> <options> <one_value_keywords> <multi_value_keywords> args)
# <options> : options (flags) pass to the macro
# <one_value_keywords> : options that neeed a value
# <multi_value_keywords> : options that neeed more than one value
cmake_parse_arguments(_pam "" "NEED_RESULTS" "${multiArgsSubTag};EXTRAS_FLAGS" ${ARGN})
## multiArgsList is the name of the list used by the multiValuesOption flag from the cmake_parse_arguments of the user function
## that's why we absolutly need to use MACRO here (and also for passing parse_arguments_multi_results when NEED_RESULTS flag is set)
## for debugging
#message("")
#message("[parse_arguments_multi] => ARGN = ${ARGN}")
#message("_pam_NEED_RESULTS=${_pam_NEED_RESULTS}")
#message("_pam_EXTRAS_FLAGS=${_pam_EXTRAS_FLAGS}")
# foreach(var ${_pam_${multiArgsSubTag}})
# message("arg=${var}")
# endforeach()
if (${CMAKE_VERSION} VERSION_GREATER "3.5")
# lets make ${_pam_${multiArgsSubTag}} behave as it is in version 3.4
# that means, cmake_parse_arguments should have only the last values of a multi set for a given keyword
# message("")
# message("values in multiArgsList")
# foreach(val ${${multiArgsList}})
# message(STATUS ${val})
# endforeach()
# message("end values in multiArgsList")
set(lastIndexFound OFF)
list(LENGTH ${multiArgsList} argnLength)
# message(${argnLength})
math(EXPR argnLength "${argnLength}-1") # make last index a valid one
set(recordIndex 0)
set(records "") # clear records list
set(record0 "") # clear first record list
foreach(iter RANGE ${argnLength})
list(GET ${multiArgsList} ${iter} value)
# message(STATUS "index=${iter} value=${value}")
if (${value} STREQUAL ${multiArgsSubTag})
if (lastIndexFound)
list(APPEND records ${recordIndex}) # records store the list NAMES
math(EXPR recordIndex "${recordIndex}+1")
set(record${recordIndex} "") # clear record list
else ()
set(lastIndexFound ON)
endif()
set(lastIndex ${iter})
else ()
if (lastIndexFound)
# message(${value})
list(APPEND record${recordIndex} ${value})
endif()
endif()
endforeach()
# save the last list of values
if (lastIndexFound)
list(APPEND records ${recordIndex}) # records store the list NAMES
endif()
# set multiArgsList to make it behave like CMake 3.4
# message("")
# message("using my records")
foreach(recordName ${records})
# message(${recordName})
# foreach(value ${record${recordName}})
# message(${value})
# endforeach()
# message("")
set(_pam_${multiArgsSubTag} ${record${recordName}})
endforeach()
# message(${_pam_${multiArgsSubTag}})
# message("")
# message("using argn")
# foreach(value ${ARGN})
# message(${value})
# endforeach()
endif() # end if cmake > 3.5
# message("values with pam ${_pam_${multiArgsSubTag}}")
## check and init
list(LENGTH ${multiArgsList} globalListCount) # GLUT_TRACE: globalListCound=16 in CMake3.4 and CMake3.8
# message(STATUS "nr items in multiArgsList: ${globalListCount}")
math(EXPR globalListCount "${globalListCount}-1") ## because it will contain [multiArgsSubTag + ${multiArgsList}]
if(_pam_NEED_RESULTS)
if(${globalListCount} EQUAL ${_pam_NEED_RESULTS})
## first time we enter into this macro (because we call it recursively)
unset(parse_arguments_multi_results)
endif()
endif()
## process the part of the multi agrs list
## ${ARGN} shouldn't be passed to the function in order to avoid missmatch size list ${multiArgsList} and _pam_${multiArgsSubTag}
## if you want to pass extra internal flags from your function to this callback, use EXTRAS_FLAGS
if(_pam_NEED_RESULTS)
parse_arguments_multi_function(parse_arguments_multi_function_result ${_pam_${multiArgsSubTag}} ${_pam_EXTRAS_FLAGS})
list(APPEND parse_arguments_multi_results ${parse_arguments_multi_function_result})
else()
# message(STATUS "about to call parse_arguments_multi_function in parse_arguments_multi.cmake:177 ${_pam_${multiArgsSubTag}} and extra flags ${_pam_EXTRAS_FLAGS}")
parse_arguments_multi_function(${_pam_${multiArgsSubTag}} ${_pam_EXTRAS_FLAGS})
endif()
## remove just processed items from the main list to process (multiArgsList)
list(REVERSE ${multiArgsList})
list(LENGTH _pam_${multiArgsSubTag} subTagListCount)
unset(ids)
foreach(id RANGE ${subTagListCount})
list(APPEND ids ${id})
endforeach()
list(REMOVE_AT ${multiArgsList} ${ids})
list(REVERSE ${multiArgsList})
## test if remain sub multi list to process (recursive call) or finish the process
list(LENGTH ${multiArgsList} mainTagListCount)
if(${mainTagListCount} GREATER 1)
## do not pass ${ARGN} just because it will re pass the initial 2 inputs args and we wont as they was consumed (in order to avoir conflicts)
# message(STATUS "about to call a parse_arguments_multi but without knowing where the definition is going to be taken from")
parse_arguments_multi(${multiArgsSubTag} ${multiArgsList} ${${multiArgsList}}
NEED_RESULTS ${_pam_NEED_RESULTS} EXTRAS_FLAGS ${_pam_EXTRAS_FLAGS}
)
endif()
endmacro()

View File

@ -0,0 +1,169 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
# NOTE
# This feature is used to easily download, store and link external dependencies. This
# requires to prepare pre-compiled libraries (to download). For now, packages have
# only be prepare for Windows 64-bit with Visual Studio 2012. (You should re-build
# everything if you want to use another version of Visual Studio/ another compiler).
# NOTE ABOUT UNIX SYSTEMS
# There is no need for "searching mechanism". This function is discard and your
# libraries should be installed is the standard folders that are:
#
# /usr/include/
# /usr/lib/
# /usr/lib64/
# for packages downloaded using apt-get/yum
#
# /usr/local/include/
# /usr/local/lib/
# /usr/local/lib64/
# for packages manually installed ("make install")
#
# if you encounter problems when linking (e.g. lib not found even if it is installed),
# please check these folders are in your search PATH environment variables.
set(EXTLIBS_PACKAGE_FOLDER "${CMAKE_SOURCE_DIR}/extlibs")
function(sibr_addlibrary)
if(NOT WIN32)
return()
endif()
file(MAKE_DIRECTORY ${EXTLIBS_PACKAGE_FOLDER})
cmake_parse_arguments(args "VCID" "VERBOSE;TIMEOUT;DEFAULT_USE;NAME;VERSION;MSVC11;MSVC12;MSVC14;MSVC17" "MULTI_SET;SET" ${ARGN})
if (NOT "${args_VERSION}" MATCHES "")
message(WARNING "VERSION is not implemented yet")
endif()
set(lcname "")
set(ucname "")
string(TOLOWER "${args_NAME}" lcname)
string(TOUPPER "${args_NAME}" ucname)
set(LIB_PACKAGE_FOLDER "${EXTLIBS_PACKAGE_FOLDER}/${lcname}")
win3rdParty(${ucname}
$<args_VCID:VCID>
VERBOSE ${args_VERBOSE}
TIMEOUT ${args_TIMEOUT}
DEFAULT_USE ${args_DEFAULT_USE}
MSVC11 "${LIB_PACKAGE_FOLDER}" "${args_MSVC11}"
MSVC12 "${LIB_PACKAGE_FOLDER}" "${args_MSVC12}"
MSVC14 "${LIB_PACKAGE_FOLDER}" "${args_MSVC14}" # TODO SV: make sure to build this library if required
MSVC17 "${LIB_PACKAGE_FOLDER}" "${args_MSVC17}"
SET ${args_SET}
MULTI_SET ${args_MULTI_SET}
)
# Add include/ directory
# and lib/ directories
# TODO SV: paths not matching with current hierarchy. example: libraw/libraw-0.17.1/include
# SR: The link directories will also be used to lookup for dependency DLLs to copy in the install directory.
# Some libraries put the DLLs in the bin/ directory, so we include those.
file(GLOB subdirs RELATIVE ${LIB_PACKAGE_FOLDER} ${LIB_PACKAGE_FOLDER}/*)
set(dirlist "")
foreach(dir ${subdirs})
if(IS_DIRECTORY ${LIB_PACKAGE_FOLDER}/${dir})
# message("adding ${LIB_PACKAGE_FOLDER}/${dir}/include/ to the include directories")
include_directories("${LIB_PACKAGE_FOLDER}/${dir}/include/")
# message("adding ${LIB_PACKAGE_FOLDER}/${dir}/lib[64] to the link directories")
link_directories("${LIB_PACKAGE_FOLDER}/${dir}/")
link_directories("${LIB_PACKAGE_FOLDER}/${dir}/lib/")
link_directories("${LIB_PACKAGE_FOLDER}/${dir}/lib64/")
link_directories("${LIB_PACKAGE_FOLDER}/${dir}/bin/")
endif()
endforeach()
endfunction()
include(FetchContent)
include(git_describe)
function(sibr_gitlibrary)
cmake_parse_arguments(args "" "TARGET;GIT_REPOSITORY;GIT_TAG;ROOT_DIR;SOURCE_DIR" "INCLUDE_DIRS" ${ARGN})
if(NOT args_TARGET)
message(FATAL "Error on sibr_gitlibrary : please define your target name.")
return()
endif()
if(NOT args_ROOT_DIR)
set(args_ROOT_DIR ${args_TARGET})
endif()
if(NOT args_SOURCE_DIR)
set(args_SOURCE_DIR ${args_TARGET})
endif()
if(args_GIT_REPOSITORY AND args_GIT_TAG)
if(EXISTS ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/${args_SOURCE_DIR}/.git)
git_describe(
PATH ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/${args_SOURCE_DIR}
GIT_URL SIBR_GITLIBRARY_URL
GIT_BRANCH SIBR_GITLIBRARY_BRANCH
GIT_COMMIT_HASH SIBR_GITLIBRARY_COMMIT_HASH
GIT_TAG SIBR_GITLIBRARY_TAG
)
if((SIBR_GITLIBRARY_URL STREQUAL args_GIT_REPOSITORY) AND
((SIBR_GITLIBRARY_BRANCH STREQUAL args_GIT_TAG) OR
(SIBR_GITLIBRARY_TAG STREQUAL args_GIT_TAG) OR
(SIBR_GITLIBRARY_COMMIT_HASH STREQUAL args_GIT_TAG)))
message(STATUS "Library ${args_TARGET} already available, skipping.")
set(SIBR_GITLIBRARY_DECLARED ON)
else()
message(STATUS "Adding library ${args_TARGET} from git...")
endif()
endif()
FetchContent_Declare(${args_TARGET}
GIT_REPOSITORY ${args_GIT_REPOSITORY}
GIT_TAG ${args_GIT_TAG}
GIT_SHALLOW ON
SOURCE_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/${args_SOURCE_DIR}
SUBBUILD_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/subbuild
BINARY_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/build
)
FetchContent_GetProperties(${args_TARGET})
string(TOLOWER "<name>" lcTargetName)
if((NOT SIBR_GITLIBRARY_DECLARED) AND (NOT ${lcTargetName}_POPULATED))
message(STATUS "Populating library ${args_TARGET}...")
FetchContent_Populate(${args_TARGET} QUIET
GIT_REPOSITORY ${args_GIT_REPOSITORY}
GIT_TAG ${args_GIT_TAG}
SOURCE_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/${args_SOURCE_DIR}
SUBBUILD_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/subbuild
BINARY_DIR ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/build
)
endif()
add_subdirectory(${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/${args_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/extlibs/${args_ROOT_DIR}/build)
get_target_property(type ${args_TARGET} TYPE)
if(NOT (type STREQUAL "INTERFACE_LIBRARY"))
set_target_properties(${args_TARGET} PROPERTIES FOLDER "extlibs")
endif()
list(APPEND ${args_TARGET}_INCLUDE_DIRS ${EXTLIBS_PACKAGE_FOLDER}/${args_ROOT_DIR})
list(APPEND ${args_TARGET}_INCLUDE_DIRS ${EXTLIBS_PACKAGE_FOLDER}/${args_ROOT_DIR}/${args_SOURCE_DIR})
foreach(args_INCLUDE_DIR ${args_INCLUDE_DIRS})
list(APPEND ${args_TARGET}_INCLUDE_DIRS ${EXTLIBS_PACKAGE_FOLDER}/${args_ROOT_DIR}/${args_SOURCE_DIR}/${args_INCLUDE_DIR})
endforeach()
include_directories(${${args_TARGET}_INCLUDE_DIRS})
else()
message(FATAL "Error on sibr_gitlibrary for target ${args_TARGET}: missing git tag or git url.")
endif()
endfunction()

View File

@ -0,0 +1,63 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
#########################################################
# Include doxygen documentation target
#########################################################
option(BUILD_DOCUMENTATION "build doxygen documentation ('Build' DOCUMENTATION target, and find the compiled docs in install/docs/index.html)" OFF)
if(BUILD_DOCUMENTATION)
set(DOXYGEN_REQUIRED_VERSION "1.8.17")
find_package(Doxygen)
if(NOT DOXYGEN_FOUND)
message(FATAL_ERROR "Doxygen not found, unable to generate documentation.")
elseif(DOXYGEN_VERSION VERSION_LESS DOXYGEN_REQUIRED_VERSION)
message(FATAL_ERROR "Doxygen version is less than ${DOXYGEN_REQUIRED_VERSION} (Current version is ${DOXYGEN_VERSION}).")
else()
set(DOXY_DOC_DEST_DIR ${CMAKE_INSTALL_ROOT}/docs) ## used in the doxyfile.in
set(DOXY_DOC_INPUT_ROOT_DIRS "${CMAKE_HOME_DIRECTORY}/src ${CMAKE_HOME_DIRECTORY}/docs ${CMAKE_CURRENT_BINARY_DIR}/generated") ## used in the doxyfile.in
set(DOXY_DOC_EXCLUDE_PATTERNS_DIRS "${DOXY_DOC_EXCLUDE_PATTERNS_DIRS}") ## used in the doxyfile.in
set(DOXY_DOC_COMMON_IMG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/img ${CMAKE_HOME_DIRECTORY}/src/projects")
set(DOXY_DOC_PAGES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/pages")
set(DOXY_DOC_GENERATED_DOC_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
string(REPLACE "\\" "\\\\" SIBR_PROJECTS_SAMPLES_SUBPAGE_REF "${SIBR_PROJECTS_SAMPLES_SUBPAGE_REF}")
string(REPLACE "\\" "\\\\" SIBR_PROJECTS_OURS_SUBPAGE_REF "${SIBR_PROJECTS_OURS_SUBPAGE_REF}")
string(REPLACE "\\" "\\\\" SIBR_PROJECTS_TOOLBOX_SUBPAGE_REF "${SIBR_PROJECTS_TOOLBOX_SUBPAGE_REF}")
string(REPLACE "\\" "\\\\" SIBR_PROJECTS_OTHERS_SUBPAGE_REF "${SIBR_PROJECTS_OTHERS_SUBPAGE_REF}")
string(REPLACE "\\" "\\\\" SIBR_PROJECTS_SAMPLES_REF_REF "${SIBR_PROJECTS_SAMPLES_REF_REF}")
string(REPLACE "\\" "\\\\" SIBR_PROJECTS_OURS_REF_REF "${SIBR_PROJECTS_OURS_REF_REF}")
string(REPLACE "\\" "\\\\" SIBR_PROJECTS_TOOLBOX_REF_REF "${SIBR_PROJECTS_TOOLBOX_REF_REF}")
string(REPLACE "\\" "\\\\" SIBR_PROJECTS_OTHERS_REF_REF "${SIBR_PROJECTS_OTHERS_REF_REF}")
string(REPLACE "\n" "\\n" SIBR_PROJECTS_SAMPLES_SUBPAGE_REF "${SIBR_PROJECTS_SAMPLES_SUBPAGE_REF}")
string(REPLACE "\n" "\\n" SIBR_PROJECTS_OURS_SUBPAGE_REF "${SIBR_PROJECTS_OURS_SUBPAGE_REF}")
string(REPLACE "\n" "\\n" SIBR_PROJECTS_TOOLBOX_SUBPAGE_REF "${SIBR_PROJECTS_TOOLBOX_SUBPAGE_REF}")
string(REPLACE "\n" "\\n" SIBR_PROJECTS_OTHERS_SUBPAGE_REF "${SIBR_PROJECTS_OTHERS_SUBPAGE_REF}")
string(REPLACE "\n" "\\n" SIBR_PROJECTS_SAMPLES_REF_REF "${SIBR_PROJECTS_SAMPLES_REF_REF}")
string(REPLACE "\n" "\\n" SIBR_PROJECTS_OURS_REF_REF "${SIBR_PROJECTS_OURS_REF_REF}")
string(REPLACE "\n" "\\n" SIBR_PROJECTS_TOOLBOX_REF_REF "${SIBR_PROJECTS_TOOLBOX_REF_REF}")
string(REPLACE "\n" "\\n" SIBR_PROJECTS_OTHERS_REF_REF "${SIBR_PROJECTS_OTHERS_REF_REF}")
file(GLOB doxygen_config_files "*.in")
foreach(filename ${doxygen_config_files})
message(STATUS "Generating ${filename}...")
get_filename_component(output_filename ${filename} NAME_WLE)
message(STATUS "Output in ${CMAKE_CURRENT_BINARY_DIR}/${output_filename}...")
configure_file(${filename} ${CMAKE_CURRENT_BINARY_DIR}/${output_filename} @ONLY)
endforeach()
add_custom_target(DOCUMENTATION ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/doxygen_prebuild.cmake
COMMAND ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/doxyfile"
WORKING_DIRECTORY ${CMAKE_HOME_DIRECTORY}
COMMENT "Building user's documentation into ${DOXY_DOC_DEST_DIR} dir..."
)
endif()
endif()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
set(SIBR_PROJECTS_SAMPLES_SUBPAGE_REF "@SIBR_PROJECTS_SAMPLES_SUBPAGE_REF@")
set(SIBR_PROJECTS_OURS_SUBPAGE_REF "@SIBR_PROJECTS_OURS_SUBPAGE_REF@")
set(SIBR_PROJECTS_TOOLBOX_SUBPAGE_REF "@SIBR_PROJECTS_TOOLBOX_SUBPAGE_REF@")
set(SIBR_PROJECTS_OTHERS_SUBPAGE_REF "@SIBR_PROJECTS_OTHERS_SUBPAGE_REF@")
set(SIBR_PROJECTS_SAMPLES_REF_REF "@SIBR_PROJECTS_SAMPLES_REF_REF@")
set(SIBR_PROJECTS_OURS_REF_REF "@SIBR_PROJECTS_OURS_REF_REF@")
set(SIBR_PROJECTS_TOOLBOX_REF_REF "@SIBR_PROJECTS_TOOLBOX_REF_REF@")
set(SIBR_PROJECTS_OTHERS_REF_REF "@SIBR_PROJECTS_OTHERS_REF_REF@")
set(DOXY_DOC_DEST_DIR "@DOXY_DOC_DEST_DIR@")
set(DOXY_DOC_GENERATED_DOC_DIR "@DOXY_DOC_GENERATED_DOC_DIR@")
set(DOXY_DOC_PAGES_DIR "@DOXY_DOC_PAGES_DIR@")
## Cleaning documentation folders
file(REMOVE_RECURSE "${DOXY_DOC_GENERATED_DOC_DIR}")
file(REMOVE_RECURSE "${DOXY_DOC_DEST_DIR}")
## Generating documentation pages with variables
file(GLOB_RECURSE doc_files "${DOXY_DOC_PAGES_DIR}/*.in")
foreach(filename ${doc_files})
message(STATUS "Generating ${filename}...")
get_filename_component(output_filename ${filename} NAME_WLE)
message(STATUS "Output in ${DOXY_DOC_GENERATED_DOC_DIR}/${output_filename}...")
configure_file(${filename} ${DOXY_DOC_GENERATED_DOC_DIR}/${output_filename} @ONLY)
endforeach()

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 556 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 985 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@ -0,0 +1,232 @@
<doxygenlayout version="1.0">
<!-- Layout definition for the navigation index -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="yes" title="" intro=""/>
<tab type="usergroup" title="Code Reference" url="[none]">
<tab type="modules" visible="yes" title="Modules" intro=""/>
<tab type="namespaces" visible="yes" title="Namespaces">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="interfaces" visible="yes" title="Interfaces">
<tab type="interfacelist" visible="yes" title="" intro=""/>
<tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="interfacehierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="classes" visible="yes" title="Classes">
<tab type="classlist" visible="yes" title="" intro=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
<tab type="structs" visible="yes" title="Structs">
<tab type="structlist" visible="yes" title="" intro=""/>
<tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
</tab>
<tab type="exceptions" visible="yes" title="Exceptions">
<tab type="exceptionlist" visible="yes" title="" intro=""/>
<tab type="exceptionindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="exceptionhierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="files" visible="yes" title="Files">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
<tab type="examples" visible="yes" title="Examples" intro=""/>
</tab>
<tab type="usergroup" title="Changelog" url="[none]">
<tab type="user" visible="yes" url="@ref deprecated" title="Deprecated features" intro=""/>
<tab type="user" visible="yes" url="@ref bug" title="Known bugs" intro=""/>
<tab type="user" visible="yes" url="@ref todo" title="Future changes" intro=""/>
</tab>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
<friends title=""/>
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
<variables title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="$INCLUDE_GRAPH"/>
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="yes"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
</directory>
</doxygenlayout>

View File

@ -0,0 +1,186 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@mainpage Getting Started
@section intro_sec Introduction
The System for Image-Based Rendering or **SIBR**, is a specialized collection of libraries and toolkits for quickly implementing Image-Based Rendering (IBR) algorithms, and includes implementations of several published IBR papers, mainly from Inria and UCL, but also (re-implementations) of projects from other research groups. Most of **SIBR** was developed over the years (since 2011) at Inria Sophia-Antipolis for the various IBR research projects in the group, but the codebase includes a significant part of code from the *fribr* codebase of P. Hedman from UCL. The codebase has a long history; see @ref sibr_history section.
In this first release, we are providing reference source code implementations and datasets for the following \ref sibr_projects_available.
We will be progressively releasing more implementations of past and future projects (please see the @ref sibr_roadmap). For the first few releases, the main intended usage of the codebase is comparisons with previous algorithms. In the medium-term future, we hope that the codebase will be useful to others for the development of their own IBR algorithms.
The codebase contains three main components: the main *core* library, various utility/helper libraries and what we call *Projects* (see @ref sibr_projects_about), that are the implementations of Inria, UCL (and other) research projects.
The core library has support for multi-view (MV) datasets, processed with Structure-from-Motion (SfM) and Multi-view Stereo (MVS) software. We support data from various SfM/MVS sources, such as *colmap* and the (commercial) *RealityCapture* package (see @ref howto_generate_dataset), and a some interactive viewing utilities for developing and debugging IBR algorithms (e.g., ``top view'' shown below).
@image HTML ulr_screenshot.png An example view of SIBR width=700px
The utilities include various MV dataset (pre-)processing utilities that are used by various *Projects* and can be of general use, and various utilities for different API interfaces (e.g., tensorflow and pytorch, OptiX) and the core *fribr* framework from UCL that is used in some *Projects*.
Each *Project* provided in **SIBR** has (more or less) similar documentation and code structure: a binary release for easy use, how to checkout the code, configure, build and install the solution, and run the basic renderer; a set if fully-processed datasets are provided for each project. The *Project* has *apps*, typically including a *rendering app* that is usually enough to run the method to compare with a new algorithm on one of our datasets.
Most projects also have a *preprocessing* step. The code for preprocessing allows processing of your own data with the corresponding algorithm; the datasets provided have been processed with these tools.
Please see the section on comparisons (@ref comparisons_sec) below.
The first *Project* is bundled in the *core* library, and has implementations of per-pixel variants of the Unstructured Lumigraph \[Buehler 2001\] (see the @ref ulrPage page). This implementation has been used as a baseline comparison in many of our projects, and is always a useful baseline for any new IBR algorithm.
The licensing of the *core* is free for non-commercial, research and evaluation purposes, by academic or industrial labs, as defined in the LICENSE.md file. For commercial usage in a for-profit product, a paid license is required; please contact George.Drettakis@inria.fr if you are interested.
The rest of this page explains how to download binaries, compile, configure and install the basic system and its documentation.
If you use this code in a publication, please cite the system as follows in your publications:
```
@misc{sibr2020,
author = "Bonopera, Sebastien and Hedman, Peter and Esnault, Jerome and Prakash, Siddhant and Rodriguez, Simon and Thonat, Theo and Benadel, Mehdi and Chaurasia, Gaurav and Philip, Julien and Drettakis, George",
title = "sibr: A System for Image Based Rendering",
year = "2020",
url = "https://sibr.gitlabpages.inria.fr/"
}
```
@section comparison_sec Comparisons
A major goal of this code release is to allow comparisons. Most renderers in the *Projects* are interactive, allowing free-viewpoint navigation in the corresponding scenes. For comparisons, most renderers take a <code>--pathFile</code> argument that is a path of cameras in the scene. These are written to the directory requested, or by default in the <code>pathOutput</code> directory at the root of the dataset. For more details on cameras and paths, see the tutorial page @ref howto_cameras_paths .
@section install_sec Installation
**Note**: The current release is for *Windows 10* only. We are planning a Linux release soon.
@subsection sibr_binaries Binary distribution
The easiest way to use *SIBR* is to download the binary distribution. All steps described below, including all preprocessing for your datasets will work using this code.
A binary distribution (200Mb) of the core is available here:
```
wget https://repo-sam.inria.fr/fungraph/sibr-release/sibr-core/install.zip
```
unzip to create the ``install'' directory. All instructions below on running the code can be performed using this binary distribution.
@subsection sibr_example To run an example
Download a dataset from: https://repo-sam.inria.fr/fungraph/sibr-datasets/
e.g., the *sibr-museum-front* dataset in the *DATASETS_PATH* directory.
```
wget https://repo-sam.inria.fr/fungraph/sibr-datasets/museum_front27_ulr.zip
```
Once you have built the system or downloaded the binaries (see above), go to *install/bin* and you can run:
```
sibr_ulrv2_app.exe --path DATASETS_PATH/sibr-museum-front
```
You will have an interactive viewer and you can navigate freely in the captured scene.
Our default interactive viewer has a main view running the algorithm and a top view to visualize the position of the calibrated cameras. By default you are in WASD mode, and can toggle to trackball using the "y" key. Please see the page [Interface](https://sibr.gitlabpages.inria.fr/docs/nightly/howto_sibr_useful_objects.html) for more details on the interface.
@subsection sibr_prerequisite Prerequisites
- git
- Visual Studio 2019 (https://visualstudio.microsoft.com/).
- Cmake 3.16+,(https://cmake.org/).
- 7zip should be installed (https://www.7-zip.org/download.html).
- Python 3.8+ should be installed and configured in the PATH (https://www.python.org/downloads/).
- PIL (pip install pillow, in an admin command if needed: https://pypi.org/project/Pillow/) might be needed for some preprocess scripts.
- ImageMagick (https://imagemagick.org/script/download.php).
- Doxygen 1.8.17+ should be installed and configured in the PATH for generating the documentation (http://www.doxygen.nl/download.html).
- If needed (Optix, Tensorflow, Pytorch,... integration), CUDA 10.1+ (https://developer.nvidia.com/cuda-downloads) and cuDNN.
- An internet connection, as external dependencies will be downloaded from our servers during the CMake configuration.
@subsection sibr_checkout Checkout the code
- Clone sibr_core repository (https://gitlab.inria.fr/sibr/sibr_core). We recommend that you checkout master branch, but you can also work with the develop branch (unstable).
@code
## through HTTPS
git clone https://gitlab.inria.fr/sibr/sibr_core.git -b master
## through SSH
git clone git@gitlab.inria.fr:sibr/sibr_core.git -b master
@endcode
- You can add the projects' source code you would like to compile with SIBR, for this see @ref sibr_projects_add)
@subsection sibr_configure_cmake Configuring the solution
- Run Cmake, select SIBR root folder as a source directory and \<sibr_root_folder\>/build/ as the build directory.
- Configure, select the Visual Studio C++ Win64 compiler.
- Select the projects you want to generate among the BUILD_* variables in the list.
- Generate.
@subsection sibr_compile Compiling
- Configure the solution & Generate like we did in @ref sibr_configure_cmake.
- Open the generated Visual Studio solution (sibr_root/build/sibr_projects.sln).
- Build the BUILD_ALL target, and then the INSTALL target.
- The compiled executables will be put in install/bin.
@note If install fails, you will have to copy the required .dll files which are not copied automatically in the install/bin directory.
In general make sure these .dll files are in the bin directory : boost_system-vc141-mt-1_64.dll, boost_filesystem-vc141-mt-1_64.dll, glew32.dll, assimp-vc140-mt.dll, embree.dll.
Alternatively, you can selectively execute some of the install targets for specific projects.
@subsection sibr_generate_documentation Generating the documentation
- Configure the solution like we did in @ref sibr_configure_cmake and choose BUILD_DOCUMENTATION along with the projects you want in the documentation. Then generate the solution.
- Open the generated Visual Studio solution (sibr_root/build/sibr_projects.sln).
- Build the DOCUMENTATION target.
- The generated documentation will be put in docs and can be accessed through install/docs/index.html.
@subsection sibr_troubleshooting Troubleshoot
- Cmake can't find GLU, GLEW or another library: use an up-to-date CMake, check that you are connected to the Internet.
- Weird OpenCV error: you probably selected the 32-bits compiler in cmake-gui.
- 'Cmd.exe failed wither error 009' or similar: make sure Python is installed and in the PATH.
- BUILD_ALL or INSTALL fail because of a project you don't really need: build and install each project separately by selecting the proper targets.
- Some projects may depend on other projects. Make sure you have checked all the required projects before generating the solution.
- Error in CUDA headers under Visual Studio 2019: make sure CUDA >= 10.1 is installed.
@subsection sibr_bugs Bugs and Issues
We will track bugs and issues through the Issues interface on gitlab. Inria gitlab does not allow creation of external accounts, so if you have an issue/bug please email <code>sibr@inria.fr</code> and we will either create a guest account or create the issue on our side.
@subsection sibr_main_authors Authors
The authors of **SIBR** *core* are Gaurav Chaurasia (Ph.D. Inria, 2011-2013), Rodrigo Ortiz-Cayon (Ph.D. Inria 2013-2016), Jerome Esnault (Software Engineer, Inria, DATES), Sebastien Bonopera (Software Engineer, Inria, DATES), Theo Thonat (Ph.D. Inria 2015-2019), Simon Rodriguez (Ph.D. Inria, 2017-2020), Julien Philip (Ph.D. Inria, 2017-2020), Siddhant Prakash (Soft. Engineer & currently Ph.D. Inria). Mehdi Benadel (Soft. Engineer, Inria) is currently in charge of **SIBR**. George Drettakis had the overall supervision of the project throughout. See also @ref sibr_history.
Each *Project* has different authors, who are listed in the corresponding project pages. A special mention is due to Peter Hedman (at UCL) who wrote the *fribr* framework used in several projects.
@subsection sibr_funding Funding
The various projects in **SIBR** were funded by Inria, French national and European research funds. These include French Ministry of Education and University of Nice Sophia-Antipolis (now Universite Cote d'Azur) funds (G. Chaurasia, S. Rodriguez), the ANR SEMAPOLIS project (https://project.inria.fr/semapolis/) and the Region Provence Alpes Cote d'Azur (T. Thonat), the EU projects VERVE (https://gv2.scss.tcd.ie/VERVE/) G. Chaurasia; CR-PLAY (http://www.cr-play.eu/) R. Ortiz-Cayon, J. Esnault, S. Bonopera; EMOTIVE (https://emotiveproject.eu/) S. Duchene, J. Philip and the ERC FUNGRAPH project (http://fungraph.inria.fr), J. Philip, S. Rodriguez, S. Prakash, S. Morgenthaler, M. Benadel. The FRIBR code was funded by the Rabin Ezra scholarship fund for P. Hedman at UCL.
@section sibr_history History of SIBR
The oldest code in SIBR was written by G. Chaurasia for his Ph.D. in 2011-2013 at what was then the REVES (LINK) research group at Inria Sophia-Antipolis. The initial ULR implementation, and parts of the code in the Superpixel Warp project [Chaurasia 2013] are from this work. Gaurav re-factored the code to allow it work first with Qt and then with OpenSceneGraph, in a code base called *ibr_collection*, used for the EU project VERVE (https://gv2.scss.tcd.ie/VERVE/). In the followup CR-PLAY (http://www.cr-play.eu/) project, the code was refactored by S. Bonopera, and as part of the ERC FUNGRAPH S. Prakash was in charge of designing the current core/projects structure. M. Benadel has been in charge of cleanup for the release. The overall development of the entire project was managed by G. Drettakis.
@section sibr_roadmap SIBR Release Roadmap
After the first release (see \ref sibr_projects_available ), we plan to release code for the deep learning solution for outdoor relighting [Philip 19] (Jan 21), and potentially for other recent IBR projects from the GRAPHDECO group.
We will be releasing a Linux version of the core, and for some of the *Projects* soon. Stay tuned.
@subsection sibr_main_authors Authors
The authors of **SIBR** *core* are Gaurav Chaurasia (Ph.D. Inria, 2011-2013), Rodrigo Ortiz-Cayon (Ph.D. Inria 2013-2016), Jerome Esnault (Software Engineer, Inria, DATES), Sebastien Bonopera (Software Engineer, Inria, DATES), Theo Thonat (Ph.D. Inria 2015-2019), Simon Rodriguez (Ph.D. Inria, 2017-2020), Julien Philip (Ph.D. Inria, 2017-2020), Siddhant Prakash (Soft. Engineer & currently Ph.D. Inria). Mehdi Benadel (Soft. Engineer, Inria) is currently in charge of **SIBR**. George Drettakis had the overall supervision of the project throughout. See also @ref sibr_history.
Each *Project* has different authors, who are listed in the corresponding project pages. A special mention is due to Peter Hedman (at UCL) who wrote the *fribr* framework used in several projects.
@subsection sibr_funding Funding
The various projects in **SIBR** were funded by Inria, French national and European research funds. These include French Ministry of Education and University of Nice Sophia-Antipolis (now Universite Cote d'Azur) funds (G. Chaurasia, S. Rodriguez), the ANR SEMAPOLIS project (https://project.inria.fr/semapolis/) and the Region Provence Alpes Cote d'Azur (T. Thonat), the EU projects VERVE (https://gv2.scss.tcd.ie/VERVE/) G. Chaurasia; CR-PLAY (http://www.cr-play.eu/) R. Ortiz-Cayon, J. Esnault, S. Bonopera; EMOTIVE (https://emotiveproject.eu/) S. Duchene, J. Philip and the ERC FUNGRAPH project (http://fungraph.inria.fr), J. Philip, S. Rodriguez, S. Prakash, S. Morgenthaler, M. Benadel. The FRIBR code was funded by the Rabin Ezra scholarship fund for P. Hedman at UCL.
@section sibr_references References
[Chaurasia 13] G. Chaurasia, S. Duchene, O. Sorkine-Hornung, & G. Drettakis. (2013). Depth synthesis and local warps for plausible image-based navigation. ACM Transactions on Graphics (TOG), 32(3), 30. http://www-sop.inria.fr/reves/Basilic/2013/CDSD13/
[Philip 19] J. Philip, M. Gharbi, T. Zhou, A. Efros, G. Drettakis (2019), Multi-view Relighting Using a Geometry-Aware Network Multi-view-Relighting.pdf ACM Transactions on Graphics (SIGGRAPH Conference Proceedings), Volume 38, Number 4 - July 2019 http://www-sop.inria.fr/reves/Basilic/2019/PGZED19/
*/

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page projects Projects
*/

View File

@ -0,0 +1,77 @@
/*!
@page projects Projects
@section sibr_projects_about What are projects ?
Research algorithms and toolboxes have been implemented for SIBR as plugins named "Projects".\n
Unstructured Lumigraph Rendering (ULR) application is provided by default with SIBR to help users get started.\n
Some projects called toolboxes might also be used by other projects to bring additional functionalities (for instance the SIBR/Optix integration).\n
@subsection sibr_projects_available Available Projects
The list of projects that have been added to this generated version of SIBR's documentation is given below.\n
For projects corresponding to publications, the link to the paper is provided.\n
Most of other projects are helper libraries that can be used to augment SIBR with new functionalities.
- @subpage sibr_projects_samples
@SIBR_PROJECTS_SAMPLES_REF_REF@
- @subpage sibr_projects_ours
@SIBR_PROJECTS_OURS_REF_REF@
- @subpage sibr_projects_others
@SIBR_PROJECTS_OTHERS_REF_REF@
- @subpage sibr_projects_toolbox
@SIBR_PROJECTS_TOOLBOX_REF_REF@
@subsection sibr_projects_documentation Access projects documentation
Each project documentation is compilable through SIBR.\n
To access the projects documentation, first :\n
- Add the project to SIBR like explained in @ref sibr_projects_add
- Compile the documentation
@subsection sibr_projects_add Adding projects to SIBR
Existing projects can be added as subdirectories in the src/projects directory.\n
For this, you need to access to the project's source code (most of them are in https://gitlab.inria.fr/sibr/projects) to clone it, build it with SIBR and use it.\n
If you want to create your own project, see @ref howto_setup_project .\n
You can follow the given steps to add a project once access is given.\n
- You will need to checkout SIBR Core source code (see @ref sibr_checkout).
- Go to src/projects
- Clone/Copy the project source code in the correct project folder (it should be the same as the project repository, or check the README for more information).
- You can then resume with @ref sibr_generate_documentation or @ref sibr_compile
@subsection sibr_project_structure Project structure
See @ref project_structure
@subsection sibr_your_project Creating your own project
See @ref howto_setup_project
*/
/*!
@page sibr_projects_samples Sample algorithms & toolboxes
@SIBR_PROJECTS_SAMPLES_SUBPAGE_REF@
*/
/*!
@page sibr_projects_ours Our algorithms
@SIBR_PROJECTS_OURS_SUBPAGE_REF@
*/
/*!
@page sibr_projects_others Other algorithms
@SIBR_PROJECTS_OTHERS_SUBPAGE_REF@
*/
/*!
@page sibr_projects_toolbox Integrated toolboxes
@SIBR_PROJECTS_TOOLBOX_SUBPAGE_REF@
*/

View File

@ -0,0 +1,21 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page tutorials Dataset Documentation & Tutorials
- @subpage howto_generate_dataset
- @subpage howto_sibr_useful_objects
- @subpage howto_setup_project
- @subpage howto_cameras_paths
*/

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page architecture Architecture
This is a diagram describing the overall SIBR architecture:
@image html sibr_new_architecture.png "Architecture Diagram" width=700px
SIBR is built using layers.
@section Core
SIBR core module exposes internal libraries (system, graphics, assets, scene, raycaster, imgproc, view, renderer, video) which can be used to implement multiple IBR algorithms.
@subsection system
At the very low level, we have **core/system** that contains OS tools (e.g. filesystems), mathematical tools (e.g. vector operations), and standard tools (e.g. string operations). It also contains a configuration file (Config.hpp) that defines many useful macros/const.
In short:
- we use STL and C++11 (std::shared_ptr are heavily used)
- we use Boost Libraries to manage filesystems.
- we use Eigen for math tools. (Dev tips: Please use sibr::Vector<NumComp, Type> (e.g. sibr::Vector3f), because they define important flags.)
@subsection graphics
Next we expose **core/graphics** which contains graphics tools, such as images, meshes, textures, rendertargets, shaders,... We use OpenCV for managing images and image operations. Note that we wrapped OpenCV's cv::Mat in sibr::Image to control/check types statically. See sibr::Image class for details.
@subsection assets
The classes contained in **core/assets** represent basic resource files present in IBR datasets. These classes are useful for loading and reading different types of files found in a typical dataset.
@subsection scene
**core/scene** contains a full IBR dataset representation and storage, based on multiple components that form a "scene". A good example is sibr::BasicIBRScene, containing a default set of assets (cameras, images, proxies etc.) which can be initialized by means of a scene metadata file.
@subsection raycaster
The **core/raycaster** library provides raycasting and intersection test utilities, wrapping Intel Embree for fast ray/triangle tests.
@subsection imgproc
Basic image processing utilities cam be found in **core/imgproc**. For more complex tasks, you can use OpenCV algorithms as our Images are backed by OpenCV matrices.
@subsection video
You can load and save videos using the **core/video** module. It internally relies on ffmpeg.
@subsection view
The **core/view** library exposes tools for making viewer apps for live rendering and debugging of the algorithms. It define a basic view interface along with interactive camera modes, a multi-window management system,...
@subsection renderer
The classes in **core/renderer** library implements general rendering passes and functionalities required for many IBR applications. usually, when designing a View for a custom rendering algorithm, you will use multiple renderers, some customs and some out-of-the-box.
*/

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page HowToColmap How to create a dataset from Colmap
We provide a python script that runs the entire Colmap pipeline, see here: @ref sibr_projects_dataset_tools_preprocess_tools_fullColmapProcess
@note The previous link might not be available if you did not build the doc with `BUILD_IBR_DATASET_TOOLS` on
However, you can also run your own Colmap reconstruction by yourself, and use `ColmapToSIBR` to create an SIBR project (i.e., images without borders, of the same size) from colmap data. In the install\scripts directory run:
@code
python colmap2sibr PATH_TO_DATASET
@endcode
This will create a *sibr_cm* subdirectory containing the modified scene.
\section HowToColmap_example_datasets Example Datasets
Example datasets processed with *fullColmapProcess* and *colmap2Sibr* are here:
\n
https://repo-sam.inria.fr/fungraph/sibr-datasets/
\n
*/

View File

@ -0,0 +1,97 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page HowToCapreal How to create a dataset from Reality Capture
\tableofcontents
@section capreal_usage How to use
We use Reality Capture to generate a reconstruction of a mesh from several images gererated with multiple point of view. The program can open a group of images and determinate the position of the initial cameras.
Please be aware that RealityCapture does not let you export the results without a license (which you might need to pay for).
Here is a detailed explanation of all the steps:
@subsection capreal_usage_layout Choose your layout
Before anything, you'll have to choose your layout.
You can modify them with the icons on the top of the screen.
The interface can be a bit wonky, especially the 3D view. If you want to avoid possible display issues, you can choose `1 + 1 + 1 Layout`.
@image html caprealnew.png Layout
@subsection capreal_usage_input_images Select input images
For reconstruction, you will need to provide a set of images of your scene. You can do so by clicking on `Inputs` or `Folder` buttons in the `Workflow` tab.
@image html caprealaddinputs.png Add input images
@image html caprealinputsonly.png Now the input images are set
@subsection capreal_usage_align_images Align images
When the image set is properly provided, you can align them with the `Align Images` option, in the `Alignment` tab.
@image html caprealalignimages.png Align images option
Now, you can see a point cloud in the 3D view.
@image html caprealpointcloud.png The point cloud you get when you align images
@subsection capreal_usage_mesh_reconstruction Mesh reconstruction
Now you'd want to have a mesh from the images. For this, you need to select one of the `Calculate Model` options in the `Reconstruction` tab. We'll go for the `Normal Detail` option.
@image html caprealmeshreconstruction.png The mesh reconstruction options
Now you should be able to see the reconstruction.
You can click on `Colorize` to colorize the mesh (or `Texture` if you want to texturize it : colorization only apprixomate vertices color, while texturing gives you an approximated texture).
The generated mesh is likely to be pretty complex in terms of triangle count.
You can decreased the number of triangles by doing : `Tools > Simplify Tools`
You can take 1 or 2 For teh render optionmillion of triangle for the simplification
You now have calibrated cameras and a reconstructed 3D mesh that are ready for use by **SIBR**. The next two sections explain whow to create a set of directories that will be useful for dataset managements, then save the data required from RealityCapture.
@image html caprealcolorizesimplify.png Colorize and Simplify Tools options
@section capreal_DirStruc Suggested directory structure
(Note: This directory structure is only suggested for user accessibility. You can store/create the dataset in separate directories as you like, as long as you provide correct input to the scripts to generate SIBR datasets.)
@li dataset\\raw
\n Contains the original images from the cameras.
\n
@li dataset\\rcprojs
\n Contains the .rcproj files and the data directories (these are big after reconstruction, since they contain the mesh and texture).
\n
@li dataset\\sfm_mvs_rc
\n Contains the exported undistorted images with black borders, the file bundle.out, pmvs_recon.ply and optionally textured.obj, textured.mtl and textured_u1_v1.png (see what to save below)
\n
@li dataset\\sibr_rc
\n Contains the extracted data to create scene(s) using SIBR, containing bundle file, reconstructed mesh, list of images, scene metadata etc. in proper directory structure.
\n
@section capreal_WhatToSave What to save from RealityCapture
In the selected directory (*sfm_mvs_rc*) save the following:
@li After alignment and reconstruction, save Registration (choose optionsbundler v0.3 Negative-Z format, jpg image type, fit=Inner_region), and save to file *bundle.out*
@li After reconstruction -> Mesh -> save to the file *recon.ply*
@li After texturing -> Mesh -> save textured.obj (which will save textured.mtl and textured_u1_v1.png containing the texture);
@todo Textures verify
@subsection Restore
@todo Does this exist ?
@li If something goes wrong, use python restore_dataset.py to restore all original files (bundle, ply, obj) as exported from RealityCapture
*/

View File

@ -0,0 +1,204 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page configure_project Configuring your project
@ingroup setup_project
@section gen_setup_config General setup
- Create a repository in `src/projects/my_project` (name your project at your convenience)
- Setup your project structure as stated in @ref project_structure
- Use the following sample files (form the following sections) for your `CMakeLists.txt` files and `Config.hpp` structure
- Re-run configure for the main SIBR `CMakeLists.txt`.
- The project should be automatically detected; If so, check `BUILD_IBR_MY_PROJECT` (`MY_PROJECT` being your project name folder) in CMake and re-generate.
@section all_sec Main project configuration
This `CMakeLists.txt` is the one in the root of your project. It is registering the subdirectories of your project against the main CMake.\n
It will also provide you with an additional project wide install target.\n
@code
set(SIBR_PROJECT "my_project") # Please replace my_project with your project folder name
project(sibr_${SIBR_PROJECT}_all)
# Update this with the folders included in your project
add_subdirectory(apps)
add_subdirectory(preprocess)
add_subdirectory(renderer)
include(install_runtime)
subdirectory_target(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR} "projects/${SIBR_PROJECT}")
@endcode
@section listing_sec Listing app & preprocesses projects
This `CMakeLists.txt` is registering the CMake projects in subdirectories against the main CMake of your SIBR project, putting them together in a custom named group.\n
They will appear as multiple solutions in a subdirectory in Visual Studio for instance.\n
Useful to group the `apps/` or `preprocess/` executables of a project.\n
\n
You can use it as sample structure for `apps/CMakeLists.txt` and `preprocess/CMakeLists.txt`.
@code
project(sibr_my_apps_group) # Please rename this project at your convenience
add_subdirectory(my_app_1/)
add_subdirectory(my_app_2/)
#...
@endcode
@section exe_sec App and preprocess projects
This example can be used for application and preprocess executables.\n
The parts to modify are the project name, the linked libraries and the folder property.\n
Put the `CMakeLists.txt` in your application project directory.
@code
set(SIBR_PROJECT "my_project") # Please replace my_project with your project folder name
project(sibr_${SIBR_PROJECT}_app) # Please rename this project at your convenience
file(GLOB SOURCES "*.cpp" "*.h" "*.hpp")
source_group("Source Files" FILES ${SOURCES})
# Define build output for project
add_executable(${PROJECT_NAME} ${SOURCES})
# Define dependencies
target_link_libraries(${PROJECT_NAME}
${Boost_LIBRARIES}
${ASSIMP_LIBRARIES}
${GLEW_LIBRARIES}
${OPENGL_LIBRARIES}
${OpenCV_LIBRARIES}
sibr_system
# you can add your internal or external dependencies here (sibr_renderer, sibr_view, sibr_graphics, sibr_assets,...)
)
# Define location in solution.
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER "projects/${SIBR_PROJECT}/apps")
## High level macro to install in an homogen way all our ibr targets
include(install_runtime)
ibr_install_target(${PROJECT_NAME}
INSTALL_PDB ## mean install also MSVC IDE *.pdb file (DEST according to target type)
STANDALONE ${INSTALL_STANDALONE} ## mean call install_runtime with bundle dependencies resolution
COMPONENT ${PROJECT_NAME}_install ## will create custom target to install only this project
)
@endcode
@section scripts_sec Scripts projects
You can also add scripts projects. Scripts are bundled in the install/scripts folder, which ensures you have access to utility functions and SIBR binaries.\n
@code
set(SIBR_PROJECT "my_project") # Please replace my_project with your project folder name
project(sibr_${SIBR_PROJECT}_scripts)
file(GLOB_RECURSE SCRIPTS "*.py") #add any scripts files / wildcards here
add_custom_target(${PROJECT_NAME} ALL)
include(install_runtime)
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER "projects/${SIBR_PROJECT}/preprocess")
ibr_install_rsc(${PROJECT_NAME} TYPE "scripts" FILES ${SCRIPTS} RELATIVE) # you can use FOLDER option if you want the scripts to be stored in a specific folder
@endcode
@section lib_sec Library project
This example can be used for libraries, in `renderer\CMakeLists.txt`.\n
The parts to modify are the project name, the linked libraries, the export/import flag for Windows libraries, and the folder property. \n
Put the `CMakeLists.txt` in your library project directory.\n
This example also supports displaying shaders and copying them to the bin/resources common directory.
@code
set(SIBR_PROJECT "my_project")
project(sibr_${SIBR_PROJECT}) # Please rename this project at your convenience
file(GLOB SOURCES "*.cpp" "*.h" "*.hpp")
source_group("Source Files" FILES ${SOURCES})
file(GLOB SHADERS "shaders/*.frag" "shaders/*.vert" "shaders/*.geom" "shaders/*.fp" "shaders/*.vp" "shaders/*.gp")
source_group("Source Files\\shaders" FILES ${SHADERS})
# Redefine sources and all the files to display in the IDE.
file(GLOB SOURCES "*.cpp" "*.h" "*.hpp" "shaders/*.frag" "shaders/*.vert" "shaders/*.geom" "shaders/*.fp" "shaders/*.vp" "shaders/*.gp")
# Declare library.
add_library(${PROJECT_NAME} SHARED ${SOURCES})
# Define dependencies.
include_directories(${Boost_INCLUDE_DIRS} .)
target_link_libraries(${PROJECT_NAME}
${Boost_LIBRARIES}
${ASSIMP_LIBRARIES}
${GLEW_LIBRARIES}
${OPENGL_LIBRARIES}
${OpenCV_LIBRARIES}
glfw3
sibr_system
# you can add your internal or external dependencies here (sibr_renderer, sibr_view, sibr_graphics, sibr_assets,...)
)
# Define export/import flag.
add_definitions( -DSIBR_MY_LIBRARY_EXPORTS -DBOOST_ALL_DYN_LINK ) # Please refactor it with your library export/import flag from Config.hpp
# Define location in solution.
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER "projects/${SIBR_PROJECT}/renderer")
## High level macro to install in an homogen way all our ibr targets
include(install_runtime)
ibr_install_target(${PROJECT_NAME}
INSTALL_PDB ## mean install also MSVC IDE *.pdb file (DEST according to target type)
SHADERS "${SHADERS}" ## You can also add scripts and resources with the corresponding keyword (SCRIPTS, RESOURCES)
RSC_FOLDER "${SIBR_PROJECT}" ## Resources will be stored in this subfolder in their respective resource folder (scripts, shaders, resources)
COMPONENT ${PROJECT_NAME}_install ## will create custom target to install only this project
)
@endcode
To handle export/import of library methods properly on Windows, you also need a `Config.hpp` file in your library directory.
@code
#ifndef __SIBR_MY_LIBRARY_CONFIG_HPP__ // Please refactor it with your library name
# define __SIBR_MY_LIBRARY_CONFIG_HPP__ // Please refactor it with your library name
# include <core/system/Config.hpp>
# ifdef SIBR_OS_WINDOWS
# ifdef SIBR_STATIC_DEFINE
# define SIBR_EXPORT
# define SIBR_NO_EXPORT
# else
# ifndef SIBR_MY_LIBRARY_EXPORT // Please refactor it with your library name
# ifdef SIBR_MY_LIBRARY_EXPORTS // Please refactor it with your library name
/* We are building this library */
# define SIBR_MY_LIBRARY_EXPORT __declspec(dllexport) // Please refactor it with your library name
# else
/* We are using this library */
# define SIBR_MY_LIBRARY_EXPORT __declspec(dllimport) // Please refactor it with your library name
# endif
# endif
# ifndef SIBR_NO_EXPORT
# define SIBR_NO_EXPORT
# endif
# endif
# else
# define SIBR_MY_LIBRARY_EXPORT // Please refactor it with your library name
# endif
#endif //__SIBR_MY_LIBRARY_CONFIG_HPP__ // Please refactor it with your library name
@endcode
*/

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page create_library Creating your library
@ingroup setup_project
@section ge_setup_library General setup
The content of your library would basically be up to what you will need in this specific project.\n
However, we do implement core patterns that could be useful to create your view and handle the rendering of your scene.
@section library_views Views
basic example of a View:
see:
- https://gitlab.inria.fr/mbenadel/sibr_simple/-/blob/master/renderer/SimpleView.hpp
- https://gitlab.inria.fr/mbenadel/sibr_simple/-/blob/master/renderer/SimpleView.cpp
@section library_renderers Renderers
basic example of a Renderer:
see:
- https://gitlab.inria.fr/mbenadel/sibr_simple/-/blob/master/renderer/SimpleRenderer.hpp
- https://gitlab.inria.fr/mbenadel/sibr_simple/-/blob/master/renderer/SimpleRenderer.cpp
@section library_shaders Shaders
Shaders copy to binary folder is handled by the library CMake.\n
You can put your shaders files in `renderer/shaders` with the following extensions:
- `.vert`
- `.frag`
- `.geom`
- `.vp`
- `.fp`
- `.gp`
If unchanged, those shaders should be copied to `install/bin/shaders_rsc`.\n
To extend this behavior, please update `renderer/CMakeLists.txt`.
*/

View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page document_project Documenting projects
@ingroup setup_project
@section gendoc Writing
Each class created in one of the core SIBR modules (system, assets,...) should be properly documented.
Please try to document as many methods as possible (especially public ones). Don't forget to <b>add each class to its module</b>.
You will find below an example of a commented class.
@verbatim
/* Represents a general view.
@ingroup sibr_view
*/
class SIBR_MY_LIBRARY_EXPORT MyView {
public:
/* Loads everything.
@param flags the options to use.
@return a boolean denoting the success of the operation.
*/
bool load(const int flags);
MyView();
~MyView();
private:
/* Performs complex operations.
@param val the value to use.
*/
void performComplexOps(const float val);
int _flags; ///< configuration flags
sibr::Vector2i _size; ///< The size of the view.
}
@endverbatim
If you need to create a new module and want it to appear in the Modules doxygen listing, you will need to create a `sibr_mymodule.dox` file in your module directory, with the following content:
@verbatim
/*!
@defgroup sibr_mymodule
@brief This is my module.
This is a longer description of my module. It's mine.
*/
@endverbatim
You can also write general .dox pages to give more details on a process or a project.\n
Please add them to your project `documentation/` folder.\n
Here is an example of a dox file content:\n
@verbatim
/*!
@page yourPageReference Your Page Name
This is a Page.\n
You can add ref to pages like this : @ref anotherPage\n
Or add a link to a subpage like this : @subpage yetAnotherPage\n
*/
@endverbatim
You can automatically link them as subpages in <a href="projects.html">docs/pages/Projects.dox</a> by providing a `<my_project>_doc.cmake` file in your project `documentation/` folder.\n
Here you can see an example:\n
@verbatim
/*!
set(PROJECT_PAGE "yourPageReference")
set(PROJECT_LINK "https://the.link.to.your.source.code.for.instance")
set(PROJECT_DESCRIPTION "A short description")
set(PROJECT_TYPE "OTHER") # this could be either SAMPLES, TOOLBOX, OURS or OTHERS. If not affiliated to SIBR, you might want to use OTHERS or TOOLBOX
*/
@endverbatim
@section compileDoc Generating
To generate the documentation, enable the BUILD_DOCUMENTATION flag in cmake and build the DOCUMENTATION target in Visual Studio. The generated output html pages will be accessible from <a href="../index.html">intall/docs/index.html</a>.
*/

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page project_structure Project Structure
@ingroup setup_project
@section gen_struct General structure
- Projects should follow the following hierarchy:
@verbatim
apps/
CMakeLists.txt # for listing apps to compile
my_app_1/ # one of your apps, named at your convenience
CMakeLists.txt
main.cpp
my_app_2/
CMakeLists.txt
main.cpp
preprocess/
CMakeLists.txt # for listing preprocesses to compile
my_preprocess_1/ # one of your preprocesses, named at your convenience
CMakeLists.txt
main.cpp
my_preprocess_2/
CMakeLists.txt
main.cpp
renderer/
CMakeLists.txt # for compiling your library
my_library_code.cpp
documentation/ # you can add optional documentation pages in this folder
my_doc.dox
CMakeLists.txt # project-wide configuration
@endverbatim
- `renderer/`: contains your library code and configuration
- `preprocess/`: contains your preprocesses listed by directory, and the configuration CMake file to list them
- `apps/`: contains your apps listed by directory, and the configuration CMake file to list them
- `documentation/`: contains additional doxygen documentation
*/

View File

@ -0,0 +1,176 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page howto_generate_dataset Dataset Structure and Generation
Most *Projects* take as input a *multi-view dataset*, i.e., a set of images taken using a camera (phone, DSLR, videocamera such as GoPro etc). In almost all cases we assume that a Structure-from-Motion (SfM) algorithm has been run on the input images to generate *calibrated cameras*, and most often a second Multi-View Stereo (MVS) step has been run, to generate a reconstructed 3D mesh. Optionally, we may also use dense depth maps that come from MVS.
In **SIBR** we have a ``native'' dataset format, described below, which was used traditionally for some of the original *Projects*. For most recent projects we have used the commercial tool RealityCapture for SfM/MVS, since it tends to produce the best overall reconstruction quality. In some recent projects (e.g., DeepBlending, or SemanticCars, see @ref projects), we have used *Colmap*, since the dense per-view depth maps are very useful.
As a result, **SIBR** supports two types of dataset natively:
@li Native **SIBR** datasets, created using the tools described below, from RealityCapture or Colmap.
We provide pre-processing documentation following which you can create SIBR compatible datasets from output of these two SfM/MVS systems:
- @subpage HowToCapreal
- @subpage HowToColmap
@li Native Colmap datasets: we simply create a metadata file the first time the dataset is read.
Different *Projects* often add additional information to their datasets, typically via multiple pre-processing utilities, some general, some specific to the *Project*.
Python scripts designed to process and prepare datasets are provided with each project along with instructions on how to use them in the corresponding documentation.
@section howto_generate_dataset_sibr_format Basic SIBR Dataset Structure and Generation
There are two main ways to generate a dataset for **SIBR**. The first is to use *colmap* (see @ref HowToColmap) to to SfM/MVS, and the second is using the commercial RealityCapture package (see @ref HowToCapreal).
After running <code>colmap</code> **SIBR** can read the dataset natively. In this case the dataset will just contain the <code>colmap</code> directory:
```
\dataset\
\dataset\colmap\
\dataset\colmap\sparse
\dataset\colmap\dataset.db
\dataset\colmap\stereo
\dataset\colmap\stereo\images
\dataset\colmap\stereo\sparse
```
SIBR expects camera calibration to be in <code>colmap\stereo\sparse</code>, and the MVS mesh in <code>colmap\stereo\meshed-delaunay.ply</code>.
Note that in this case, the images *do not have the same size*. Some IBR algorithms (e.g., ULR) can handle this, but others require that the input images all have the same size; this was historically the case for [Chaurasia 13], and **SIBR** handles this natively.
Specifically, we run the <code>colmap2sibr</code> script to generate an **SIBR** dataset.
The basic structure of this **SIBR** dataset is shown below, generated from colmap with texture:
\n
```
\dataset\
\dataset\colmap\
\dataset\sibr_cm\scene_metadata.txt
\dataset\sibr_cm\cameras
\dataset\sibr_cm\meshes
\dataset\sibr_cm\images
\dataset\sibr_cm\cameras\bundle.out
\dataset\sibr_cm\cameras\list_images.txt
\dataset\sibr_cm\images\{img00000000.jpg,...,img000000NN.jpg}
\dataset\sibr_cm\meshes\recon.{ply,obj}
\dataset\capreal\
\dataset\capreal\mesh.ply
\dataset\capreal\texture.png
```
\n
The native **SIBR** directory structure in <code>sibr_cm</code> is as follows.
The <code>colmap</code> directory contains the colmap reconstruction, with the calibration, depthmap and mesh data.
The <code>capreal</code> directory contains the textured mesh generated by the conversion pipeline.
In the <code>sibr_cm</code> subdirectory:
@li The *cameras* directory contains the calibrated cameras, using the *Bundler* format by default (\ref subsecDataSetFormatsBundle).
@li The *images* directory that contains the undistorted images from the reconstruction and the list images file (\ref subsecDataSetFormatsListImg)
@li The *meshes* directory that contains a *recon.ply* file that is the 3D reconstruction of the scene
\n
To generate a dataset after following the procedure for RealityCapture (@ref HowToCapreal), you need to perform the following steps:
@li Generate and build the solution to generate executables for preprocessing applications (unless you already have the binary distribution).
@li Go to `install\scripts`
@li Run the python script using
```
python ibr_preprocess_rc_to_sibr.py -i original_dataset_path -o original_dataset_path\sibr_rc --bin path_to_sibr_bin
```
@li Specifying the binaries directory is optional. While compiling cmake automatically generates settings file which is parsed by the script to set bin directory.
@li The script calls the distordCrop, cropFromCenter, and clipping_planes app executables; make sure they are up to date.
- They crop the images to remove the black borders; the --ratio parameter to distordCrop (currently 0.2 (/.5)) sets the percentage of border which can be removed. Images that have larger black borders are removed from the dataset.
- They also copy the meshes (ply and obj if available) and modifies the bundle.out and list_images.txt to the new values of resolution, and removes the images excluded (the numbers can be found in Dataset\\SibrData\\raw\\excluded_images.txt)
- Next they compute the clipping planes for each camera corresponding to input images and stores them in a clipping_planes.txt file.
- Finally, they parse all data to create a scene_metadata.txt file which holds information of the images, clipping planes etc. and is used to create the scene. This file can be manually extended.
@li *[Recommended]* If you do not want to create a copy of the dataset, you can only specify the input directory with -i option. The dataset will be generated within the input directory itself.
\n
The **SIBR** dataset will have the following structure, similar to the case above, but with <code>sibr_rc</code> instead of <code>sibr_cm</code>.
```
\dataset\
\dataset\sibr_rc\scene_metadata.txt
\dataset\sibr_rc\cameras
\dataset\sibr_rc\meshes
\dataset\sibr_rc\images
\dataset\sibr_rc\cameras\bundle.out
\dataset\sibr_rc\cameras\list_images.txt
\dataset\sibr_rc\images\{img000.jpg,...,img0NN.jpg}
\dataset\sibr_rc\meshes\recon.ply
\dataset\sibr_rc\meshes\recon.ply
\dataset\capreal\
\dataset\capreal\textured.obj
\dataset\capreal\textured.mtl
\dataset\capreal\textured_u1_v1.png
```
\n
\subsection subsecInputDatasetFilesFormats Dataset Files and Formats
\n
The following sections contain documentation of the various files used in the dataset. Some are inherited from other SfM/MVS solutions.
\subsection subsecMetadataFile The scene_metadata.txt file
Contains the list of images and their resolution as well as the near and far planes for each images.
\n
\subsection subsecDataSetFormatsBundle The bundle.out file
\n
Content: [the bundler documentation](http://www.cs.cornell.edu/~snavely/bundler/bundler-v0.4-manual.html) explain all what it contain \n
Description: [the output of the bundler](http://www.cs.cornell.edu/~snavely/bundler/bundler-v0.4-manual.html#S6) \n
Bundle file format is in plain text :\n
~~~~~~~~~~~~~{.txt}
# Bundle file v0.3
<num_cameras> <num_points> [two integers]
<camera1>
<camera2>
...
<cameraN>
<point1>
<point2>
...
<pointM>
~~~~~~~~~~~~~
Where \<camera\> contain :
~~~~~~~~~~~~~{.txt}
<f> <k1> <k2> [the focal length, followed by two radial distortion coeffs]
<R> [a 3x3 matrix representing the camera rotation]
<t> [a 3-vector describing the camera translation]
~~~~~~~~~~~~~
And where \<point\> contain :
~~~~~~~~~~~~~{.txt}
<position> [a 3-vector describing the 3D position of the point]
<color> [a 3-vector describing the RGB color of the point]
<view list> [a list of views the point is visible in]
~~~~~~~~~~~~~
\subsection subsecDataSetFormatsListImg The list_images.txt file
Content: It a list of all input images sorted by order it was taken (renamed) with their resolution \n
Description: If you have [ImageMagick](http://www.imagemagick.org/script/command-line-options.php#format_identify_) you can do : `identify -format "%f %w %h\n" *.jpg` \n
~~~~~~~~~~~~~{.txt}
<%8d.jpg> <width> <height>
~~~~~~~~~~~~~
Example:
~~~~~~~~~~~~~{.txt}
00000000.jpg 2256 1504
00000001.jpg 2256 1504
00000002.jpg 2256 1504
...
00000026.jpg 2256 1504
00000027.jpg 2256 1504
~~~~~~~~~~~~~
*/

View File

@ -0,0 +1,21 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page howto_setup_project How to setup your own project
- @subpage project_structure
- @subpage configure_project
- @subpage create_library
- @subpage document_project
*/

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page howto_cameras_paths Cameras, Paths and Dataset Alignment
@section cameras_section Cameras
Calibrated cameras come from the SfM method used. We support bundler <code>.out</code> (http://www.cs.cornell.edu/~snavely/bundler/bundler-v0.4-manual.html), Blender <code>.lookat</code>, Colmap <code>cameras.txt/images.txt</code> and to a certain extent VisualSFM <code>.nvm</code> files.
Each format has different constraints, and they are not always compatible. Internally, we convert to an <code>sibr::InputCamera</code> data structure.
@section paths_section Paths
We can read paths, i.e., a sequence of cameras, in any of the above formats in the interactive viewers for most renderers, typically in the main "View" panel, and the "Load path" button. The path can be played either by interpolated between the views ("Play" button), or just playing the exact cameras ("Play (No Interp)"). We also have an internal <code>.path</code> binary path format.
You can define key cameras in the same menu using the "Add key" button.
Paths can be played by most renderers by running the renderer in offscreen mode:
```
SIBR_renderer_app.exe --offscreen --pathFile path.(out|lookat|tst|path) [--outPath optionalOutputPath --noExit]
```
By default, the application exits when this operation is performed. Rendering the same path is the easiest way to compare different algorithms, and works for most of the *Projects* provided.
@section align_section Aligning datasets and transforming paths
We provide the <code>alignMeshes</code> tools to align two different reconstructions of the same multi-view dataset, see also the dataset tools page (@ref sibr_projects_dataset_tools).
If you need to align your dataset <code>dataset2Align</code> (e.g., a colmap reconstruction) to a reference dataset <code>refDataset</code> (e.g., a RealityCapture reconstruction) you can use the alignMeshes command (in <code>install\bin</code>).
*Important note: both datasets must have the same (or a subset of the same) images, calibrated cameras and a fully reconstructed mesh*
```
alignMeshes_rwdi.exe --path2Align dataset2Align --pathRef refDataset --out outputPath
alignMeshes.exe --path2Align dataset2Align --pathRef refDataset --out outputPath
```
This will align the two datasets, and write the aligned mesh in <code>outputPath</code> as well as the file <code>transform.txt</code> that contains the transformation matrix of the <code>dataset2Align</code> to <code>refDataset</code>.
Please note that alignMeshes may not manage to completely align meshes: please lalways compare the aligned mesh with the target (e.g., using meshlab). If alignmeshes fails, an alternative is to use a manual tool such as CloudCompare or meshlab.
You can then transform a camera path defined in the first dataset to the a path in the reference dataset:
```
cameraConverter_rwdi.exe --input inputPath.(out|lookat|path|tst) --output outputPath.(out|lookat|path|tst)
cameraConverter.exe --input inputPath.(out|lookat|path|tst) --output outputPath.(out|lookat|path|tst)
```
*/

View File

@ -0,0 +1,150 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
/*!
@page howto_sibr_useful_objects Useful systems in SIBR
@section multiviewmanager Using the windowing system
SIBR provides tools to display multiple rendering algorithms in different subviews that can be resized and hidden on screen. This is handled by the `MultiViewManager`. once instantiated and tied to a system window, the multi view manager can keep track of multiple views, ensuring that their content is updated and that they receive the correct user inputs. Views can be hidden, resized, their content captured as a screenshot.
Two modes can be used, mainly for legacy reasons:
- IBR subviews, that have to implement onRenderIBR() (which was used to support anaglyph rendering previously)
- basic subviews, that have to implement onRender()
It is possible to associate an interactive user camera to a view, so that the user can move around in the displayed content. Two views can use the same handler, for synchronized motion.
Basic example:
@code
Window window(PROGRAM_NAME, sibr::Vector2i(50, 50), myArgs);
MultiViewManager manager(window, false);
// Register a first view, with an interactive user camera
MyView::Ptr myView(new MyView());
InteractiveCameraHandler::Ptr userCam(new InteractiveCameraHandler());
manager.addIBRSubView("My view", myView);
manager.addCameraForView("My view", userCam);
// Register another view, which already handles the user motions by itself
DebugView::Ptr dbgView(new DebugView());
manager.addSubView("Debug view", dbgView, usedResolution);
while (window.isOpened()) {
Input::poll();
window.makeContextCurrent();
if (Input::global().key().isPressed(Key::Escape)) {
window.close();
}
manager.onUpdate(Input::global());
manager.onRender(window);
window.swapBuffer();
}
@endcode
@image html multiviewmanager.png
@section interactiveHandler Interactive user camera
User interaction in a view are handled by an `InteractiveCameraHandler`, that supports many interaction modes such as a FPS camera or a trackball.
It can also snaps to predefined viewpoints or interpolate between them. You can adjust the field of view and frustum planes.
You can toggle between modes in the GUI or by pressing Y.
- FPS : move around with WASD, down/up with Q/E, rotate with IJKL and roll with U/O.
- Trackball : rotate around a central point with the left click in the center of the view, roll with left click towards the view edges. Pan with righ click in the center region, move forward/backward with right click towards the view edges, or by scrolling. Ctrl+left click redefines the center of the trackball, this is very useful to focus on a specific region of the scene and zoom in.
- Orbit: rotate around using the numeric keypad.
@subsection recordPaths Recording and replaying camera paths
The handler can also records and playback paths. Once the `Record` button is pressed, all user camera motions are recorded. When pressing `Save path`, they will be saved to a file on disk. Types such as `.lookat`, `.path` and `.bundle` are supported, which is useful for comparison with other frameworks. A `.path` can be reloaded using the `Load path` button, and will start playing automatically.
@subsection recordVideos Generating videos
It is possible to record videos and dump images following a path in a view. In the camera handler GUI, you can check if you want to record videos or frames. If checked, the next start a path starts playing, each frame will be recorded and saved on disk.
- for video recording, check the corresponding box, start playing the path. At the end, in the view manager, select "Capture > Export video" and select the output destination (supported export format: h264 with `.mp4` extension).
- for frames recording, hen checking the box you will have to select an output directory. once the path starts to play, frames are going to be saved in the directory.
@section debugview Visualizing debug geometry
It can be useful to visualize information such as the scene geometry, location of the cameras, rays, voxel-like structures in a view with an interactive camera. SIBR provides the `MultiMeshManager` for this prupose. It can be used to display multiple meshes, vertices, lines,... At runtime, a list of all elements is displayed and many attributes can be toggled. The same attributes can be edited from the code using chaining. Everything can be updated on the fly based on the objects names.
For instance:
@code
debugView.addMeshAsLines("BBox", bbox).setColor({1.0f, 0.0f, 1.0f}).setDepthTest(false).setColormode(USER_DEFINED);
// Later in the code
debugView.addMeshAsLines("BBox", anotherBbox); // will replace the previous mesh
// Later again
debugView.getMeshData("BBox").setAlpha(0.5f); // dim the box
@endcode
Because the MultiMeshManager conforms to the ViewBase interface, it can be added to the view manager as any other view. It comes with its own interactive camera.
@note The `SceneDebugView` that can be used to visualize an IBR dataset including the geometry, cameras and images, is built on top of `MultiMeshManager`, with extra code generating geometry for the frusta and the image quads.
@image html multimeshmanager.png
@section commandlineargs Command line arguments
To simplify the definition and parsing of arguments, SIBR provide tools to easily define and populate arguments. The system is based on `Arg<T>` and `RequiredArg<T>`, that can be used to define arguments anywhere. It is recommended to group them in a structure, especially as some existing structures can be reused to define command arguments (windowing options, dataset path, etc., see for instance `WindowAppArgs` or `BasicDatasetArgs`).
Before anything, you have to make sure the raw input arguments have been parsed by calling `CommandLineArgs::parseMainArgs(argc, argv);` in your main. Any argument instantiated afterwards will then be able to fetch its user-provided value (if it exists). Default values and help messages can be provided when declaring arguments. Required arguments will raise an error when used if the user did not provide a value.
Arguments will convert to their contained type when using them, it is also possible to access their value using `get()`. Arguments values can also be set directly in the code.
@code
struct MyArgs : virtual WindowAppArgs, BasicDatasetArgs {
RequiredArg<int> iterations = {"itcount", 5, "Number of smoothing iterations"};
Arg<std::string> logPath = {"log", "", "Path to log file"};
Arg<bool> showResult = {"show", "Display results in a popup window"};
}
int main(int argc, char** argv){
CommandLineArgs::parseMainArgs(argc, argv);
MyArgs args;
const std::string logFile = args.logPath.get() + "_test.log";
Thing(args.iterations, logFile);
if(args.showResult){
//...
}
}
@endcode
@section uniformsystem The uniform system
When using OpenGL shaders, values are often passed from the CPU using uniforms. In the past, SIBR required the developer to maintain both a GLParameter object and the corresponding variable on the CPU to store the value and expose it. It is now recommended to use GLUniform<T>, that wraps a CPU value while allowing you to update the GPU uniform easily. The GLUniform will automatically converts to its contained type in most cases ; if a reference to the CPU value is needed, you can use get().
@code
// In the header, as members of a renderer for instance
GLShader _shader;
GLuniform<float> _val = 0.5;
// At construction
_shader.init("My Shader", "vertex shader content", "fragment shader content");
_val.init(_shader, "alpha"); // link the uniform to the shader, specify the name in the shader code
// At some point in the code
_val += 0.3f; // Mofidy the CPU value
// In the render loop
_shader.begin();
_val.send(); // Send to the GPU
...
@endcode
*/

View File

@ -0,0 +1,176 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
################################################################################
# This CMakeLists.txt manages which projects should be built and add their #
# dependencies. #
################################################################################
set(SIBR_FOLDER "core")
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "")
option(BUILD_SIBR "Build core libs of SIBR (sibr_system, sibr_graphics, sibr_view, sibr_assets, ...)" ON)
#https://stackoverflow.com/questions/7787823/cmake-how-to-get-the-name-of-all-subdirectories-of-a-directory
MACRO(SUBDIRLIST result curdir)
FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
SET(dirlist "")
foreach(child ${children})
IF(IS_DIRECTORY ${curdir}/${child})
LIST(APPEND dirlist ${child})
ENDIF()
endforeach()
SET(${result} ${dirlist})
ENDMACRO()
set(SIBR_PROJECTS_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/projects")
SUBDIRLIST(SUBDIRS ${SIBR_PROJECTS_FOLDER})
list(APPEND PROJECT_SUBFOLDERS "apps" "preprocess" "renderer" "scripts" "library")
# Moving ulr to the top of the list
list(PREPEND SUBDIRS "dataset_tools" "ulr" "basic")
list(REMOVE_DUPLICATES SUBDIRS)
## DEPS ##
include(include_once)
message(STATUS "\n\n****************** Handling core dependencies ******************")
include_once(dependencies) ## Map/bind 3rdParty/external dependencies packages to cmake
message(STATUS "****************************************************************\n\n")
foreach(subdir ${SUBDIRS})
set(${subdir}_ROOT_DIR "${SIBR_PROJECTS_FOLDER}/${subdir}")
set(PROJECT_NAME "BUILD_IBR_${subdir}")
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME)
if(${${PROJECT_NAME}})
foreach(PROJECT_SUBFOLDER ${PROJECT_SUBFOLDERS})
if(EXISTS "${${subdir}_ROOT_DIR}/${PROJECT_SUBFOLDER}/cmake/Modules")
list(APPEND CMAKE_MODULE_PATH ${${subdir}_ROOT_DIR}/${PROJECT_SUBFOLDER}/cmake/Modules)
endif()
if(EXISTS "${${subdir}_ROOT_DIR}/${PROJECT_SUBFOLDER}/cmake/dependencies.cmake")
message(STATUS "********* Handling ${subdir} ${PROJECT_SUBFOLDER} dependencies *********")
include_once("${${subdir}_ROOT_DIR}/${PROJECT_SUBFOLDER}/cmake/dependencies.cmake")
message(STATUS "****************************************************************\n\n")
endif()
endforeach()
endif()
endforeach()
Win3rdPartyGlobalCacheAction()
include_directories(.)
if (BUILD_SIBR)
add_subdirectory(core/system)
add_subdirectory(core/graphics)
add_subdirectory(core/renderer)
add_subdirectory(core/raycaster)
add_subdirectory(core/view)
add_subdirectory(core/scene)
add_subdirectory(core/assets)
add_subdirectory(core/imgproc)
add_subdirectory(core/video)
endif()
set(PROJECTS_ON_AT_FIRST_BUILD "basic" "gaussianviewer" "remote")
foreach(subdir ${SUBDIRS})
message(STATUS "Adding ${subdir} project")
set(PROJECT_NAME "BUILD_IBR_${subdir}")
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME)
if(NOT (DEFINED ${PROJECT_NAME}))
foreach(PROJECT_SUBFOLDER ${PROJECT_SUBFOLDERS})
if(EXISTS "${${subdir}_ROOT_DIR}/${PROJECT_SUBFOLDER}/CMakeLists.txt")
if(subdir IN_LIST PROJECTS_ON_AT_FIRST_BUILD)
option(${PROJECT_NAME} "Build project \"${subdir}\"" ON)
else()
option(${PROJECT_NAME} "Build project \"${subdir}\"" OFF)
endif()
break()
endif()
endforeach()
endif()
message(STATUS "${PROJECT_NAME} is ${${PROJECT_NAME}}")
if(${${PROJECT_NAME}})
if(EXISTS "${${subdir}_ROOT_DIR}/CMakeLists.txt")
add_subdirectory("${${subdir}_ROOT_DIR}")
else()
foreach(PROJECT_SUBFOLDER ${PROJECT_SUBFOLDERS})
if(EXISTS "${${subdir}_ROOT_DIR}/${PROJECT_SUBFOLDER}/CMakeLists.txt")
add_subdirectory("${${subdir}_ROOT_DIR}/${PROJECT_SUBFOLDER}")
endif()
endforeach()
endif()
if(EXISTS "${${subdir}_ROOT_DIR}/documentation/" AND BUILD_DOCUMENTATION)
unset(PROJECT_PAGE)
unset(PROJECT_LINK)
unset(PROJECT_DESCRIPTION)
unset(PROJECT_TYPE)
include("${${subdir}_ROOT_DIR}/documentation/${subdir}_doc.cmake" OPTIONAL)
if(NOT DEFINED PROJECT_PAGE)
set(PROJECT_PAGE "${subdir}Page")
endif()
if(NOT DEFINED PROJECT_TYPE)
set(PROJECT_TYPE "OTHERS")
endif()
set(PROJECT_SUBPAGE_REF " - @subpage ${PROJECT_PAGE}")
set(PROJECT_REF_REF " - @ref ${PROJECT_PAGE}")
if(DEFINED PROJECT_LINK)
string(APPEND PROJECT_SUBPAGE_REF " (${PROJECT_LINK})")
string(APPEND PROJECT_REF_REF " (${PROJECT_LINK})")
endif()
if(DEFINED PROJECT_DESCRIPTION)
string(APPEND PROJECT_SUBPAGE_REF ": ${PROJECT_DESCRIPTION}")
string(APPEND PROJECT_REF_REF " (${PROJECT_DESCRIPTION})")
endif()
string(APPEND SIBR_PROJECTS_${PROJECT_TYPE}_SUBPAGE_REF_LOCAL "${PROJECT_SUBPAGE_REF}\n")
string(APPEND SIBR_PROJECTS_${PROJECT_TYPE}_REF_REF_LOCAL "${PROJECT_REF_REF}\n")
if(EXISTS "${${subdir}_ROOT_DIR}/documentation/img")
set(DOXY_APP_SPECIFIC_IMG_PATH_LOCAL "${DOXY_APP_SPECIFIC_IMG_PATH_LOCAL} ${${subdir}_ROOT_DIR}/documentation/img")
endif()
if(EXISTS "${${subdir}_ROOT_DIR}/LICENSE.md")
set(DOXY_DOC_EXCLUDE_PATTERNS_DIRS_LOCAL "${DOXY_DOC_EXCLUDE_PATTERNS_DIRS_LOCAL} ${${subdir}_ROOT_DIR}/LICENSE.md")
endif()
endif()
else()
set(DOXY_DOC_EXCLUDE_PATTERNS_DIRS_LOCAL "${DOXY_DOC_EXCLUDE_PATTERNS_DIRS_LOCAL} ${${subdir}_ROOT_DIR}")
endif()
endforeach()
set(SIBR_PROJECTS_SAMPLES_SUBPAGE_REF "${SIBR_PROJECTS_SAMPLES_SUBPAGE_REF_LOCAL}" PARENT_SCOPE)
set(SIBR_PROJECTS_OURS_SUBPAGE_REF "${SIBR_PROJECTS_OURS_SUBPAGE_REF_LOCAL}" PARENT_SCOPE)
set(SIBR_PROJECTS_TOOLBOX_SUBPAGE_REF "${SIBR_PROJECTS_TOOLBOX_SUBPAGE_REF_LOCAL}" PARENT_SCOPE)
set(SIBR_PROJECTS_OTHERS_SUBPAGE_REF "${SIBR_PROJECTS_OTHERS_SUBPAGE_REF_LOCAL}" PARENT_SCOPE)
set(SIBR_PROJECTS_SAMPLES_REF_REF "${SIBR_PROJECTS_SAMPLES_REF_REF_LOCAL}" PARENT_SCOPE)
set(SIBR_PROJECTS_OURS_REF_REF "${SIBR_PROJECTS_OURS_REF_REF_LOCAL}" PARENT_SCOPE)
set(SIBR_PROJECTS_TOOLBOX_REF_REF "${SIBR_PROJECTS_TOOLBOX_REF_REF_LOCAL}" PARENT_SCOPE)
set(SIBR_PROJECTS_OTHERS_REF_REF "${SIBR_PROJECTS_OTHERS_REF_REF_LOCAL}" PARENT_SCOPE)
set(DOXY_APP_SPECIFIC_IMG_PATH "${DOXY_APP_SPECIFIC_IMG_PATH_LOCAL}" PARENT_SCOPE)
set(DOXY_DOC_EXCLUDE_PATTERNS_DIRS "${DOXY_DOC_EXCLUDE_PATTERNS_DIRS_LOCAL}" PARENT_SCOPE)
if (BUILD_IBR_TFGL_INTEROP)
add_subdirectory(projects/tfgl_interop/renderer/custom_ops)
endif()

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
# include <boost/filesystem.hpp>
# include <fstream>
# include "core/assets/ActiveImageFile.hpp"
namespace sibr
{
bool ActiveImageFile::load( const std::string& filename, bool verbose )
{
std::fstream file(filename, std::ios::in);
if(_numImages == 0 )
SIBR_WRG << "No Images Loaded while loading '"<<filename<<"'"<<std::endl;
// always create the array size of cameras so it can be queried.
_active.resize(_numImages);
for(int i=0; i < _numImages; i++)
_active[i]=false;
if (file && !boost::filesystem::is_empty(filename))
{
while (file.eof() == false)
{
int imageId;
file >> imageId;
_active[imageId] = true;
}
if( verbose )
SIBR_FLOG << "'"<< filename <<"' successfully loaded." << std::endl;
else
std::cerr<< "." ;
return true;
}
else {
for(int i=0; i < _numImages; i++)
_active[i]=true;
if( verbose )
SIBR_WRG << "file not found: '"<<filename<<"'"<<std::endl;
}
return false;
}
bool ActiveImageFile::load( const std::string& filename, int numImage, bool verbose )
{
_numImages = numImage;
return load(filename, verbose);
}
} // namespace sibr

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#pragma once
# include "core/graphics/Image.hpp"
# include "core/assets/Config.hpp"
# include "core/assets/IFileLoader.hpp"
namespace sibr
{
/** Represent a active_images.txt file use to select a subset of a scene images.
\ingroup sibr_assets
*/
class SIBR_ASSETS_EXPORT ActiveImageFile : public IFileLoader
{
public:
/**
Set the number of images contained in the associated scene.
\param n the number of images.
*/
void setNumImages(int n) { _numImages = n; }
/**
Load an active cameras listing from a file on disk.
\param filename the path to the file.
\param verbose output additional informations to the standard output.
\return a boolean indicating if the loading was successful or not.
*/
bool load( const std::string& filename, bool verbose = true ) override;
/**
Load an active cameras listing from a file on disk, expecting numImage images in total.
The active images file does not indicate the total number of cameras in the scene, thus the additional parameter.
\param filename the path to the file.
\param numImages the total number of images in the associated scene.
\param verbose output additional informations to the standard output.
\return a boolean indicating if the load was successful or not.
*/
bool load( const std::string& filename, int numImages, bool verbose = true );
/**
Return a reference to a boolean vector indicating, for each picture of
the associated scene, if it is active or not.
\return the boolean vector described above.
*/
const std::vector<bool>& active( void ) const { return _active; }
private:
std::vector<bool> _active; ///< Flags denoting which images are active.
int _numImages = 0; ///< Number of images.
};
} // namespace sibr

View File

@ -0,0 +1,45 @@
# Copyright (C) 2020, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
project(sibr_assets)
file(GLOB SOURCES "*.cpp" "*.h" "*.hpp" )
source_group("Source Files" FILES ${SOURCES})
file(GLOB SOURCES "*.cpp" "*.h" "*.hpp")
## Specify target rules
add_library(${PROJECT_NAME} SHARED ${SOURCES})
include_directories(
${Boost_INCLUDE_DIRS}
${xatlas_INCLUDE_DIRS}
)
target_link_libraries(${PROJECT_NAME}
${Boost_LIBRARIES}
${ASSIMP_LIBRARIES}
${GLEW_LIBRARIES}
${OPENGL_LIBRARIES}
${OpenCV_LIBRARIES}
OpenMP::OpenMP_CXX
sibr_graphics
xatlas
)
add_definitions(-DSIBR_ASSETS_EXPORTS -DBOOST_ALL_DYN_LINK)
set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER ${SIBR_FOLDER})
## High level macro to install in an homogen way all our ibr targets
include(install_runtime)
ibr_install_target(${PROJECT_NAME}
INSTALL_PDB ## mean install also MSVC IDE *.pdb file (DEST according to target type)
)

View File

@ -0,0 +1,515 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#include <fstream>
#include "core/assets/CameraRecorder.hpp"
#include "core/assets/InputCamera.hpp"
#include <opencv2/imgcodecs.hpp>
namespace sibr
{
void CameraRecorder::use(Camera& cam)
{
if (_recording) {
_cameras.push_back(cam);
}
else if (_playing && _pos < _cameras.size() ) {
const float znear = cam.znear();
const float zfar = cam.zfar();
if( !_playNoInterp ) {
//std::cout << _playing << std::endl;
// If we reach the last frame of the interpolation b/w two cameras, skip to next camera.
if (_interp > (1.0f - _speed))
{
_interp = 0.0f;
_pos++;
}
// Interpolate between the two closest cameras.
const float k = std::min(std::max(_interp, 0.0f), 1.0f);
sibr::Camera & camStart = _cameras[std::min(int(_pos), int(_cameras.size()) - 1)];
sibr::Camera & camNext = _cameras[std::min(int(_pos) + 1, int(_cameras.size())-1)];
cam = sibr::Camera::interpolate(camStart, camNext, k);
_interp += _speed;
}
else {
cam = _cameras[_pos];
_pos++;
if (_pos == _cameras.size())
_playNoInterp = false;
}
// Preserve the znear and zfar.
cam.znear(znear);
cam.zfar(zfar);
if (_saving) {
std::ostringstream ssZeroPad;
ssZeroPad << std::setw(8) << std::setfill('0') << (_pos);
cam.setSavePath(_savingPath + "/" + ssZeroPad.str() + ".png");
//std::cout << "Saving frame as: " << cam.savePath() << std::endl;
}
if (_savingVideo) {
cam.setDebugVideo(true);
}
if (_pos >= _cameras.size())
{
stop();
SIBR_LOG << "[CameraRecorder] - Playback Finished" << std::endl;
}
}
else {
//std::cout << _playing << std::endl;
cam.setSavePath("");
cam.setDebugVideo(false);
}
}
void CameraRecorder::playback(void)
{
stop();
_playing = true;
SIBR_LOG << "[CameraRecorder] - Playing" << std::endl;
}
void CameraRecorder::record(void)
{
stop();
_recording = true;
SIBR_LOG << "[CameraRecorder] - Recording" << std::endl;
}
void sibr::CameraRecorder::saving(std::string savePath)
{
_saving = true;
_savingPath = savePath;
SIBR_LOG << "[CameraRecorder] - Recording" << std::endl;
}
void CameraRecorder::savingVideo(bool saveVideo)
{
_savingVideo = saveVideo;
}
void sibr::CameraRecorder::stopSaving(void)
{
_saving = false;
_savingPath = "";
}
void CameraRecorder::stop(void)
{
_recording = _playing = false;
_pos = 0;
_interp = 0.0f;
}
void CameraRecorder::reset(void)
{
stop();
_cameras.clear();
}
bool CameraRecorder::load(const std::string& filename)
{
reset();
sibr::ByteStream stream;
if (stream.load(filename) == false)
return false;
int32 num = 0;
std::cout << " CameraRecorder::load " << num << std::endl;
stream >> num;
while (num > 0)
{
Camera cam;
stream >> cam;
_cameras.emplace_back(std::move(cam));
--num;
}
SIBR_LOG << "[CameraRecorder] - Loaded from " << filename << std::endl;
return stream;
}
void CameraRecorder::save(const std::string& filename)
{
sibr::ByteStream stream;
int32 num = (int32)_cameras.size();
stream << num;
for (const Camera& cam : _cameras)
stream << cam;
stream.saveToFile(filename);
SIBR_LOG << "[CameraRecorder] - Saved " << num << " cameras to " << filename << std::endl;
}
bool CameraRecorder::safeLoad(const std::string & filename, int w, int h)
{
Path path = Path(filename);
if (path.extension().string() == ".out") {
loadBundle(filename, w, h);
return true;
} else if (path.extension().string() == ".path") {
return load(filename);
}
SIBR_WRG << "Unable to load camera path" << std::endl;
return false;
}
void CameraRecorder::loadBundle(const std::string & filePath, int w, int h)
{
const std::string bundlerFile = filePath;
SIBR_LOG << "Loading bundle path." << std::endl;
// check bundler file
std::ifstream bundle_file(bundlerFile);
SIBR_ASSERT(bundle_file.is_open());
// read number of images
std::string line;
getline(bundle_file, line); // ignore first line - contains version
int numImages = 0;
bundle_file >> numImages; // read first value (number of images)
getline(bundle_file, line); // ignore the rest of the line
std::vector<InputCamera::Ptr> cameras(numImages);
// Parse bundle.out file for camera calibration parameters
for (int i = 0; i < numImages; i++) {
Matrix4f m;
bundle_file >> m(0) >> m(1) >> m(2) >> m(3) >> m(4);
bundle_file >> m(5) >> m(6) >> m(7) >> m(8) >> m(9);
bundle_file >> m(10) >> m(11) >> m(12) >> m(13) >> m(14);
cameras[i] = InputCamera::Ptr(new InputCamera(i, w, h, m, true));
cameras[i]->znear(0.2f); cameras[i]->zfar(250.f);
}
for (const InputCamera::Ptr cam : cameras)
{
_cameras.push_back(*cam);
}
}
void CameraRecorder::loadColmap(const std::string &filePath, int w, int h)
{
SIBR_LOG << "Loading colmap path." << std::endl;
boost::filesystem::path colmapDir ( filePath );
SIBR_LOG << "DEBUG: colmap path dir " << colmapDir.parent_path().string() << std::endl;
std::vector<InputCamera::Ptr> path = InputCamera::loadColmap(colmapDir.parent_path().string(), float(0.01), 1000, false );
for (const InputCamera::Ptr cam : path)
{
_cameras.push_back(*cam);
}
}
void CameraRecorder::loadLookat(const std::string &filePath, int w, int h)
{
SIBR_LOG << "Loading lookat path." << std::endl;
std::vector<InputCamera::Ptr> path = InputCamera::loadLookat(filePath, std::vector<Vector2u>{Vector2u(w, h)});
for (const InputCamera::Ptr cam : path)
{
_cameras.push_back(*cam);
}
}
void CameraRecorder::saveAsBundle(const std::string & filePath, const int height, const int step)
{
std::ofstream out(filePath.c_str(), std::ios::binary);
if (!out.good()) {
SIBR_LOG << "ERROR: cannot write to the file '" << filePath << "'" << std::endl;
return;
}
if(_cameras.empty()) {
return;
}
const int size = static_cast<int>(_cameras.size() / step);
out << "# Bundle file v0.3\n";
out << size << " " << 0 << "\n";
for (int i = 0; i < _cameras.size(); i += step) {
const sibr::Camera cam = _cameras[i];
sibr::Quaternionf q = cam.rotation();
sibr::Matrix3f m1 = q.toRotationMatrix();
sibr::Vector3f pos = -m1.transpose() * cam.position();
float m[15];
m[0] = 0.5f*height / tan(cam.fovy() / 2.f); m[1] = 0.0f; m[2] = 0.0f;
m[3] = m1(0, 0), m[4] = m1(1, 0), m[5] = m1(2, 0);
m[6] = m1(0, 1), m[7] = m1(1, 1), m[8] = m1(2, 1);
m[9] = m1(0, 2), m[10] = m1(1, 2), m[11] = m1(2, 2);
m[12] = pos.x(), m[13] = pos.y(), m[14] = pos.z();
out << m[0] << " " << m[1] << " " << m[2] << std::endl;
out << m[3] << " " << m[4] << " " << m[5] << std::endl;
out << m[6] << " " << m[7] << " " << m[8] << std::endl;
out << m[9] << " " << m[10] << " " << m[11] << std::endl;
out << m[12] << " " << m[13] << " " << m[14] << std::endl;
}
out << std::endl;
out.close();
SIBR_LOG << "[CameraRecorder] - Saved " << _cameras.size() << " cameras to " << filePath << " (using fovy " <<_cameras[0].fovy() << ")." << std::endl;
}
void CameraRecorder::saveAsColmap(const std::string& filePath, const int height, const int width)
{
std::string basepath = parentDirectory(filePath);
std::cout << basepath << std::endl;
std::string images_filepath = basepath + "/images.txt";
std::string cameras_filepath = basepath + "/cameras.txt";
std::ofstream out_images(images_filepath.c_str(), std::ios::binary);
std::ofstream out_cameras(cameras_filepath.c_str(), std::ios::binary);
if (!out_images.good()) {
SIBR_LOG << "ERROR: cannot write to the file '" << filePath << "'" << std::endl;
return;
}
if (!out_cameras.good()) {
SIBR_LOG << "ERROR: cannot write to the file '" << filePath << "'" << std::endl;
return;
}
if (_cameras.empty()) {
return;
}
const int size = static_cast<int>(_cameras.size());
sibr::Matrix3f converter;
converter << 1, 0, 0,
0, -1, 0,
0, 0, -1;
out_images << "# Image list with two lines of data per image:" << std::endl;
out_images << "# IMAGE_ID, QW, QX, QY, QZ, TX, TY, TZ, CAMERA_ID, NAME" << std::endl;
out_images << "# POINTS2D[] as (X, Y, POINT3D_ID)" << std::endl;
for (int i = 0; i < _cameras.size(); i++) {
sibr::Matrix3f tmp = _cameras[i].rotation().toRotationMatrix() * converter;
sibr::Matrix3f Qinv = tmp.transpose();
sibr::Quaternionf q = quatFromMatrix(Qinv);
sibr::Vector3f t = converter * _cameras[i].rotation().toRotationMatrix().transpose() * (-_cameras[i].position());
out_images << i << " " << -_cameras[i].rotation().x() << " " << -_cameras[i].rotation().w() << " " << -_cameras[i].rotation().z() << " " << _cameras[i].rotation().y() << " " <<
_cameras[i].view()(0, 3) << " " << -_cameras[i].view()(1, 3) << " " << -_cameras[i].view()(2, 3) << " " << i << " " << "00000000.png" << std::endl << std::endl;
float focal = 0.5f * height / tan(_cameras[i].fovy() / 2.f);
//float focal = 1.0f / (tan(0.5f * cam.fovy()) * 2.0f / float(height));
out_cameras << i << " " << "PINHOLE" << " " << width << " " << height << " " << focal << " " << focal << " " << width / 2.0 << " " << height / 2.0 << std::endl;
}
out_images << std::endl;
out_images.close();
out_cameras << std::endl;
out_cameras.close();
SIBR_LOG << "[CameraRecorder] - Saved " << _cameras.size() << " cameras to " << filePath << " (using fovy " << _cameras[0].fovy() << ")." << std::endl;
}
void CameraRecorder::saveAsFRIBRBundle(const std::string & dirPath, const int width, const int height)
{
const std::string bundlepath = dirPath + "/path.rd.out";
const std::string listpath = dirPath + "/list.txt";
const std::string imagesDir = dirPath + "/visualize/";
sibr::makeDirectory(dirPath);
sibr::makeDirectory(imagesDir);
std::ofstream out(bundlepath);
std::ofstream outList(listpath);
if (out.good() && outList.good()) {
const int size = static_cast<int>(_cameras.size() / 1);
out << "# Bundle file v0.3\n";
out << size << " " << 0 << "\n";
sibr::Matrix3f converter;
converter << 1, 0, 0,
0, -1, 0,
0, 0, -1;
sibr::Matrix3f from_cv;
from_cv << 1, 0, 0,
0, -1, 0,
0, 0, -1;
for (int i = 0; i < _cameras.size(); ++i) {
const sibr::Camera cam = _cameras[i];
sibr::Matrix3f orientation = cam.rotation().toRotationMatrix();
sibr::Vector3f position = cam.position();
sibr::Matrix3f rotation_cv = converter.transpose() * orientation.transpose() * converter;
sibr::Matrix3f rotation_bundler = from_cv * rotation_cv;
sibr::Vector3f position_cv = converter.transpose() * position;
sibr::Vector3f translation_cv = -(rotation_cv * position_cv);
sibr::Vector3f pos = from_cv * translation_cv;
sibr::Matrix3f m1 = rotation_bundler.transpose();
float m[15];
m[0] = 0.5f*height / tan(cam.fovy() / 2.f); m[1] = 0.0f; m[2] = 0.0f;
m[3] = m1(0, 0), m[4] = m1(1, 0), m[5] = m1(2, 0);
m[6] = m1(0, 1), m[7] = m1(1, 1), m[8] = m1(2, 1);
m[9] = m1(0, 2), m[10] = m1(1, 2), m[11] = m1(2, 2);
m[12] = pos.x(), m[13] = pos.y(), m[14] = pos.z();
out << m[0] << " " << m[1] << " " << m[2] << std::endl;
out << m[3] << " " << m[4] << " " << m[5] << std::endl;
out << m[6] << " " << m[7] << " " << m[8] << std::endl;
out << m[9] << " " << m[10] << " " << m[11] << std::endl;
out << m[12] << " " << m[13] << " " << m[14] << std::endl;
const std::string imageName = sibr::intToString<8>(i) + ".jpg";
outList << "visualize/" + imageName << " 0 " << m[0] << std::endl;
cv::Mat3b dummy(height, width);
cv::imwrite(imagesDir + imageName, dummy);
}
out << std::endl;
out.close();
outList.close();
SIBR_LOG << "[CameraRecorder] - Saved " << _cameras.size() << " cameras to " << dirPath << "." << std::endl;
}
}
void CameraRecorder::saveAsLookAt(const std::string & filePath) const
{
InputCamera::saveAsLookat(_cameras, filePath);
}
// offline path rendering
bool CameraRecorder::loadPath(const std::string& pathFileName, int w, int h) {
_savingPath = parentDirectory(pathFileName);
if (!fileExists(pathFileName)) {
SIBR_WRG << "Camera path " << pathFileName << " doesnt exist. " << std::endl;
return false;
}
_ow = w, _oh = h;
if (boost::filesystem::extension(pathFileName) == ".out")
loadBundle(pathFileName, w, h);
else if (boost::filesystem::extension(pathFileName) == ".lookat")
loadLookat(pathFileName, w, h);
else if (boost::filesystem::extension(pathFileName) == ".txt")
loadColmap(pathFileName, w, h);
else
load(pathFileName);
return true;
}
void CameraRecorder::recordOfflinePath(const std::string& outPathDir, ViewBase::Ptr view, const std::string& prefix) {
sibr::ImageRGBA32F::Ptr outImage;
outImage.reset(new ImageRGBA32F(_ow, _oh));
std::string outpathd = outPathDir;
sibr::RenderTargetRGBA32F::Ptr outFrame;
outFrame.reset(new RenderTargetRGBA32F(_ow, _oh));
std::string outFileName;
boost::filesystem::path dstFolder;
outpathd = outPathDir;
if (outPathDir == "pathOutput" && _savingPath != "") { // default to path parent, saved by loadPath
outpathd = _savingPath + "/" + "pathOutput";
dstFolder = outpathd;
if (!directoryExists(outpathd) && !boost::filesystem::create_directories(dstFolder))
SIBR_ERR << "Error creating directory " << dstFolder << std::endl;
}
if( prefix != "" )
dstFolder = outpathd = outpathd + "/" + prefix;
else
dstFolder = outpathd ;
if (!directoryExists(outpathd) && !boost::filesystem::create_directories(dstFolder))
SIBR_ERR << "Error creating directory " << dstFolder << std::endl;
std::cout << "Rendering path with " << _cameras.size() << " cameras to " << outpathd << std::endl;
for (int i = 0; i < _cameras.size(); ++i) {
outFrame->clear();
std::ostringstream ssZeroPad;
ssZeroPad << std::setw(8) << std::setfill('0') << i;
outFileName = outpathd + "/" + ssZeroPad.str() + ".png";
std::cout << outFileName << " " << std::endl;
view->onRenderIBR(*outFrame, _cameras[i]);
outFrame->readBack(*outImage);
outImage->save(outFileName, false);
}
std::cout << std::endl;
std::cout << "Done rendering path. " << std::endl;
}
void CameraRecorder::saveImage(const std::string& outPathDir, const Camera& cam, int w, int h) {
sibr::ImageRGBA32F::Ptr outImage;
_ow = w, _oh = h;
outImage.reset(new ImageRGBA32F(_ow, _oh));
std::string outpathd = outPathDir;
sibr::RenderTargetRGBA32F::Ptr outFrame;
outFrame.reset(new RenderTargetRGBA32F(_ow, _oh));
std::string outFileName;
boost::filesystem::path dstFolder;
outpathd = outPathDir;
if (outPathDir == "") { // default to path parent, saved by loadPath
outpathd = _dsPath + "/" + "pathOutput";
dstFolder = outpathd;
if (!directoryExists(outpathd) && !boost::filesystem::create_directories(dstFolder))
SIBR_ERR << "Error creating directory " << dstFolder << std::endl;
}
dstFolder = outpathd;
if (!directoryExists(outpathd) && !boost::filesystem::create_directories(dstFolder))
SIBR_ERR << "Error creating directory " << dstFolder << std::endl;
std::cout << "Saving current camera to " << outpathd << std::endl;
outFrame->clear();
std::ostringstream ssZeroPad;
static int i = 0;
ssZeroPad << std::setw(8) << std::setfill('0') << i++;
outFileName = outpathd + "/" + ssZeroPad.str() + ".png";
std::cout << outFileName << " " << std::endl;
_view->onRenderIBR(*outFrame, cam);
outFrame->readBack(*outImage);
outImage->save(outFileName, false);
std::cout << std::endl;
std::cout << "Done saving image. " << std::endl;
}
} // namespace sibr

View File

@ -0,0 +1,236 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#pragma once
# include <vector>
# include "core/assets/Config.hpp"
# include "core/graphics/Camera.hpp"
# include "core/view/ViewBase.hpp"
# define SIBR_CAMERARECORDER_DEFAULTFILE "camera-record.bytes"
namespace sibr
{
/** This class handles the recording and replay of a stream of cameras.
\ingroup sibr_assets
*/
class SIBR_ASSETS_EXPORT CameraRecorder
{
public:
/**
Default constructor.
*/
CameraRecorder(void) :
_pos(0), _recording(false), _playing(false), _saving(false), _savingPath(""), _savingVideo(false), _savingVideoPath(""), _speed(1.0f), _interp(0.0f), _playNoInterp(false) {
//load();
}
/**
Default destructor.
*/
~CameraRecorder( void ) {
}
/**
This method supports two modes: if the recorder is currently recording,
the camera argument will be saved into the recording; else if the recorder
is playing, the camera argument will be set to the current replaid camera.
\param cam A reference to the camera to record/update.
*/
void use( Camera& cam );
/**
Start playing the recorded camera stream from the beginning, at a rate of one step for each "use" call.
*/
void playback( void );
/**
Start recording a new camera stream, at a rate of one camera saved for each "use" call.
*/
void record( void );
/**
Start asking the renderer to save the frames, at a rate of one image saved for each "use" call.
*/
void saving(std::string savePath);
/**
Toggle the save flag for video frames when replaying.
\param saveVideo the new flag status
*/
void savingVideo(bool saveVideo);
/**
Stop saving.
*/
void stopSaving(void);
/**
Stop playing/recording.
*/
void stop( void );
/**
Clear the current recording.
*/
void reset( void );
/**
Set value of play no interpolation
*/
void playNoInterpolation( bool val ) { _playNoInterp = val; }
/**
Load a recorded camera stream from a given file.
\param filename Optional path to the file to load from. By default will try to
load SIBR_CAMERARECORDER_DEFAULTFILE from the current directory.
\return a boolean denoting the loading success/failure.
*/
bool load( const std::string& filename=SIBR_CAMERARECORDER_DEFAULTFILE );
/**
Save the current recording stream to a given file.
\param filename Optional path to the file to write to. By default will try to
write to SIBR_CAMERARECORDER_DEFAULTFILE in the current directory.
*/
void save( const std::string& filename=SIBR_CAMERARECORDER_DEFAULTFILE );
/** Load recorded path based on file extension.
*\param filename the file to load
*\param w resoltuion width
*\param h resolution height
*\return a success boolean
*\note w and h are needed when loading a Bundle.
*/
bool safeLoad(const std::string& filename, int w = 1920, int h = 1080);
/**
Load a recording stream saved as a bundle file (useful for path from FRIBR).
\param filePath Path to the bundle file to write to.
\param w the image width to use for Fov computation
\param h the image height
*/
void loadBundle(const std::string & filePath, int w = 1920, int h = 1080);
/**
*Load a camera path generated by the camera editor / bledner plugin
*\param filePath Path to the .lookat file.
*\param w Width of the cameras to create.
*\param h Height of the cameras to create.
*/
void loadLookat(const std::string &filePath, int w = 1920, int h = 1080);
/**
*Load a camera path generated by colmap requires filename images.txt for now TODO GD; fix this
*\param filePath Path to the images.txt file; assumes that a cameras.txt is "next to" it;
*\param w Width of the cameras to create.
*\param h Height of the cameras to create.
*/
void loadColmap(const std::string &filePath, int w = 1920, int h = 1080);
/**
Save the current recording stream as a bundle file.
\param filePath Path to the bundle file to write to.
\param height the height in pixels of the camera. Used to compute focal length in mm as expected by bundle.
\param step set to a value greater than 1 to save every "step" camera in the recording stream.
*/
void saveAsBundle(const std::string & filePath, const int height, const int step = 1);
void saveAsColmap(const std::string& filePath, const int height, const int width);
/**
Save the current recording stream as a bundle file and a series of empty images for FRIBR compatibility.
\param dirPath Path to the directory to export to.
\param width the width in pixels of the camera.
\param height the height in pixels of the camera.
*/
void saveAsFRIBRBundle(const std::string & dirPath, const int width, const int height);
/**
Save the current recording stream as a lookat file.
\param filePath Path to the lookat file to write to.
*/
void saveAsLookAt(const std::string& filePath) const;
/**
\return a boolean denoting if the recorder is currently playing.
*/
bool isPlaying() const { return _playing; }
/**
\return a boolean denoting if the recorder is currently recording.
*/
bool isRecording() const { return _recording; }
/**
\return a boolean denoting if the recorder is currently asking frames to be saved.
*/
bool isSaving() const { return _saving; }
/**
\return A reference to the current stream of recorded cameras.
*/
std::vector<Camera>& cams() { return _cameras; }
/**
Updates the cameras from a vector, usefull to play already loaded path.
*/
void cams(std::vector<Camera>& cams) { _cameras = cams; }
/**
Load a path, based on file extension name. Cameras loaded into _cameras
*/
bool loadPath(const std::string& pathFileName, int w, int h);
/**
Play path for offline rendering using abstract View interface
*/
void recordOfflinePath(const std::string& outPathDir, ViewBase::Ptr view, const std::string& prefix);
/**
Save an image
*/
void setViewPath(ViewBase::Ptr view, const std::string& dataset_path) { _view = view; _dsPath = dataset_path; };
void saveImage(const std::string& outPathDir, const Camera& cam, int w, int h);
/**
* \return the interpolation speed
*/
float & speed() { return _speed; }
private:
std::string _dsPath; // path to dataset
ViewBase::Ptr _view; // view to save images
uint _pos; ///< Current camera ID for replay.
std::vector<Camera> _cameras; ///< List of recorded cameras.
bool _recording; ///< Are we currently recording.
bool _playing; ///< Are we currently playing.
bool _saving; ///< Are we saving the path as images.
std::string _savingPath; ///< Destination base path for saved images.
bool _savingVideo; ///< Are we saving the path as video.
std::string _savingVideoPath; ///< Destination base path for saved video.
float _speed; ///< Playback speed.
float _interp; ///< Current interpoaltion factor.
bool _playNoInterp; ///< Just play the cameras, make sure focal is preserved
int _ow, _oh; ///< offline output path resolution
};
///// DEFINITIONS /////
} // namespace sibr

View File

@ -0,0 +1,99 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#pragma once
# include "core/graphics/Config.hpp"
# include <iomanip>
#ifdef SIBR_OS_WINDOWS
//// Export Macro (used for creating DLLs) ////
# ifdef SIBR_STATIC_DEFINE
# define SIBR_EXPORT
# define SIBR_NO_EXPORT
# else
# ifndef SIBR_ASSETS_EXPORT
# ifdef SIBR_ASSETS_EXPORTS
/* We are building this library */
# define SIBR_ASSETS_EXPORT __declspec(dllexport)
# else
/* We are using this library */
# define SIBR_ASSETS_EXPORT __declspec(dllimport)
# endif
# endif
# ifndef SIBR_NO_EXPORT
# define SIBR_NO_EXPORT
# endif
# endif
# else
# define SIBR_ASSETS_EXPORT
# endif
namespace sibr
{
/**
* Utility that converts an integer id to a string using
* the "most used" format.
* \param id the id to convert (fi 7)
* \return the corresponding string (fi "0000007")
* \ingroup sibr_assets
*/
inline std::string imageIdToString( int id ) {
std::ostringstream oss;
oss << std::setfill('0') << std::setw(8) << id;
return oss.str();
}
/** Generate a string representation of an integer, padded with zeros.
* \param id the integer
* \return the padded string
* \note The template int value determines the padding count.
* \ingroup sibr_assets
* */
template<unsigned int N> std::string intToString(int id) {
std::ostringstream oss;
oss << std::setfill('0') << std::setw(N) << id;
return oss.str();
}
/**
* Get the default path and filename used for the proxy
* mesh.
* \param datasetPath the base path
* \return the mesh path
* \ingroup sibr_assets
*/
inline std::string getProxyFilename( const std::string& datasetPath ) {
return datasetPath + "/pmvs/models/pmvs_recon.ply";
}
/**
* Loading status for streaming.
* \todo Rename the following status into: NotLoaded, CPULoading, CPUReady, GPUReady, Failure.
* \ingroup sibr_assets
*/
namespace LoadingStatus
{
enum Enum
{
NotLoaded = 0,
InProgress,
CPUReady,
Successful,
Failure,
Count
};
} // namespace LoadingStatus
} // namespace sibr

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#pragma once
# include "core/assets/Config.hpp"
namespace sibr
{
/** General file loading interface.
\ingroup sibr_assets
*/
class SIBR_ASSETS_EXPORT IFileLoader
{
public:
/** Destructor. */
virtual ~IFileLoader( void ) { }
/** Load the file content from disk.
\param filename path to the file
\param verbose display information
\return a boolean denoting success
*/
virtual bool load( const std::string& filename, bool verbose = true ) = 0;
};
} // namespace sibr

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
# include <boost/filesystem.hpp>
# include <fstream>
# include "core/assets/ImageListFile.hpp"
namespace sibr
{
bool ImageListFile::load( const std::string& filename, bool verbose )
{
std::fstream file(filename, std::ios::in);
_infos.clear();
if (file)
{
while (file.eof() == false)
{
Infos i;
file >> i.filename >> i.width >> i.height;
if (i.filename.size())
_infos.emplace_back(std::move(i));
}
// store basename
boost::filesystem::path path(filename);
_basename = path.parent_path().string();
if( verbose )
SIBR_FLOG << "'"<< filename <<"' successfully loaded." << std::endl;
return true;
}
else
SIBR_WRG << "file not found: '"<<filename<<"'"<<std::endl;
return false;
}
} // namespace sibr

View File

@ -0,0 +1,120 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#pragma once
# include "core/graphics/Image.hpp"
# include "core/assets/Config.hpp"
# include "core/assets/IFileLoader.hpp"
# include "core/assets/ActiveImageFile.hpp"
namespace sibr
{
/** Represents a list of input images.
\ingroup sibr_assets
*/
class SIBR_ASSETS_EXPORT ImageListFile : public IFileLoader
{
public:
/** Image infos. */
struct Infos
{
std::string filename; ///< image filename.
uint camId; ///< Associated camera ID.
uint width; ///< Image width.
uint height; ///< Image height.
};
public:
/** Load the list file from disk.
\param filename path to the list file
\param verbose display information
\return a boolean denoting success
*/
bool load( const std::string& filename , bool verbose = true);
/** Images information.
* \return each image infos.
*/
const std::vector<Infos>& infos( void ) const { return _infos; }
/** Image absename.
*\return the basename
**/
const std::string& basename( void ) const { return _basename; }
/** Load images.
\return the loaded images
*/
template <class TImage>
std::vector<TImage> loadImages( void ) const;
/** Load images, applying an active images file filter.
\param ac the active list file
\return the loaded images
\note Non-active images are present but empty.
*/
template <class TImage>
std::vector<TImage> loadImages( const ActiveImageFile& ac) const;
private:
std::vector<Infos> _infos; ///< Image infos.
std::string _basename; ///< Root name.
};
///// DEFINITIONS /////
template <class TImage>
std::vector<TImage> ImageListFile::loadImages( const ActiveImageFile& ac ) const {
std::vector<TImage> out;
SIBR_LOG << "[ImageListFile] loading images";
out.resize(_infos.size());
if (_infos.empty() == false)
{
#pragma omp parallel for
for (int i = 0; i < _infos.size(); ++i)
if( ac.active()[i] )
out[i].load(_basename + "/" + _infos.at(i).filename, false);
}
else
SIBR_WRG << "cannot load images (ImageListFile is empty. Did you use ImageListFile::load(...) before ?";
std::cout << std::endl;
return out;
}
template <class TImage>
std::vector<TImage> ImageListFile::loadImages( void ) const {
std::vector<TImage> out;
std::cerr << "[ImageListFile] loading images";
out.resize(_infos.size());
if (_infos.empty() == false)
{
#pragma omp parallel for
for (int i = 0; i < _infos.size(); ++i)
out[i].load(_basename + "/" + _infos.at(i).filename, false);
}
else
SIBR_WRG << "cannot load images (ImageListFile is empty. Did you use ImageListFile::load(...) before ?";
return out;
}
} // namespace sibr

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,333 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#pragma once
#include "core/graphics/Config.hpp"
#include "core/graphics/Camera.hpp"
#include "core/assets/Config.hpp"
namespace sibr
{
/** Input camera parameters. Inherits all basic camera functionality from Camera
* and adds functions for depth samples from multi-view stereo.
*
* \sa Camera, NovelCamera
* \ingroup sibr_assets
*/
class SIBR_ASSETS_EXPORT InputCamera : public Camera
{
public:
typedef std::shared_ptr<InputCamera> Ptr;
/** Near/far plane representation. */
struct Z {
/** Constructor. */
Z() {}
/** Constructor.
* \warning Ordering of the values is swapped.
* \param f far plane
* \param n near plane
*/
Z(float f, float n) : far(f), near(n) {}
float far = 0.0f; ///< Far plane.
float near = 0.0f; ///< Near plane.
};
/** Default constructor. */
InputCamera() :
_focal(0.f), _k1(0.f), _k2(0.f), _w(0), _h(0), _id(0), _active(true)
{ }
/** Partial constructor
* \param f focal length in mm
* \param k1 first distortion parameter
* \param k2 second distortion parameter
* \param w width of input image
* \param h height of input image
* \param id ID of input image
*/
InputCamera(float f, float k1, float k2, int w, int h, int id);
InputCamera(float fy, float fx, float k1, float k2, int w, int h, int id);
/** Constructor, initialize the input camera.
* \param id ID of input image
* \param w width of input image
* \param h height of input image
* \param position camera position
* \param rotation camera rotation
* \param focal focal length in mm
* \param k1 first distortion parameter
* \param k2 second distortion parameter
* \param active input image active or not
*/
InputCamera(int id, int w, int h, sibr::Vector3f & position, sibr::Matrix3f & rotation, float focal, float k1, float k2, bool active);
/** Constructor, initialize the input camera.
* \param id ID of input image
* \param w width of input image
* \param h height of input image
* \param m camera parameters resad from Bundler output file
* \param active input image active or not
* \param fovFromFocal: if true, compute fov from focal else use "standard sibr" convention
* \sa Bundler: http://phototour.cs.washington.edu/bundler/
* \deprecated Avoid using this legacy constructor.
*/
InputCamera(int id, int w, int h, sibr::Matrix4f m, bool active);
/** Constructor from a basic Camera.
* \param c camera
* \param w image width
* \param h image height
*/
InputCamera(const Camera& c, int w, int h);
/** Copy constructor. */
InputCamera(const InputCamera&) = default;
/** Move constructor. */
InputCamera(InputCamera&&) = default;
/** Copy operator. */
InputCamera& operator =(const InputCamera&) = default;
/** Move operator. */
InputCamera& operator =(InputCamera&&) = default;
/** Input image width
* \return width of input image
*/
uint w(void) const;
/** Input image height
* \return height of input image
*/
uint h(void) const;
/** Check if the input camera active or inactive,
* camera is completely ignored if set to inactive.
* \return true if active, false otherwise
*/
bool isActive(void) const;
/** Set camera active status
*\param active if true, camera is in use
*/
void setActive(bool active) { _active = active ; }
/** \return the image name */
inline const std::string& name(void) const { return _name; }
/** Set camera name
* \param s the new name
*/
inline void name( const std::string& s ) { _name = s; }
/** Update image dimensions. Calls \a update() after changing image width and height
* \param w image width
* \param h image height
*/
void size( uint w, uint h );
/** \return the camera id */
uint id() const { return _id; }
/** Project a world space point into screen space.
*\param pt 3d world point
*\return screen space position and depth, in (0,w)x(0,h)x(0,1)
*/
Vector3f projectScreen( const Vector3f& pt ) const;
/** \return the focal length */
float focal() const;
/** \return the focal length x */
float focalx() const;
/** set the focal length ; to be used with caution; focal is usually inferred from the fov*/
void setFocal(float focal) { _focal = focal; }
/** \return the k1 distorsion parameter */
float k1() const;
/** \return the k2 distorsion parameter */
float k2() const;
/** Back-project pixel coordinates and depth.
* \param pixelPos pixel coordinates p[0],p[1] in [0,w-1]x[0,h-1]
* \param depth d in [-1,1]
* \returns 3D world point
*/
Vector3f unprojectImgSpaceInvertY( const sibr::Vector2i & pixelPos, const float & depth ) const;
/** Project 3D point using perspective projection.
* \param point3d 3D point
* \returns pixel coordinates in [0,w-1]x[0,h-1] and depth d in [-1,1]
*/
Vector3f projectImgSpaceInvertY( const Vector3f& point3d ) const;
/** Load from internal binary representation.
* \param filename file path
* \return success boolean
*/
bool loadFromBinary( const std::string& filename );
/** Save to disk using internal binary representation.
* \param filename file path
*/
void saveToBinary( const std::string& filename ) const;
/** Save a file in the IBR TopView format.
* \param outfile the destination file
*/
void writeToFile(std::ostream& outfile) const;
/** Load a file in the IBR TopView format.
* \param infile the input file
*/
void readFromFile(std::istream& infile);
/** Conver to Bundle string.
* \param negativeZ should the Z axis be flipped
* \recomputeFocal recompute the focal or just set
* \return a string that can be used to create a bundle file from this camera
*/
std::string toBundleString(bool negativeZ = false, bool recomputeFocal = true) const;
/** \return A vector of four Vector2i corresponding to the pixels at the camera corners
*/
std::vector<sibr::Vector2i> getImageCorners() const;
/** Return a new camera resized to the specified height
*/
sibr::InputCamera resizedH(int h) const;
/** Return a new camera resized to the specified height
*/
sibr::InputCamera resizedW(int w) const;
/** Return the lookat string of the camera
*/
std::string lookatString() const;
/** save a vector of cameras as lookat
*/
static void saveAsLookat(const std::vector<InputCamera::Ptr> & cams, const std::string & fileName);
/** save a vector of cameras sizes to a file to be read by mitsuba rendering script
*/
static void saveImageSizes(const std::vector<InputCamera::Ptr> & cams, const std::string & fileName);
/** Save a vector of cameras as a bundle file.
*\param cams the cameras
* \param fileName output bundle file path
* \param negativeZ should the Z axis be flipped
* \param exportImages should empty images with the proper dimensions be saved in a visualize subdirectory
* \param oldFocal: recompute focal, else assign that of camera TODO: fix this
*/
static void saveAsBundle(const std::vector<InputCamera::Ptr> & cams, const std::string & fileName, bool negativeZ = false, bool exportImages = false, bool recomputeFocal=true);
/** Save a vector of cameras as a lookat file.
*\param cams the cameras
* \param fileName output lookat file path
*/
static void saveAsLookat(const std::vector<sibr::Camera> & cams, const std::string & fileName);
/** Load cameras from a bundler file.
*\param datasetPath path to the root of the dataset, should contain bundle.out, list_images.txt and optionally clipping_planes.txt
* \param zNear default near-plane value to use if the clipping_planes.txt file doesn't exist
* \param zFar default far-plane value to use if the clipping_planes.txt file doesn't exist
* \param bundleName name of the bundle file
* \param listName name of the list images file
* \returns the loaded cameras
*/
static std::vector<InputCamera::Ptr> load( const std::string& datasetPath, float zNear = 0.01f, float zFar = 1000.0f, const std::string & bundleName = "bundle.out", const std::string & listName = "list_images.txt");
/** Load cameras from a NVM file.
*\param nvmPath path to the NVM file
* \param zNear default near-plane value to use
* \param zFar default far-plane value to use.
* \param wh will contain the sizes of each camera image
* \returns the loaded cameras
*/
static std::vector<InputCamera::Ptr> loadNVM(const std::string& nvmPath, float zNear = 0.01f, float zFar = 1000.0f, std::vector<sibr::Vector2u> wh = std::vector<sibr::Vector2u>());
/** Load cameras from a .lookat file generated by our Blender plugin.
* \param lookatPath path to the lookAt file
* \param wh indicative size of each camera image
* \param zNear default near-plane value to use
* \param zFar default far-plane value to use.
* \returns the loaded cameras
*/
static std::vector<InputCamera::Ptr> loadLookat(const std::string& lookatPath, const std::vector<sibr::Vector2u>& wh= std::vector<sibr::Vector2u>(),float zNear= -1, float zFar= -1);
static std::vector<InputCamera::Ptr> InputCamera::loadTransform(const std::string& transformPath, int w, int h, std::string extension, const float zNear = 0.01f, const float zFar = 1000.0f, const int offset = 0, const int fovXfovYFlag = 0);
/** Load cameras from a Colmap txt file.
* \param colmapSparsePath path to the Colmap sparse directory, should contains cameras.txt and images.txt
* \param zNear default near-plane value to use
* \param zFar default far-plane value to use.
* \param fovXfovYFlag should we use two dimensional fov.
* \returns the loaded cameras
* \note the camera frame is internally transformed to be consistent with fribr and RC.
*/
static std::vector<InputCamera::Ptr> loadColmap(const std::string& colmapSparsePath, const float zNear = 0.01f, const float zFar = 1000.0f, const int fovXfovYFlag = 0);
static std::vector<InputCamera::Ptr> loadColmapBin(const std::string& colmapSparsePath, const float zNear = 0.01f, const float zFar = 1000.0f, const int fovXfovYFlag = 0);
static std::vector<InputCamera::Ptr> loadJSON(const std::string& jsonPath, const float zNear = 0.01f, const float zFar = 1000.0f);
/** Load cameras from a bundle file.
* \param bundlerPath path to the bundle file.
* \param zNear default near-plane value to use
* \param zFar default far-plane value to use.
* \param listImagePath path to the list_images.txt file. Will default to a file in the same directory as the bundle.out file.
* \param path: if this is a path, then you can load more images that those defined in the list_images file of the datset; TODO: possibly should require a list_images.txt for the path
* \returns the loaded cameras
*/
static std::vector<InputCamera::Ptr> loadBundle(const std::string& bundlerPath, float zNear = 0.01f, float zFar = 1000.0f, const std::string & listImagePath = "", bool path = false);
/** Load cameras from a bundle file.
* \param bundlerPath path to the bundle file.
* \param zNear default near-plane value to use
* \param zFar default far-plane value to use.
* \param listImagePath path to the list_images.txt file. Will default to a file in the same directory as the bundle.out file.
* \returns the loaded cameras
*/
static std::vector<InputCamera::Ptr> loadBundleFRIBR(const std::string& bundlerPath, float zNear = 0.01f, float zFar = 1000.0f, const std::string & listImagePath = "");
/** Load cameras from a Meshrrom SFM cameras.sfm txt file.
* \param meshroomSFMPath path to the Meshroom StructureFromMotion/{dd63cea98bda0e3b53ec76f17b0753b3e4dde589}/ directory, should contains cameras.sfm
* \param zNear default near-plane value to use
* \param zFar default far-plane value to use.
* \returns the loaded cameras
* \note the camera frame is internally transformed to be consistent with fribr and RC.
*/
static std::vector<InputCamera::Ptr> loadMeshroom(const std::string& meshroomSFMPath, const float zNear = 0.01f, const float zFar = 1000.0f);
uint _id; ///< Input camera id
protected:
float _focal; ///< focal length
float _focalx; ///< focal length x, if there is one (colmap typically; -1 by default use with caution)
float _k1; ///< K1 bundler distorsion parameter
float _k2; ///< K2 bundler dist parameter
uint _w; ///< Image width
uint _h; ///< Image height
std::string _name; ///< Input image name
bool _active; ///< is the camera currently in use.
};
} // namespace sibr

View File

@ -0,0 +1,117 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#include <iostream>
#include <fstream>
#include <algorithm>
#include <sstream>
#include "core/assets/Resources.hpp"
/// \todo TODO: If you care about security (did someone want to hack/use your app
/// to hide a virus/retrieve informations from this compiled code), comment
/// the following line and resolve warnings by finding new safe-functions.
#pragma warning(disable:4996) // affect this .cpp only
namespace sibr
{
Resources* Resources::_instance = NULL;
Resources* Resources::Instance()
{
if (_instance == 0)
_instance = new Resources;
return _instance;
}
Resources::Resources()
{
_rscPaths.push_back(sibr::getInstallDirectory());
std::ifstream rscFile(sibr::getInstallDirectory() + "/ibr_resources.ini");
if(rscFile.good())
{
for(std::string line; safeGetline(rscFile, line); )
{
_rscPaths.push_back(line);
}
}
else {
std::ifstream rscFile2(sibr::getInstallDirectory() + "/bin/ibr_resources.ini");
for(std::string line; safeGetline(rscFile2, line); )
_rscPaths.push_back(line);
}
/// \todo WIP: used in prevision to load plugins (TODO: test under linux)
std::ifstream pathFile(sibr::getInstallDirectory() + "/ibr_paths.ini");
if(pathFile.good())
{
for(std::string line; safeGetline(pathFile, line); )
{
std::string name = line.substr(0, line.find("="));
std::string value = line.substr(line.find("=")+1, line.length());
char* curEnv = getenv(name.c_str());
std::string currentEnv;
if(curEnv!=NULL)
currentEnv = std::string(curEnv);
#ifdef SIBR_OS_WINDOWS
std::replace(value.begin(), value.end(), '/', '\\'); // linux to windows path
char delimiter = ';';
#else
std::replace(value.begin(), value.end(), '\\', '/'); // windows to linux path
char delimiter = ':';
#endif
std::stringstream ss;
ss << delimiter;
if(!currentEnv.empty())
if (currentEnv.at(currentEnv.length()-1) != delimiter)
currentEnv.append(ss.str());
line = name + "=" + currentEnv + value;
putenv(const_cast<char*>(line.c_str()));
std::cout<<"[Resources] env: "<<name<<"="<<getenv(name.c_str())<<std::endl;
}
}
}
Resources::~Resources()
{
}
std::string Resources::getResourceFilePathName(std::string const & filename, bool & success)
{
// we assume the first element of _rscPaths if the current dir
// Weird bug -- GD: I have no idea why, but if I dont call this the paths dont work under linux
std::string installdir = sibr::getInstallDirectory();
// someone gave us the correct full path
std::ifstream rscFileTest(filename);
if (success = rscFileTest.good())
return filename;
for(std::string rscPath : _rscPaths)
{
std::string filePathName = sibr::getInstallDirectory() + "/" + rscPath + "/" + filename;
std::ifstream rscFile(filePathName);
if (success = rscFile.good()) {
return filePathName;
}
}
return filename;
}
std::string Resources::getResourceFilePathName(std::string const & filename)
{
bool success = false;
return getResourceFilePathName(filename,success);
}
} // namespace sibr

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#pragma once
#include "core/assets/Config.hpp"
#include <vector>
#include <string>
namespace sibr
{
/** Singleton used to store a list of plausible path to look for (based on the ibr_resources.ini)
\ingroup sibr_assets
*/
class SIBR_ASSETS_EXPORT Resources
{
public:
/// Our singleton
static Resources* Instance();
protected:
/// Constructor.
Resources();
/// Destructor
virtual ~Resources();
public:
/** Look for the filename into plausible resource paths.
* \param filename file name
* \param success was the file found in the registered locations
* \return the full file path
*/
std::string getResourceFilePathName(std::string const & filename, bool & success);
/** Look for the filename into plausible resource paths.
* \param filename file name
* \return the full file path
*/
std::string getResourceFilePathName(std::string const & filename);
protected:
std::vector<std::string> _rscPaths; ///< List of directories to check into.
static Resources * _instance; ///< Singleton.
};
} // namespace sibr

View File

@ -0,0 +1,276 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#include "UVUnwrapper.hpp"
#include <core/system/SimpleTimer.hpp>
#include <core/graphics/Utils.hpp>
#include "xatlas.h"
int printCallback(const char * format, ...) {
va_list args;
va_start(args, format);
std::cout << "\r";
const int res = vprintf(format, args);
va_end(args);
return res;
}
bool progressCallback(xatlas::ProgressCategory category, int progress, void *userData){
std::cout << "\r\t" << xatlas::StringForEnum(category) << "[" << std::flush;
for (int i = 0; i < 10; i++)
std::cout << (progress / ((i + 1) * 10) ? "*" : " ");
std::cout << "] " << progress << "%" << std::flush;
if(progress == 100) {
std::cout << std::endl;
}
return true;
}
void setPixel(uint8_t *dest, int destWidth, int x, int y, const sibr::Vector3ub & color){
uint8_t *pixel = &dest[x * 3 + y * (destWidth * 3)];
pixel[0] = color[0];
pixel[1] = color[1];
pixel[2] = color[2];
}
// https://github.com/miloyip/line/blob/master/line_bresenham.c
// License: public domain.
static void rasterizeLine(uint8_t *dest, int destWidth, const int *p1, const int *p2, const sibr::Vector3ub & color)
{
const int dx = abs(p2[0] - p1[0]), sx = p1[0] < p2[0] ? 1 : -1;
const int dy = abs(p2[1] - p1[1]), sy = p1[1] < p2[1] ? 1 : -1;
int err = (dx > dy ? dx : -dy) / 2;
int current[2];
current[0] = p1[0];
current[1] = p1[1];
while(setPixel(dest, destWidth, current[0], current[1], color), current[0] != p2[0] || current[1] != p2[1]){
const int e2 = err;
if (e2 > -dx) { err -= dy; current[0] += sx; }
if (e2 < dy) { err += dx; current[1] += sy; }
}
}
/*
https://github.com/ssloy/tinyrenderer/wiki/Lesson-2:-Triangle-rasterization-and-back-face-culling
Copyright Dmitry V. Sokolov
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
void rasterizeTriangle(uint8_t *dest, int destWidth, const int *t0, const int *t1, const int *t2, const sibr::Vector3ub & color)
{
if (t0[1] > t1[1]) std::swap(t0, t1);
if (t0[1] > t2[1]) std::swap(t0, t2);
if (t1[1] > t2[1]) std::swap(t1, t2);
const int total_height = t2[1] - t0[1];
for (int i = 0; i < total_height; i++) {
const bool second_half = i > t1[1] - t0[1] || t1[1] == t0[1];
const int segment_height = second_half ? t2[1] - t1[1] : t1[1] - t0[1];
const float alpha = (float)i / total_height;
const float beta = (float)(i - (second_half ? t1[1] - t0[1] : 0)) / float(segment_height);
int A[2], B[2];
for (int j = 0; j < 2; j++) {
A[j] = int(t0[j] + (t2[j] - t0[j]) * alpha);
B[j] = int(second_half ? t1[j] + (t2[j] - t1[j]) * beta : t0[j] + (t1[j] - t0[j]) * beta);
}
if (A[0] > B[0]) std::swap(A, B);
for (int j = A[0]; j <= B[0]; j++) {
setPixel(dest, destWidth, j, t0[1] + i, color);
}
}
}
using namespace sibr;
UVUnwrapper::UVUnwrapper(const sibr::Mesh& mesh, unsigned int res) : _mesh(mesh) {
_size = res;
// Create empty atlas.
xatlas::SetPrint(printCallback, false);
_atlas = xatlas::Create();
xatlas::SetProgressCallback(_atlas, progressCallback, nullptr);
// Add the mesh to the atlas.
SIBR_LOG << "[UVMapper] Adding one mesh with " << mesh.vertices().size() << " vertices and " << mesh.triangles().size() << " triangles." << std::endl;
// For now consider everything as one mesh. Splitting in components *might* help.
xatlas::MeshDecl meshDecl;
meshDecl.vertexCount = uint32_t(mesh.vertices().size());
meshDecl.vertexPositionData = mesh.vertexArray();
meshDecl.vertexPositionStride = sizeof(sibr::Vector3f);
if (mesh.hasNormals()) {
meshDecl.vertexNormalData = mesh.normalArray();
meshDecl.vertexNormalStride = sizeof(sibr::Vector3f);
}
// UV can be used as a hint.
if (mesh.hasTexCoords()) {
meshDecl.vertexUvData = mesh.texCoordArray();
meshDecl.vertexUvStride = sizeof(sibr::Vector2f);
}
meshDecl.indexCount = uint32_t(mesh.triangles().size() * 3);
meshDecl.indexData = mesh.triangleArray();
meshDecl.indexFormat = xatlas::IndexFormat::UInt32;
const xatlas::AddMeshError error = xatlas::AddMesh(_atlas, meshDecl, 1);
if (error != xatlas::AddMeshError::Success) {
xatlas::Destroy(_atlas);
SIBR_ERR << "\r[UVMapper] Error adding mesh: " << xatlas::StringForEnum(error) << std::endl;
}
// Not necessary. Only called here so geometry totals are printed after the AddMesh progress indicator
xatlas::AddMeshJoin(_atlas);
}
sibr::Mesh::Ptr UVUnwrapper::unwrap() {
// Generate atlas.
SIBR_LOG << "[UVMapper] Generating atlas.." << std::endl;
xatlas::ChartOptions chartOptions = xatlas::ChartOptions();
xatlas::PackOptions packOptions = xatlas::PackOptions();
packOptions.bruteForce = false;
packOptions.resolution = uint32_t(_size);
Timer timer;
timer.tic();
xatlas::Generate(_atlas, chartOptions, packOptions);
SIBR_LOG << "[UVMapper] Generation took: " << timer.deltaTimeFromLastTic<Timer::s>() << "s." << std::endl;
SIBR_LOG << "[UVMapper] Output resolution: " << _atlas->width << "x" << _atlas->height << std::endl;
SIBR_LOG << "[UVMapper] Generated " << _atlas->chartCount << " charts, " << _atlas->atlasCount << " atlases." << std::endl;
for (uint32_t i = 0; i < _atlas->atlasCount; i++) {
SIBR_LOG << "[UVMapper] \tAtlas " << i << ": utilisation: " << _atlas->utilization[i] * 100.0f << "%" << std::endl;
}
uint32_t totalVertices = 0;
uint32_t totalFaces = 0;
for (uint32_t i = 0; i < _atlas->meshCount; i++) {
const xatlas::Mesh& xmesh = _atlas->meshes[i];
totalVertices += xmesh.vertexCount;
totalFaces += xmesh.indexCount / 3;
}
SIBR_LOG << "[UVMapper] Output geometry data: " << totalVertices << " vertices, " << totalFaces << " triangles." << std::endl;
// Write meshes.
uint32_t firstVertex = 0;
std::vector<sibr::Vector3f> positions;
std::vector<sibr::Vector3f> normals;
std::vector<sibr::Vector2f> texcoords;
std::vector<sibr::Vector3f> colors;
std::vector<sibr::Vector3u> triangles;
// We could preallocate and paraellize if needed.
for (uint32_t i = 0; i < _atlas->meshCount; i++) {
const xatlas::Mesh& xmesh = _atlas->meshes[i];
for (uint32_t v = 0; v < xmesh.vertexCount; v++) {
const xatlas::Vertex& vertex = xmesh.vertexArray[v];
const sibr::Vector3f& pos = _mesh.vertices()[vertex.xref];
positions.emplace_back(pos);
if (_mesh.hasNormals()) {
const sibr::Vector3f& n = _mesh.normals()[vertex.xref];
normals.emplace_back(n);
}
if (_mesh.hasColors()) {
const sibr::Vector3f& c = _mesh.colors()[vertex.xref];
colors.emplace_back(c);
}
_mapping.emplace_back(vertex.xref);
texcoords.emplace_back(vertex.uv[0] / float(_atlas->width), vertex.uv[1] / float(_atlas->height));
}
for (uint32_t f = 0; f < xmesh.indexCount; f += 3) {
const uint32_t i0 = firstVertex + xmesh.indexArray[f + 0];
const uint32_t i1 = firstVertex + xmesh.indexArray[f + 1];
const uint32_t i2 = firstVertex + xmesh.indexArray[f + 2];
triangles.emplace_back(i0, i1, i2);
}
firstVertex += xmesh.vertexCount;
}
Mesh::Ptr finalMesh(new Mesh(false));
finalMesh->vertices(positions);
finalMesh->normals(normals);
finalMesh->texCoords(texcoords);
finalMesh->colors(colors);
finalMesh->triangles(triangles);
SIBR_LOG << "[UVMapper] Done." << std::endl;
return finalMesh;
}
const std::vector<uint>& UVUnwrapper::mapping() const
{
return _mapping;
}
std::vector<ImageRGB::Ptr> UVUnwrapper::atlasVisualization() const {
if(!_atlas || _atlas->width <= 0 || _atlas->height <= 0) {
SIBR_WRG << "[UVMapper] Atlas has not been created/processed." << std::endl;
return {};
}
SIBR_LOG << "[UVMapper] Rasterizing result maps..." << std::endl;
// Rasterize unwrapped meshes.
// \todo port to SIBR image API.
std::vector<uint8_t> outputChartsImage;
const uint32_t imageDataSize = _atlas->width * _atlas->height * 3;
outputChartsImage.resize(_atlas->atlasCount * imageDataSize);
for (uint32_t i = 0; i < _atlas->meshCount; i++) {
const xatlas::Mesh &xmesh = _atlas->meshes[i];
const sibr::Vector3ub white = { 255, 255, 255 };
// Rasterize mesh charts.
for (uint32_t j = 0; j < xmesh.chartCount; j++) {
const xatlas::Chart *chart = &xmesh.chartArray[j];
const sibr::Vector3ub color = sibr::randomColor<unsigned char>();
for (uint32_t k = 0; k < chart->faceCount; k++) {
int verts[3][2];
for (int l = 0; l < 3; l++) {
const xatlas::Vertex &v = xmesh.vertexArray[xmesh.indexArray[chart->faceArray[k] * 3 + l]];
verts[l][0] = int(v.uv[0]);
verts[l][1] = int(v.uv[1]);
}
uint8_t *imageData = &outputChartsImage[chart->atlasIndex * imageDataSize];
rasterizeTriangle(imageData, _atlas->width, verts[0], verts[1], verts[2], color);
rasterizeLine(imageData, _atlas->width, verts[0], verts[1], white);
rasterizeLine(imageData, _atlas->width, verts[1], verts[2], white);
rasterizeLine(imageData, _atlas->width, verts[2], verts[0], white);
}
}
}
// Convert raw vectors to images.
std::vector<ImageRGB::Ptr> views(_atlas->meshCount);
for (uint32_t i = 0; i < _atlas->meshCount; i++) {
views[i].reset(new ImageRGB(_atlas->width, _atlas->height));
uint8_t *imageData = &outputChartsImage[i * imageDataSize];
#pragma omp parallel for
for(int y = 0; y < int(_atlas->height); ++y) {
for(int x = 0; x < int(_atlas->width); ++x) {
const size_t baseId = (y * _atlas->width + x)*3;
for(int j = 0; j < 3; ++j) {
views[i](x, y)[j] = imageData[baseId + j];
}
}
}
views[i]->flipH();
}
return views;
}
UVUnwrapper::~UVUnwrapper() {
xatlas::Destroy(_atlas);
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2020, Inria
* GRAPHDECO research group, https://team.inria.fr/graphdeco
* All rights reserved.
*
* This software is free for non-commercial, research and evaluation use
* under the terms of the LICENSE.md file.
*
* For inquiries contact sibr@inria.fr and/or George.Drettakis@inria.fr
*/
#pragma once
#include <core/assets/Config.hpp>
#include <core/graphics/Mesh.hpp>
namespace xatlas {
struct Atlas;
}
namespace sibr
{
/** Unwraps a mesh onto a plane, generating texture coordinates for each vertex.
* Internaly relies on xatlas for unwrapping.
\ingroup sibr_assets
*/
class SIBR_ASSETS_EXPORT UVUnwrapper {
public:
/** Constructor.
*\param mesh the mesh to unwrap, if UVs are already present they will be used as a guide
*\param res the target texture width, will determine UV accuracy
*/
UVUnwrapper(const sibr::Mesh& mesh, unsigned int res);
/** Unwrap the mesh, return a copy with UV coordinates. Note that some vertices might be duplicated if they are assigned different UVs in two faces.
* \return the unwrapped mesh
*/
sibr::Mesh::Ptr unwrap();
/** For each vertex of the unwrapped mesh, the mapping give the index of the corresponding vertex in the input mesh.
* \return a reference to the mapping vector
*/
const std::vector<uint> & mapping() const;
/** Generate debug visualization by rasterizing the meshes in texture space.
* \return a set of images, one per atlas
*/
std::vector<ImageRGB::Ptr> atlasVisualization() const;
/// Destructor.
~UVUnwrapper();
private:
const sibr::Mesh& _mesh; ///< Unwrapped mesh.
unsigned int _size; ///< Width of the atlas, detemrine the accuracy of the estimated UVs.
xatlas::Atlas* _atlas; ///< Atlas object.
std::vector<uint> _mapping; ///< Mapping from the new vertices to the old (some might be duplicated with different UV values).
};
}

Some files were not shown because too many files have changed in this diff Show More