Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Headless rendering #273

Merged
merged 23 commits into from
Apr 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions docs/tutorial/Advanced/headless_rendering.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
.. _headless_rendering:

Headless rendering
-------------------------------------

This tutorial introduces how to render and save images from terminal without any display device.

.. Note:: This feature is experimental. Only tested with Ubuntu 16.04 environment.

Install OSMesa
````````````````````````

To generate a headless context, it is necessary to install `OSMesa <https://www.mesa3d.org/osmesa.html>`_.

.. code-block:: shell

$ sudo apt-get install libosmesa6-dev

Otherwise, recent version of OSMesa can be built from source.

.. code-block:: shell

# download OSMesa 2018 release
$ cd
$ wget ftp://ftp.freedesktop.org/pub/mesa/mesa-18.0.0.tar.gz
$ tar xf mesa-18.0.0.tar.gz
$ cd mesa-18.0.0/

# configure compile option and build
$ ./configure --enable-osmesa --disable-driglx-direct --disable-gbm --enable-dri --with-gallium-drivers=swrast
$ make

# add OSMesa to local path.
$ export PATH=$PATH:~/mesa-18.0.0

.. _install_virtualenv:

Install virtualenv
````````````````````````

The next step is to make a virtual environment for Python.

.. code-block:: shell

$ sudo apt-get install virtualenv python-pip
$ virtualenv -p /usr/bin/python3 py3env
$ source py3env/bin/activate
(py3env) $ pip install numpy matplotlib

This script installs and activates ``py3env``. Necessary modules, ``numpy`` and ``matplotlib`` are installed on ``py3env``.

.. Error:: Anaconda users are recommended to use this configuration as ``conda install matplotlib`` installs additional modules that is not based on OSMesa. This will make **segmentation fault error** at the runtime.


Build Open3D with OSMesa
````````````````````````

Let's move to build folder.

.. code-block:: shell

(py3env) $ cd ~/Open3D/
(py3env) $ mkdir build && cd build

In the next step, there are two cmake flags need to be specified.

- ``-DOpen3D_HEADLESS_RENDERING=ON``: this flag informs glew and glfw should use **OSMesa**.
- ``-DOpen3D_USE_NATIVE_DEPENDENCY_BUILD=OFF``: note that headless rendering is only working with **glew 2.1** and **glfw 3.3-dev** version. In most of the case, these versions are not installed in vanilla Ubuntu systems. Instead of using naive build, this flag lets Open3D build glew 2.1 and glfw 3.3-dev from source.

As a result, the cmake command is the following

.. code-block:: shell

(py3env) $ cmake -DOpen3D_HEADLESS_RENDERING=ON \
-DOpen3D_USE_NATIVE_DEPENDENCY_BUILD=OFF \
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
../src

Note that ``-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3`` is the same path what was used for :ref:`install_virtualenv`.

If cmake successfully generates makefiles, build Open3D.

.. code-block:: shell

(py3env) $ make # or make -j in multi-core machine



Test headless rendering
````````````````````````

As a final step, test a python script that saves depth and surface normal sequences.

.. code-block:: shell

(py3env) $ cd ~/Open3D/build/lib/Tutorial/Advanced/
(py3env) $ python headless_rendering.py

This should print the following:

.. code-block:: shell

Capture image 00000
Capture image 00001
Capture image 00002
Capture image 00003
Capture image 00004
Capture image 00005
:
Capture image 00030

Rendered images are at ~/Open3D/build/lib/TestData/depth and image folder.

.. Note:: ``headless_rendering.py`` saves png files. This may take some time. Try tweak the script for your purpose.

.. Error:: If glew and glfw did not correctly linked with OSMesa, it may crash with following error. **GLFW Error: X11: The DISPLAY environment variable is missing. Failed to initialize GLFW**
1 change: 1 addition & 0 deletions docs/tutorial/Advanced/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Advanced
rgbd_integration
customized_visualization
interactive_visualization
headless_rendering
48 changes: 48 additions & 0 deletions src/CMake/FindOSMesa.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Try to find Mesa off-screen library and include dir.
# Once done this will define
#
# OSMESA_FOUND - true if OSMesa has been found
# OSMESA_INCLUDE_DIR - where the GL/osmesa.h can be found
# OSMESA_LIBRARY - Link this to use OSMesa
#set(OSMESA_ROOT "/home/syncle/mesa-18.0.0/")

if(NOT OSMESA_INCLUDE_DIR)

# If we have a root defined look there first
if(OSMESA_ROOT)
find_path(OSMESA_INCLUDE_DIR GL/osmesa.h PATHS ${OSMESA_ROOT}/include
NO_DEFAULT_PATH
)
endif()

if(NOT OSMESA_INCLUDE_DIR)
find_path(OSMESA_INCLUDE_DIR GL/osmesa.h PATHS
/usr/openwin/share/include
/opt/graphics/OpenGL/include
)
endif()
endif()

# This may be left blank if OSMesa symbols are included
# in the main Mesa library
if(NOT OSMESA_LIBRARY)
# If we have a root defined look there first
if(OSMESA_ROOT)
find_library(OSMESA_LIBRARY NAMES OSMesa OSMesa16 OSMesa32 PATHS ${OSMESA_ROOT}/lib
NO_DEFAULT_PATH
)
endif()

if(NOT OSMESA_LIBRARY)
find_library(OSMESA_LIBRARY NAMES OSMesa OSMesa16 OSMesa32 PATHS
/opt/graphics/OpenGL/lib
/usr/openwin/lib
)
endif()
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OSMesa DEFAULT_MSG OSMESA_LIBRARY OSMESA_INCLUDE_DIR)

mark_as_advanced(OSMESA_INCLUDE_DIR OSMESA_LIBRARY)

6 changes: 1 addition & 5 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ option(Open3D_BUILD_PYTHON_BINDING "Build Python binding for Open3D" ON)
option(Open3D_BUILD_PYTHON_BINDING_TESTS "Copy test files for Open3D Python binding" ON)
option(Open3D_BUILD_PYTHON_BINDING_TUTORIALS "Copy tutorial files for Open3D Python binding" ON)
option(Open3D_USE_NATIVE_DEPENDENCY_BUILD "Prioritize using native dependency build" ON)
option(Open3D_HEADLESS_RENDERING "Use OSMesa for headless rendering" OFF)

# default built type
if(NOT CMAKE_BUILD_TYPE)
Expand Down Expand Up @@ -122,11 +123,6 @@ if(EXISTS "${Open3D_SOURCE_DIR}/Experimental/CMakeLists.txt")
add_subdirectory(Experimental)
endif(EXISTS "${Open3D_SOURCE_DIR}/Experimental/CMakeLists.txt")

if(EXISTS "${Open3D_SOURCE_DIR}/Sandbox/CMakeLists.txt")
message(STATUS "Build projects in Sandbox")
add_subdirectory(Sandbox)
endif(EXISTS "${Open3D_SOURCE_DIR}/Sandbox/CMakeLists.txt")

# Python binding
if (Open3D_BUILD_PYTHON_BINDING)
add_subdirectory(Python)
Expand Down
33 changes: 33 additions & 0 deletions src/External/GLFW/CMake/GenerateMappings.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Usage:
# cmake -P GenerateMappings.cmake <path/to/mappings.h.in> <path/to/mappings.h>

set(source_url "https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt")
set(source_path "${CMAKE_CURRENT_BINARY_DIR}/gamecontrollerdb.txt")
set(template_path "${CMAKE_ARGV3}")
set(target_path "${CMAKE_ARGV4}")

if (NOT EXISTS "${template_path}")
message(FATAL_ERROR "Failed to find template file ${template_path}")
endif()

file(DOWNLOAD "${source_url}" "${source_path}"
STATUS download_status
TLS_VERIFY on)

list(GET download_status 0 status_code)
list(GET download_status 1 status_message)

if (status_code)
message(FATAL_ERROR "Failed to download ${source_url}: ${status_message}")
endif()

file(STRINGS "${source_path}" lines)
foreach(line ${lines})
if ("${line}" MATCHES "^[0-9a-fA-F].*$")
set(GLFW_GAMEPAD_MAPPINGS "${GLFW_GAMEPAD_MAPPINGS}\"${line}\",\n")
endif()
endforeach()

configure_file("${template_path}" "${target_path}" @ONLY NEWLINE_STYLE UNIX)
file(REMOVE "${source_path}")

Empty file modified src/External/GLFW/CMake/MacOSXBundleInfo.plist.in
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion src/External/GLFW/CMake/amd64-mingw32msvc.cmake
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SET(CMAKE_CXX_COMPILER "amd64-mingw32msvc-g++")
SET(CMAKE_RC_COMPILER "amd64-mingw32msvc-windres")
SET(CMAKE_RANLIB "amd64-mingw32msvc-ranlib")

# Configure the behaviour of the find commands
# Configure the behaviour of the find commands
SET(CMAKE_FIND_ROOT_PATH "/usr/amd64-mingw32msvc")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
Expand Down
2 changes: 1 addition & 1 deletion src/External/GLFW/CMake/i586-mingw32msvc.cmake
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SET(CMAKE_CXX_COMPILER "i586-mingw32msvc-g++")
SET(CMAKE_RC_COMPILER "i586-mingw32msvc-windres")
SET(CMAKE_RANLIB "i586-mingw32msvc-ranlib")

# Configure the behaviour of the find commands
# Configure the behaviour of the find commands
SET(CMAKE_FIND_ROOT_PATH "/usr/i586-mingw32msvc")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
Expand Down
2 changes: 1 addition & 1 deletion src/External/GLFW/CMake/i686-pc-mingw32.cmake
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SET(CMAKE_CXX_COMPILER "i686-pc-mingw32-g++")
SET(CMAKE_RC_COMPILER "i686-pc-mingw32-windres")
SET(CMAKE_RANLIB "i686-pc-mingw32-ranlib")

#Configure the behaviour of the find commands
#Configure the behaviour of the find commands
SET(CMAKE_FIND_ROOT_PATH "/opt/mingw/usr/i686-pc-mingw32")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
Expand Down
2 changes: 1 addition & 1 deletion src/External/GLFW/CMake/i686-w64-mingw32.cmake
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SET(CMAKE_CXX_COMPILER "i686-w64-mingw32-g++")
SET(CMAKE_RC_COMPILER "i686-w64-mingw32-windres")
SET(CMAKE_RANLIB "i686-w64-mingw32-ranlib")

# Configure the behaviour of the find commands
# Configure the behaviour of the find commands
SET(CMAKE_FIND_ROOT_PATH "/usr/i686-w64-mingw32")
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
Expand Down
16 changes: 0 additions & 16 deletions src/External/GLFW/CMake/modules/FindEGL.cmake

This file was deleted.

16 changes: 0 additions & 16 deletions src/External/GLFW/CMake/modules/FindGLESv1.cmake

This file was deleted.

16 changes: 0 additions & 16 deletions src/External/GLFW/CMake/modules/FindGLESv2.cmake

This file was deleted.

40 changes: 28 additions & 12 deletions src/External/GLFW/CMake/modules/FindMir.cmake
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
# Try to find Mir on a Unix system
# FindMir
# -------
# Finds the Mir library
#
# This will define:
# This will will define the following variables::
#
# MIR_LIBRARIES - Link these to use Wayland
# MIR_INCLUDE_DIR - Include directory for Wayland
#
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
# MIR_FOUND - the system has Mir
# MIR_INCLUDE_DIRS - the Mir include directory
# MIR_LIBRARIES - the Mir libraries
# MIR_DEFINITIONS - the Mir definitions


find_package (PkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules (PC_MIR mirclient>=0.26.2 QUIET)

find_path(MIR_INCLUDE_DIR NAMES mir_toolkit/mir_client_library.h
PATHS ${PC_MIR_INCLUDE_DIRS})

if (NOT WIN32)
find_library(MIR_LIBRARY NAMES mirclient
PATHS ${PC_MIR_LIBRARIES} ${PC_MIR_LIBRARY_DIRS})

find_package (PkgConfig)
pkg_check_modules (PKG_MIR QUIET mirclient)
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (MIR
REQUIRED_VARS MIR_LIBRARY MIR_INCLUDE_DIR)

set (MIR_INCLUDE_DIR ${PKG_MIR_INCLUDE_DIRS})
set (MIR_LIBRARIES ${PKG_MIR_LIBRARIES})
if (MIR_FOUND)
set(MIR_LIBRARIES ${MIR_LIBRARY})
set(MIR_INCLUDE_DIRS ${PC_MIR_INCLUDE_DIRS})
set(MIR_DEFINITIONS -DHAVE_MIR=1)
endif()

endif ()
mark_as_advanced (MIR_LIBRARY MIR_INCLUDE_DIR)
endif()
18 changes: 18 additions & 0 deletions src/External/GLFW/CMake/modules/FindOSMesa.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Try to find OSMesa on a Unix system
#
# This will define:
#
# OSMESA_LIBRARIES - Link these to use OSMesa
# OSMESA_INCLUDE_DIR - Include directory for OSMesa
#
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>

if (NOT WIN32)

find_package (PkgConfig)
pkg_check_modules (PKG_OSMESA QUIET osmesa)

set (OSMESA_INCLUDE_DIR ${PKG_OSMESA_INCLUDE_DIRS})
set (OSMESA_LIBRARIES ${PKG_OSMESA_LIBRARIES})

endif ()
Loading