This commit is contained in:
PodmogilnyjIvan
2021-12-03 03:34:31 -08:00
commit ff4acf84be
542 changed files with 136810 additions and 0 deletions

2
Thirdparty/Pangolin/.clang-format vendored Normal file
View File

@@ -0,0 +1,2 @@
DisableFormat: true
SortIncludes: false

3
Thirdparty/Pangolin/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.DS_Store
CMakeLists.txt.user
build*

3
Thirdparty/Pangolin/.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "external/pybind11"]
path = external/pybind11
url = https://github.com/pybind/pybind11.git

30
Thirdparty/Pangolin/.travis.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
sudo: required
dist: xenial
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt -qq update ; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt install -qq --no-install-suggests --no-install-recommends libeigen3-dev libglew-dev libc++-dev libwayland-dev libxkbcommon-dev wayland-protocols libegl1-mesa-dev; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then pyenv versions && pyenv global system 3.7; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install eigen glew ; fi
language: cpp
matrix:
include:
- os: linux
compiler: gcc
env: PARALLEL_BUILD="-- -j 8"
- os: linux
compiler: clang
env: PARALLEL_BUILD="-- -j 8"
- os: osx
env: PARALLEL_BUILD="-- -j 8"
- os: windows
env: PARALLEL_BUILD="--parallel 8"
script:
- mkdir build
- cd build
- cmake -D CMAKE_BUILD_TYPE=Release ..
- cmake --build . $PARALLEL_BUILD

109
Thirdparty/Pangolin/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,109 @@
cmake_minimum_required(VERSION 2.8.12)
project("Pangolin")
set(PANGOLIN_VERSION_MAJOR 0)
set(PANGOLIN_VERSION_MINOR 6)
set(PANGOLIN_VERSION ${PANGOLIN_VERSION_MAJOR}.${PANGOLIN_VERSION_MINOR})
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/")
# Platform configuration vars
include(SetPlatformVars)
SET(CPACK_GENERATOR "DEB")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Steven Lovegrove")
SET(CPACK_PACKAGE_VERSION_MAJOR ${PANGOLIN_VERSION_MAJOR})
SET(CPACK_PACKAGE_VERSION_MINOR ${PANGOLIN_VERSION_MINOR})
SET(CPACK_PACKAGE_VERSION_PATCH "0")
include(CPack)
option( BUILD_TESTS "Build Tests" ON )
option( BUILD_TOOLS "Build Examples" ON )
option( BUILD_EXAMPLES "Build Tools" ON )
set (CMAKE_CXX_STANDARD 14)
if(_WIN_)
option( BUILD_SHARED_LIBS "Build Shared Library" OFF)
option( BUILD_EXTERN_GLEW "Automatically download, build and compile GLEW" ON)
option( BUILD_EXTERN_LIBPNG "Automatically download, build and compile libpng" ON)
option( BUILD_EXTERN_LIBJPEG "Automatically download, build and compile libjpeg" ON)
option( MSVC_USE_STATIC_CRT "Use static C Runtime with MSVC, /MT instead of /MD" ON)
# Make sure there are no erroneous C Runtime flags
list(APPEND FLAG_VARS
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
)
if(MSVC_USE_STATIC_CRT)
foreach(FLAG_VAR ${FLAG_VARS})
string(REGEX REPLACE "/MD" "/MT" NEW_FLAGS "${${FLAG_VAR}}")
set(${FLAG_VAR} "${NEW_FLAGS}" CACHE STRING "" FORCE)
endforeach()
else()
foreach(FLAG_VAR ${FLAG_VARS})
string(REGEX REPLACE "/MT" "/MD" NEW_FLAGS "${${FLAG_VAR}}")
set(${FLAG_VAR} "${NEW_FLAGS}" CACHE STRING "" FORCE)
endforeach()
endif()
else()
option( BUILD_SHARED_LIBS "Build Shared Library" ON)
endif()
if(NOT MSVC)
set( CMAKE_CXX_FLAGS "-Wall -Wextra ${CMAKE_CXX_FLAGS}" )
endif()
if(ANDROID)
set(ANDROID_PACKAGE_NAME "com.github.stevenlovegrove.pangolin")
include(AndroidUtils)
endif()
if(ANDROID OR IOS)
set(HAVE_GLES 1)
option(BUILD_FOR_GLES_2 "Build for OpenGL ES 2 instead of ES 1" ON )
if(BUILD_FOR_GLES_2)
set(HAVE_GLES_2 1)
endif()
endif()
if(_OSX_)
set(CMAKE_MACOSX_RPATH ON)
endif()
# Overide with cmake -DCMAKE_BUILD_TYPE=Debug {dir}
if( NOT CMAKE_BUILD_TYPE AND NOT _WIN_ )
message("Build type not set (defaults to release)")
message("-DCMAKE_BUILD_TYPE=Debug for debug")
set( CMAKE_BUILD_TYPE Release )
endif()
string(TOLOWER ${PROJECT_NAME} LIBRARY_NAME)
# make an uninstall target
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY
)
add_custom_target(pangolin_uninstall
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
add_subdirectory("external")
add_subdirectory("src")
if(BUILD_TESTS)
set(Pangolin_DIR ${Pangolin_BINARY_DIR}/src)
add_subdirectory("test")
endif()
if(BUILD_TOOLS)
set(Pangolin_DIR ${Pangolin_BINARY_DIR}/src)
add_subdirectory(tools)
endif()
if(BUILD_EXAMPLES)
set(Pangolin_DIR ${Pangolin_BINARY_DIR}/src)
add_subdirectory(examples)
endif()

22
Thirdparty/Pangolin/LICENCE vendored Normal file
View File

@@ -0,0 +1,22 @@
Copyright (c) 2011 Steven Lovegrove and Richard Newcombe
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

176
Thirdparty/Pangolin/README.md vendored Normal file
View File

@@ -0,0 +1,176 @@
What is Pangolin
====================================
Pangolin is a lightweight portable rapid development library for managing OpenGL
display / interaction and abstracting video input. At its heart is a simple
OpenGl viewport manager which can help to modularise 3D visualisation without
adding to its complexity, and offers an advanced but intuitive 3D navigation
handler. Pangolin also provides a mechanism for manipulating program variables
through config files and ui integration, and has a flexible real-time plotter
for visualising graphical data.
The ethos of Pangolin is to reduce the boilerplate code that normally
gets written to visualise and interact with (typically image and 3D
based) systems, without compromising performance. It also enables write-once
code for a number of platforms, currently including Windows, Linux, OSX, Android
and IOS.
## Code ##
Find the latest version on [Github](http://github.com/stevenlovegrove/Pangolin):
```
git clone https://github.com/stevenlovegrove/Pangolin.git
```
## Dependencies ##
Optional dependencies are enabled when found, otherwise they are silently disabled.
Check the CMake configure output for details.
### Required Dependencies ###
* C++11
* OpenGL (Desktop / ES / ES2)
* (lin) `sudo apt install libgl1-mesa-dev`
* Glew
* (win) built automatically (assuming git is on your path)
* (deb) `sudo apt install libglew-dev`
* (mac) `sudo port install glew`
* CMake (for build environment)
* (win) http://www.cmake.org/cmake/resources/software.html
* (deb) `sudo apt install cmake`
* (mac) `sudo port install cmake`
### Recommended Dependencies ###
* Python2 / Python3, for drop-down interactive console
* (win) http://www.python.org/downloads/windows
* (deb) `sudo apt install libpython2.7-dev`
* (mac) preinstalled with osx
* (for pybind11) `git submodule init && git submodule update`
* (useful modules) `sudo python -mpip install numpy pyopengl Pillow pybind11`
* Wayland
* pkg-config: `sudo apt install pkg-config`
* Wayland and EGL:`sudo apt install libegl1-mesa-dev libwayland-dev libxkbcommon-dev wayland-protocols`
### Optional Dependencies for video input ###
* FFMPEG (For video decoding and image rescaling)
* (deb) `sudo apt install ffmpeg libavcodec-dev libavutil-dev libavformat-dev libswscale-dev libavdevice-dev`
* DC1394 (For firewire input)
* (deb) `sudo apt install libdc1394-22-dev libraw1394-dev`
* libuvc (For cross-platform webcam video input via libusb)
* git://github.com/ktossell/libuvc.git
* libjpeg, libpng, libtiff, libopenexr (For reading still-image sequences)
* (deb) `sudo apt install libjpeg-dev libpng12-dev libtiff5-dev libopenexr-dev`
* OpenNI / OpenNI2 (For Kinect / Xtrion / Primesense capture)
* DepthSense SDK
### Very Optional Dependencies ###
* Eigen / TooN (These matrix types supported in the Pangolin API.)
* CUDA Toolkit >= 3.2 (Some CUDA header-only interop utilities included)
* http://developer.nvidia.com/cuda-downloads
* Doxygen for generating html / pdf documentation.
## Building ##
Pangolin uses the CMake portable pre-build tool. To checkout and build pangolin in the
directory 'build', execute the following at a shell (or the equivelent using a GUI):
```
git clone https://github.com/stevenlovegrove/Pangolin.git
cd Pangolin
mkdir build
cd build
cmake ..
cmake --build .
```
If you would like to build the documentation and you have Doxygen installed, you
can execute:
```
cmake --build . --target pangolin_doc
```
**On Windows**, Pangolin will attempt to download and build *glew*, *libjpeg*, *libpng* and *zlib* automatically. It does so assuming that git is available on the path - this assumption may be wrong for windows users who have downloaded Pangolin via a zip file on github. You will instead need to download and compile the dependencies manually, and set the BUILD_EXTERN_(lib) options to false for these libraries. The alternate and recommended approach is to install [gitbash](https://git-scm.com/downloads) and work from within their provided console.
## Issues ##
Please visit [Github Issues](https://github.com/stevenlovegrove/Pangolin/issues) to view and report problems with Pangolin. Issues and pull requests should be raised against the master branch which contains the current development version.
Please note; most Pangolin dependencies are optional - to disable a dependency which may be causing trouble on your machine, set the BUILD_PANGOLIN_(option) variable to false with a cmake configuration tool (e.g. ccmake or cmake-gui).
## Contributions and Continuous Integration ##
For CI, Pangolin uses [travis-ci.org](https://travis-ci.org/stevenlovegrove/Pangolin) for Ubuntu, OSX and [ci.appveyor.com](https://ci.appveyor.com/project/stevenlovegrove/pangolin) for Windows.
To contribute to Pangolin, I would appreciate pull requests against the master branch. This will trigger CI builds for your changes automatically, and help me to merge with confidence.
## Binaries ##
Binaries are available for Windows x64, as output by the Windows CI server: [Appveyor Artifacts](https://ci.appveyor.com/project/stevenlovegrove/pangolin/build/artifacts).
## Bindings ##
### Python ###
Pangolin python bindings are enabled via [pybind11](www.pybind11.com). These bindings can be used both standalone and from within Pangolin's drop-down console (press the back-tick key, `).
To enable the bindings, you must checkout the pybind submodule. To use pangolin in python, it's recommend to install a few other python packages too:
```
sudo python -mpip install numpy pyopengl Pillow pybind11
git submodule init && git submodule update
```
The python module pypangolin must be on your python path, either through installation, or by setting it explicitly:
```
import sys
sys.path.append('path/of/pypangolin.so')
```
## Scheme syntax for windowing and video
Pangolin uses 'URI' syntax for modularising video drivers and windowing backends. The syntax follows along the lines of `module_name:[option1=value1,option2=value2,...]//module_resource_to_open`. Some examples for using this URI syntax with the VideoViewer tool is as follows:
```
VideoViewer test://
VideoViewer uvc:[size=640x480]///dev/video0
VideoViewer flip://debayer:[tile=rggb,method=downsample]//file://~/somefile.pango
```
Notice that for video, some modules support chaining to construct a simple filter graph. See include/pangolin/video/video.h for more examples.
For windowing, you can also customize default arguments for Pangolin applications by setting the `PANGOLIN_WINDOW_URI` environment variable. For instance, on high-DPI screens (in this example on OSX), you could set:
```
setenv PANGOLIN_WINDOW_URI "cocoa:[HIGHRES=true]//"
```
Some window parameters that may be interesting to override are `DISPLAYNAME`, `DOUBLEBUFFER`, `SAMPLE_BUFFERS`, `SAMPLES`, `HIGHRES`. Window modules currently include `x11`, `winapi`, `cocoa`.
## Acknowledgements ##
I'd like to thank the growing number of kind contributors to Pangolin for helping to make it more stable and feature rich. Many features of Pangolin have been influenced by other projects such as GFlags, GLConsole, and libcvd in particular. I'd also like to thank the FOSS projects on which Pangolin depends.
For a summary of those who have made code contributions, execute:
```
git shortlog -sne
```

25
Thirdparty/Pangolin/appveyor.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
os: Visual Studio 2015
clone_folder: c:/projects/Pangolin
platform: x64
configuration: Release
build:
verbosity: minimal
project: c:/projects/Pangolin/build/Pangolin.sln
install:
- ps: wget http://bitbucket.org/eigen/eigen/get/3.2.10.zip -outfile eigen3.zip
- cmd: 7z x eigen3.zip -o"C:/projects" -y > nul
before_build:
- cd c:/projects/Pangolin
- mkdir bin
- mkdir build
- cd build
- cmake -G "Visual Studio 14 2015 Win64" -D EIGEN3_INCLUDE_DIR=C:/projects/eigen-eigen-b9cd8366d4e8 -D CMAKE_INSTALL_PREFIX=../bin ..
on_success:
- 7z a pangolin_build.zip "c:/projects/Pangolin/build/src/include" "c:/projects/Pangolin/build/src/Release/pangolin.lib" "c:/projects/Pangolin/build/tools/*/Release/*.exe" "c:/projects/Pangolin/build/examples/*/Release/*.exe"
- appveyor PushArtifact pangolin_build.zip

View File

@@ -0,0 +1,25 @@
# -----------------------------------------------
# File that provides "make uninstall" target
# We use the file 'install_manifest.txt'
# -----------------------------------------------
IF(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_BINARY_DIR@/install_manifest.txt\"")
ENDIF(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
FILE(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
STRING(REGEX REPLACE "\n" ";" files "${files}")
FOREACH(file ${files})
MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
IF(EXISTS "$ENV{DESTDIR}${file}")
EXEC_PROGRAM(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
IF(NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
ENDIF(NOT "${rm_retval}" STREQUAL 0)
ELSE(EXISTS "$ENV{DESTDIR}${file}")
MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
ENDIF(EXISTS "$ENV{DESTDIR}${file}")
ENDFOREACH(file)

View File

@@ -0,0 +1,153 @@
include(ExternalProject)
set(ExternConfig "")
if( BUILD_EXTERN_GLEW )
#########################################################
# GLEW
#########################################################
ExternalProject_Add( __glew
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/glew"
GIT_REPOSITORY https://github.com/Perlmint/glew-cmake.git
GIT_TAG 7574ab4d00b683e56adbfdec7da636529dfe65d8
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_C_FLAGS_RELEASE=${CMAKE_C_FLAGS_RELEASE}
-DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG}
-DCMAKE_C_FLAGS_MINSIZEREL=${CMAKE_C_FLAGS_MINSIZEREL}
-DCMAKE_C_FLAGS_RELWITHDEBINFO=${CMAKE_C_FLAGS_RELWITHDEBINFO}
)
add_library(_glew STATIC IMPORTED GLOBAL)
add_dependencies(_glew __glew)
set_target_properties(_glew PROPERTIES
IMPORTED_LOCATION_RELWITHDEBINFO ${CMAKE_INSTALL_PREFIX}/lib/glew.lib
IMPORTED_LOCATION_RELEASE ${CMAKE_INSTALL_PREFIX}/lib/glew.lib
IMPORTED_LOCATION_DEBUG ${CMAKE_INSTALL_PREFIX}/lib/glewd.lib
)
set(GLEW_FOUND true PARENT_SCOPE)
set(GLEW_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include" PARENT_SCOPE)
set(GLEW_LIBRARY _glew PARENT_SCOPE)
set(GLEW_STATIC 1 PARENT_SCOPE)
set(ExternConfig "${ExternConfig}
add_library(_glew STATIC IMPORTED)
set_target_properties(_glew PROPERTIES
IMPORTED_LOCATION_RELWITHDEBINFO \"${CMAKE_INSTALL_PREFIX}/lib/glew.lib\"
IMPORTED_LOCATION_RELEASE \"${CMAKE_INSTALL_PREFIX}/lib/glew.lib\"
IMPORTED_LOCATION_DEBUG \"${CMAKE_INSTALL_PREFIX}/lib/glewd.lib\"
)")
endif()
if( BUILD_EXTERN_LIBPNG )
#########################################################
# zlib
#########################################################
ExternalProject_Add( __zlib
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/zlib"
GIT_REPOSITORY https://github.com/madler/zlib.git
GIT_TAG v1.2.8
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_C_FLAGS_RELEASE=${CMAKE_C_FLAGS_RELEASE}
-DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG}
-DCMAKE_C_FLAGS_MINSIZEREL=${CMAKE_C_FLAGS_MINSIZEREL}
-DCMAKE_C_FLAGS_RELWITHDEBINFO=${CMAKE_C_FLAGS_RELWITHDEBINFO}
)
add_library(_zlib STATIC IMPORTED GLOBAL)
add_dependencies(_zlib __zlib)
set_target_properties(_zlib PROPERTIES
IMPORTED_LOCATION_RELEASE ${CMAKE_INSTALL_PREFIX}/lib/zlibstatic.lib
IMPORTED_LOCATION_RELWITHDEBINFO ${CMAKE_INSTALL_PREFIX}/lib/zlibstatic.lib
IMPORTED_LOCATION_DEBUG ${CMAKE_INSTALL_PREFIX}/lib/zlibstaticd.lib
)
#########################################################
# libpng
#########################################################
ExternalProject_Add( __libpng
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/libpng"
GIT_REPOSITORY https://github.com/glennrp/libpng.git
GIT_TAG v1.6.18
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DZLIB_INCLUDE_DIR=${CMAKE_INSTALL_PREFIX}/include
-DZLIB_LIBRARY=${CMAKE_INSTALL_PREFIX}/lib/zlibstatic*.lib
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_C_FLAGS_RELEASE=${CMAKE_C_FLAGS_RELEASE}
-DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG}
-DCMAKE_C_FLAGS_MINSIZEREL=${CMAKE_C_FLAGS_MINSIZEREL}
-DCMAKE_C_FLAGS_RELWITHDEBINFO=${CMAKE_C_FLAGS_RELWITHDEBINFO}
DEPENDS __zlib
)
add_library(_libpng STATIC IMPORTED GLOBAL)
add_dependencies(_libpng __libpng)
set_target_properties(_libpng PROPERTIES
IMPORTED_LOCATION_RELWITHDEBINFO ${CMAKE_INSTALL_PREFIX}/lib/libpng16_static.lib
IMPORTED_LOCATION_RELEASE ${CMAKE_INSTALL_PREFIX}/lib/libpng16_static.lib
IMPORTED_LOCATION_DEBUG ${CMAKE_INSTALL_PREFIX}/lib/libpng16_staticd.lib
)
set(PNG_FOUND true PARENT_SCOPE)
set(PNG_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include" PARENT_SCOPE)
set(PNG_LIBRARY _libpng PARENT_SCOPE)
set(ZLIB_LIBRARY _zlib PARENT_SCOPE)
set(ExternConfig "${ExternConfig}
add_library(_zlib STATIC IMPORTED)
set_target_properties(_zlib PROPERTIES
IMPORTED_LOCATION_RELEASE \"${CMAKE_INSTALL_PREFIX}/lib/zlibstatic.lib\"
IMPORTED_LOCATION_RELWITHDEBINFO \"${CMAKE_INSTALL_PREFIX}/lib/zlibstatic.lib\"
IMPORTED_LOCATION_DEBUG \"${CMAKE_INSTALL_PREFIX}/lib/zlibstaticd.lib\"
)
add_library(_libpng STATIC IMPORTED)
set_target_properties(_libpng PROPERTIES
IMPORTED_LOCATION_RELEASE \"${CMAKE_INSTALL_PREFIX}/lib/libpng16_static.lib\"
IMPORTED_LOCATION_RELWITHDEBINFO \"${CMAKE_INSTALL_PREFIX}/lib/libpng16_static.lib\"
IMPORTED_LOCATION_DEBUG \"${CMAKE_INSTALL_PREFIX}/lib/libpng16_staticd.lib\"
)")
endif()
if( BUILD_EXTERN_LIBJPEG )
#########################################################
# libjpg
#########################################################
ExternalProject_Add( __libjpeg
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/libjpeg"
GIT_REPOSITORY https://github.com/LuaDist/libjpeg.git
GIT_TAG bc8f8be222287fec977ec3f47a5cb065cceb2ee9
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DBUILD_SHARED_LIBS=false
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_C_FLAGS_RELEASE=${CMAKE_C_FLAGS_RELEASE}
-DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG}
-DCMAKE_C_FLAGS_MINSIZEREL=${CMAKE_C_FLAGS_MINSIZEREL}
-DCMAKE_C_FLAGS_RELWITHDEBINFO=${CMAKE_C_FLAGS_RELWITHDEBINFO}
)
add_library(_libjpeg STATIC IMPORTED GLOBAL)
add_dependencies(_libjpeg __libjpeg)
set_target_properties(_libjpeg PROPERTIES
IMPORTED_LOCATION ${CMAKE_INSTALL_PREFIX}/lib/jpeg.lib
)
set(JPEG_FOUND true PARENT_SCOPE)
set(JPEG_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include" PARENT_SCOPE)
set(JPEG_LIBRARY _libjpeg PARENT_SCOPE)
set(ExternConfig "${ExternConfig}
add_library(_libjpeg STATIC IMPORTED)
set_target_properties(_libjpeg PROPERTIES
IMPORTED_LOCATION \"${CMAKE_INSTALL_PREFIX}/lib/jpeg.lib\"
)")
endif()
set(ExternConfig "${ExternConfig}" PARENT_SCOPE)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,92 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#include <pangolin/gl/glfont.h>
#ifdef HAVE_GLES
GLfloat g_raster_pos[4];
inline void glRasterPos3f(GLfloat x, GLfloat y, GLfloat z)
{
// find object point (x,y,z)' in pixel coords
GLdouble projection[16];
GLdouble modelview[16];
GLint view[4];
#ifdef HAVE_GLES_2
std::copy(pangolin::glEngine().projection.top().m, pangolin::glEngine().projection.top().m+16, projection);
std::copy(pangolin::glEngine().modelview.top().m, pangolin::glEngine().modelview.top().m+16, modelview);
#else
glGetDoublev(GL_PROJECTION_MATRIX, projection );
glGetDoublev(GL_MODELVIEW_MATRIX, modelview );
#endif
glGetIntegerv(GL_VIEWPORT, view );
pangolin::glProject(x, y, z, modelview, projection, view,
g_raster_pos, g_raster_pos + 1, g_raster_pos + 2);
}
inline void glRasterPos2f(GLfloat x, GLfloat y)
{
glRasterPos3f(x,y,1.0f);
}
inline void glRasterPos2i(GLint x, GLint y)
{
glRasterPos3f((GLfloat)x, (GLfloat)y, 1.0f );
}
inline void glRasterPos3fv(const GLfloat *v){
glRasterPos3f(v[0],v[1],v[2]);
}
inline void glRasterPos2fv(const GLfloat *v){
glRasterPos3f(v[0],v[1],1.0f);
}
#endif // HAVE_GLES
inline void glutBitmapString(void * /*font*/, const unsigned char *str)
{
#ifndef HAVE_GLES
float g_raster_pos[4];
glGetFloatv(GL_CURRENT_RASTER_POSITION, g_raster_pos);
#endif
pangolin::GlFont::I().Text( (const char *)str ).DrawWindow(
g_raster_pos[0], g_raster_pos[1], g_raster_pos[2]
);
}
inline int glutBitmapLength(void * /*font*/, const unsigned char *str)
{
return (int)(pangolin::GlFont::I().Text((const char *)str).Width());
}
#define GLUT_BITMAP_HELVETICA_12 0;

View File

@@ -0,0 +1,20 @@
#pragma once
#include <pangolin/platform.h>
// Use either C++17 optional, or the standalone backwards compatible version
#if (__cplusplus >= 201703L)
# include <optional>
#else
# include <experimental/optional.hpp>
#endif
namespace pangolin {
#if (__cplusplus >= 201703L)
template <typename T>
using optional = std::optional<T>;
#else
template <typename T>
using optional = std::experimental::optional<T>;
#endif
}

View File

@@ -0,0 +1,49 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <typeinfo>
#include <type_traits>
// enable_if From Boost
namespace pangolin
{
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include <pangolin/platform.h>
// Use either C++17 variant, or the standalone backwards compatible version
// of M. Park.
#if (__cplusplus >= 201703L)
# include <variant>
#else
# include <mpark/variant.hpp>
#endif
namespace pangolin {
#if (__cplusplus >= 201703L)
using std::variant;
using std::get;
using std::get_if;
using std::visit;
#else
using mpark::variant;
using mpark::get;
using mpark::get_if;
using mpark::visit;
#endif
}

View File

@@ -0,0 +1,80 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <vector>
#include <string>
namespace pangolin
{
enum ConsoleLineType
{
ConsoleLineTypeCmd,
ConsoleLineTypeCmdOptions,
ConsoleLineTypeStdout,
ConsoleLineTypeStderr,
ConsoleLineTypeOutput,
ConsoleLineTypeHelp,
};
class ConsoleLine
{
public:
inline ConsoleLine()
: linetype(ConsoleLineTypeCmd)
{
}
inline ConsoleLine(std::string text, ConsoleLineType linetype = ConsoleLineTypeOutput)
: text(text), linetype(linetype)
{
}
std::string text;
ConsoleLineType linetype;
};
class ConsoleInterpreter
{
public:
inline virtual ~ConsoleInterpreter()
{
}
virtual void PushCommand(const std::string& cmd) = 0;
virtual bool PullLine(ConsoleLine& line) = 0;
virtual std::vector<std::string> Complete(
const std::string& cmd, int max_options = 20
) = 0;
};
}

View File

@@ -0,0 +1,109 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <deque>
#include <pangolin/platform.h>
#include <pangolin/gl/glfont.h>
#include <pangolin/var/var.h>
#include <pangolin/display/view.h>
#include <pangolin/handler/handler.h>
#include <pangolin/gl/colour.h>
#include <pangolin/console/ConsoleInterpreter.h>
namespace pangolin
{
class ConsoleView : public pangolin::View, pangolin::Handler
{
public:
struct Line
{
Line()
: linetype(ConsoleLineTypeCmd)
{
}
Line(const GlText& text, ConsoleLineType linetype = ConsoleLineTypeCmd )
: text(text), linetype(linetype)
{
}
GlText text;
ConsoleLineType linetype;
};
// Construct with interpreter (and take ownership)
ConsoleView(ConsoleInterpreter* interpreter);
~ConsoleView();
View& ShowWithoutAnimation(bool show=true);
// Replace implementation in View to account for hiding animation
View& Show(bool show=true);
// Replace implementation in View to account for hiding animation
void ToggleShow();
// Replace implementation in View to account for hiding animation
bool IsShown() const;
void Render() override;
void Keyboard(View&, unsigned char key, int x, int y, bool pressed) override;
private:
void DrawLine(const ConsoleView::Line& l, int carat);
void ProcessOutputLines();
void AddLine(const std::string& text, ConsoleLineType linetype = ConsoleLineTypeCmd);
Line* GetLine(int id, ConsoleLineType line_type, const std::string& prefix = "");
ConsoleInterpreter* interpreter;
GlFont& font;
int carat;
Line current_line;
std::deque<Line> line_buffer;
bool hiding;
GLfloat bottom;
Colour background_colour;
std::map<ConsoleLineType,pangolin::Colour> line_colours;
float animation_speed;
};
}

View File

@@ -0,0 +1,86 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <iostream>
#include <string>
#include <cmath>
namespace pangolin
{
/// Units for measuring screen distances.
enum Unit {
Fraction,
Pixel,
ReversePixel
};
/// Defines absolute or relative position from parent viewport edge.
/// Constructors distinguised by whole pixels, or floating
/// fraction in interval [0,1]
struct PANGOLIN_EXPORT Attach {
/// Attach to Left/Bottom edge
Attach() : unit(Fraction), p(0) {}
/// General constructor
Attach(Unit unit, GLfloat p) : unit(unit), p(p) {}
/// Specify relative position in range [0,1].
/// 0 represents leftmost / bottom-most edge,
/// 1 represents rightmost / topmost edge
Attach(GLfloat p) : unit(Fraction), p(p) {
// Allow for numerical imprecision when checking usage.
if( p < -1E-3 || 1.001 < p ) {
std::cerr << "Pangolin API Change: Display::SetBounds must be used with Attach::Pix or Attach::ReversePix to specify pixel bounds relative to an edge. See the code samples for details." << std::endl;
throw std::exception();
}
}
/// Specify absolute position from leftmost / bottom-most edge.
static Attach Pix(int p) {
return Attach(p >=0 ? Pixel : ReversePixel, std::abs((float)p));
}
/// Specify absolute position from rightmost / topmost edge.
static Attach ReversePix(int p) {
return Attach(ReversePixel, (GLfloat)p);
}
/// Specify relative position in range [0,1].
/// 0 represents leftmost / bottom-most edge,
/// 1 represents rightmost / topmost edge
static Attach Frac(float frac) {
return Attach(frac);
}
Unit unit;
GLfloat p;
};
} // namespace pangolin

View File

@@ -0,0 +1,68 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/display/display_internal.h>
#include <pangolin/display/device/PangolinNSApplication.h>
#include <pangolin/display/device/PangolinNSGLView.h>
namespace pangolin
{
struct OsxWindow : public PangolinGl
{
OsxWindow(const std::string& title, int width, int height, bool USE_RETINA);
~OsxWindow();
void StartFullScreen();
void StopFullScreen();
void ToggleFullscreen() override;
void Move(int x, int y) override;
void Resize(unsigned int w, unsigned int h) override;
void MakeCurrent() override;
void RemoveCurrent() override;
void SwapBuffers() override;
void ProcessEvents() override;
private:
NSWindow* _window;
PangolinNSGLView *view;
};
}

View File

@@ -0,0 +1,59 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
////////////////////////////////////////////////////////////////////
// PangolinNSApplication
////////////////////////////////////////////////////////////////////
@interface PangolinNSApplication : NSObject {
}
+ (void)run_pre;
+ (void)run_step;
@end
////////////////////////////////////////////////////////////////////
// PangolinWindowDelegate
////////////////////////////////////////////////////////////////////
@interface PangolinWindowDelegate : NSObject <NSWindowDelegate>
@end
////////////////////////////////////////////////////////////////////
// PangolinAppDelegate
////////////////////////////////////////////////////////////////////
@interface PangolinAppDelegate : NSObject <NSApplicationDelegate>
@end

View File

@@ -0,0 +1,45 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#include <pangolin/display/display_internal.h>
////////////////////////////////////////////////////////////////////
// PangolinNSGLView
////////////////////////////////////////////////////////////////////
@interface PangolinNSGLView : NSOpenGLView
{
pangolin::PangolinGl* context;
float backing_scale;
}
@end

View File

@@ -0,0 +1,89 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/display/display_internal.h>
#include <string>
#include <windowsx.h>
namespace pangolin
{
struct WinWindow : public PangolinGl
{
WinWindow(
const std::string& title, int width, int height
);
~WinWindow();
void StartFullScreen();
void StopFullScreen();
void ToggleFullscreen() override;
void Move(int x, int y) override;
void Resize(unsigned int w, unsigned int h) override;
void MakeCurrent() override;
void RemoveCurrent() override;
void SwapBuffers() override;
void ProcessEvents() override;
HGLRC GetGLRenderContext()
{
return hGLRC;
}
private:
static LRESULT APIENTRY WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT HandleWinMessages(UINT message, WPARAM wParam, LPARAM lParam);
void RegisterThisClass(HMODULE hCurrentInst);
void SetupPixelFormat(HDC hdc);
void SetupPalette(HDC hDC);
// Owns the Window
HWND hWnd;
HDC hDC;
HGLRC hGLRC;
HPALETTE hPalette;
};
}

View File

@@ -0,0 +1,109 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/display/display_internal.h>
#include <stdexcept>
#include <string>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/glx.h>
namespace pangolin
{
struct X11Display
{
X11Display(const char* name = 0) {
XInitThreads();
display = XOpenDisplay(name);
if (!display) {
throw std::runtime_error("Pangolin X11: Failed to open X display");
}
}
~X11Display() {
XCloseDisplay(display);
}
// Owns the display
::Display* display;
};
struct X11GlContext : public GlContextInterface
{
X11GlContext(std::shared_ptr<X11Display> &d, ::GLXFBConfig chosenFbc, std::shared_ptr<X11GlContext> shared_context = std::shared_ptr<X11GlContext>() );
~X11GlContext();
std::shared_ptr<X11Display> display;
std::shared_ptr<X11GlContext> shared_context;
// Owns the OpenGl Context
::GLXContext glcontext;
};
struct X11Window : public PangolinGl
{
X11Window(
const std::string& title, int width, int height,
std::shared_ptr<X11Display>& display, ::GLXFBConfig chosenFbc
);
~X11Window();
void ToggleFullscreen() override;
void Move(int x, int y) override;
void Resize(unsigned int w, unsigned int h) override;
void MakeCurrent(GLXContext ctx);
void MakeCurrent() override;
void RemoveCurrent() override;
void SwapBuffers() override;
void ProcessEvents() override;
// References the X11 display and context.
std::shared_ptr<X11Display> display;
std::shared_ptr<X11GlContext> glcontext;
// Owns the X11 Window and Colourmap
::Window win;
::Colormap cmap;
Atom delete_message;
};
}

View File

@@ -0,0 +1,333 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <android/configuration.h>
#include <android/looper.h>
#include <android/native_activity.h>
#include <android/log.h>
#include <string>
#include <pangolin/utils/type_convert.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "pango", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "pango", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "pango", __VA_ARGS__))
/* For debug builds, always enable the debug traces in this library */
#undef NDEBUG
#ifndef NDEBUG
# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "pango", __VA_ARGS__))
#else
# define LOGV(...) ((void)0)
#endif
template<typename T> inline
void Log(T v) {
const std::string sv = pangolin::Convert<std::string,T>::Do(v);
LOGI(sv.c_str());
}
template<typename T> inline
void Log(const std::string& str, T v)
{
const std::string sv = pangolin::Convert<std::string,T>::Do(v);
LOGI((str + ":" + sv).c_str());
}
namespace pangolin
{
void CreateAndroidWindowAndBind(std::string name);
void ProcessAndroidEvents();
void FinishAndroidFrame();
}
#ifdef __cplusplus
extern "C" {
#endif
struct android_app;
/**
* Data associated with an ALooper fd that will be returned as the "outData"
* when that source has data ready.
*/
struct android_poll_source {
// The identifier of this source. May be LOOPER_ID_MAIN or
// LOOPER_ID_INPUT.
int32_t id;
// The android_app this ident is associated with.
struct android_app* app;
// Function to call to perform the standard processing of data from
// this source.
void (*process)(struct android_app* app, struct android_poll_source* source);
};
/**
* This is the interface for the standard glue code of a threaded
* application. In this model, the application's code is running
* in its own thread separate from the main thread of the process.
* It is not required that this thread be associated with the Java
* VM, although it will need to be in order to make JNI calls any
* Java objects.
*/
struct android_app {
// The application can place a pointer to its own state object
// here if it likes.
void* userData;
// Fill this in with the function to process main app commands (APP_CMD_*)
void (*onAppCmd)(struct android_app* app, int32_t cmd);
// Fill this in with the function to process input events. At this point
// the event has already been pre-dispatched, and it will be finished upon
// return. Return 1 if you have handled the event, 0 for any default
// dispatching.
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
// The ANativeActivity object instance that this app is running in.
ANativeActivity* activity;
// The current configuration the app is running in.
AConfiguration* config;
// This is the last instance's saved state, as provided at creation time.
// It is NULL if there was no state. You can use this as you need; the
// memory will remain around until you call android_app_exec_cmd() for
// APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
// These variables should only be changed when processing a APP_CMD_SAVE_STATE,
// at which point they will be initialized to NULL and you can malloc your
// state and place the information here. In that case the memory will be
// freed for you later.
void* savedState;
size_t savedStateSize;
// The ALooper associated with the app's thread.
ALooper* looper;
// When non-NULL, this is the input queue from which the app will
// receive user input events.
AInputQueue* inputQueue;
// When non-NULL, this is the window surface that the app can draw in.
ANativeWindow* window;
// Current content rectangle of the window; this is the area where the
// window's content should be placed to be seen by the user.
ARect contentRect;
// Current state of the app's activity. May be either APP_CMD_START,
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
int activityState;
// This is non-zero when the application's NativeActivity is being
// destroyed and waiting for the app thread to complete.
int destroyRequested;
// -------------------------------------------------
// Below are "private" implementation of the glue code.
pthread_mutex_t mutex;
pthread_cond_t cond;
int msgread;
int msgwrite;
pthread_t thread;
struct android_poll_source cmdPollSource;
struct android_poll_source inputPollSource;
int running;
int stateSaved;
int destroyed;
int redrawNeeded;
AInputQueue* pendingInputQueue;
ANativeWindow* pendingWindow;
ARect pendingContentRect;
const char* application_so;
};
enum {
/**
* Looper data ID of commands coming from the app's main thread, which
* is returned as an identifier from ALooper_pollOnce(). The data for this
* identifier is a pointer to an android_poll_source structure.
* These can be retrieved and processed with android_app_read_cmd()
* and android_app_exec_cmd().
*/
LOOPER_ID_MAIN = 1,
/**
* Looper data ID of events coming from the AInputQueue of the
* application's window, which is returned as an identifier from
* ALooper_pollOnce(). The data for this identifier is a pointer to an
* android_poll_source structure. These can be read via the inputQueue
* object of android_app.
*/
LOOPER_ID_INPUT = 2,
/**
* Start of user-defined ALooper identifiers.
*/
LOOPER_ID_USER = 3,
};
enum {
/**
* Command from main thread: the AInputQueue has changed. Upon processing
* this command, android_app->inputQueue will be updated to the new queue
* (or NULL).
*/
APP_CMD_INPUT_CHANGED,
/**
* Command from main thread: a new ANativeWindow is ready for use. Upon
* receiving this command, android_app->window will contain the new window
* surface.
*/
APP_CMD_INIT_WINDOW,
/**
* Command from main thread: the existing ANativeWindow needs to be
* terminated. Upon receiving this command, android_app->window still
* contains the existing window; after calling android_app_exec_cmd
* it will be set to NULL.
*/
APP_CMD_TERM_WINDOW,
/**
* Command from main thread: the current ANativeWindow has been resized.
* Please redraw with its new size.
*/
APP_CMD_WINDOW_RESIZED,
/**
* Command from main thread: the system needs that the current ANativeWindow
* be redrawn. You should redraw the window before handing this to
* android_app_exec_cmd() in order to avoid transient drawing glitches.
*/
APP_CMD_WINDOW_REDRAW_NEEDED,
/**
* Command from main thread: the content area of the window has changed,
* such as from the soft input window being shown or hidden. You can
* find the new content rect in android_app::contentRect.
*/
APP_CMD_CONTENT_RECT_CHANGED,
/**
* Command from main thread: the app's activity window has gained
* input focus.
*/
APP_CMD_GAINED_FOCUS,
/**
* Command from main thread: the app's activity window has lost
* input focus.
*/
APP_CMD_LOST_FOCUS,
/**
* Command from main thread: the current device configuration has changed.
*/
APP_CMD_CONFIG_CHANGED,
/**
* Command from main thread: the system is running low on memory.
* Try to reduce your memory use.
*/
APP_CMD_LOW_MEMORY,
/**
* Command from main thread: the app's activity has been started.
*/
APP_CMD_START,
/**
* Command from main thread: the app's activity has been resumed.
*/
APP_CMD_RESUME,
/**
* Command from main thread: the app should generate a new saved state
* for itself, to restore from later if needed. If you have saved state,
* allocate it with malloc and place it in android_app.savedState with
* the size in android_app.savedStateSize. The will be freed for you
* later.
*/
APP_CMD_SAVE_STATE,
/**
* Command from main thread: the app's activity has been paused.
*/
APP_CMD_PAUSE,
/**
* Command from main thread: the app's activity has been stopped.
*/
APP_CMD_STOP,
/**
* Command from main thread: the app's activity is being destroyed,
* and waiting for the app thread to clean up and exit before proceeding.
*/
APP_CMD_DESTROY,
};
/**
* Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
* app command message.
*/
int8_t android_app_read_cmd(struct android_app* android_app);
/**
* Call with the command returned by android_app_read_cmd() to do the
* initial pre-processing of the given command. You can perform your own
* actions for the command after calling this function.
*/
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
/**
* Call with the command returned by android_app_read_cmd() to do the
* final post-processing of the given command. You must have done your own
* actions for the command before calling this function.
*/
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,219 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/gl/glinclude.h>
#include <pangolin/handler/handler_enums.h>
#include <pangolin/utils/params.h>
#include <pangolin/display/window.h>
#include <functional>
#include <string>
#include <memory>
/*! \file display.h
* This file contains a number of global methods for creating and
* querying window state as well as handling user input.
*/
namespace pangolin
{
// CreateWindowAndBind parameter key names.
// X11 Window options:
extern const char* PARAM_DISPLAYNAME; // std::string
extern const char* PARAM_DOUBLEBUFFER; // bool
extern const char* PARAM_SAMPLE_BUFFERS; // int
extern const char* PARAM_SAMPLES; // int
extern const char* PARAM_HIGHRES; // bool - Apple Retina screens only
// Forward Declarations
struct View;
struct Viewport;
class UserApp;
/// Give this OpenGL context a name or switch contexts.
/// This is required to initialise Pangolin for use with an
/// externally defined OpenGL context. You needn't call it
/// if you have used CreateWindowAndBind() to create a window
/// or launched a pangolin::UserApp
PANGOLIN_EXPORT
WindowInterface& BindToContext(std::string name);
/// Initialise OpenGL window (determined by platform) and bind context.
/// This method will choose an available windowing system if one is present.
PANGOLIN_EXPORT
WindowInterface& CreateWindowAndBind(std::string window_title, int w = 640, int h = 480, const Params& params = Params());
/// Return pointer to current Pangolin Window context, or nullptr if none bound.
PANGOLIN_EXPORT
WindowInterface* GetBoundWindow();
PANGOLIN_EXPORT
void DestroyWindow(const std::string& window_title);
/// Launch users derived UserApp, controlling OpenGL event loop.
/// This method will block until the application exits, calling app's
/// Init() method to start and Render() method subsequently to draw each frame.
/// @return exit code for use when returning from main. Currently always 0.
PANGOLIN_EXPORT
int LaunchUserApp(UserApp& app);
/// Perform any post rendering, event processing and frame swapping.
PANGOLIN_EXPORT
void FinishFrame();
/// Request that the window close.
PANGOLIN_EXPORT
void Quit();
/// Request that all windows close.
PANGOLIN_EXPORT
void QuitAll();
/// Returns true if user has requested to close OpenGL window.
PANGOLIN_EXPORT
bool ShouldQuit();
/// Returns true if user has interacted with the window since this was last called.
PANGOLIN_EXPORT
bool HadInput();
/// Returns true if user has resized the window.
PANGOLIN_EXPORT
bool HasResized();
/// Renders any views with default draw methods.
PANGOLIN_EXPORT
void RenderViews();
/// Perform any post render events, such as screen recording.
PANGOLIN_EXPORT
void PostRender();
/// Request to be notified via functor when key is pressed.
/// Functor may take one parameter which will equal the key pressed
PANGOLIN_EXPORT
void RegisterKeyPressCallback(int key, std::function<void(void)> func);
/// Save window contents to image.
PANGOLIN_EXPORT
void SaveWindowOnRender(std::string filename_prefix);
PANGOLIN_EXPORT
void SaveFramebuffer(std::string prefix, const Viewport& v);
namespace process
{
/// Tell pangolin to process input to drive display.
/// You will need to call this manually if you haven't let
/// Pangolin register callbacks from your windowing system
PANGOLIN_EXPORT
void Keyboard( unsigned char key, int x, int y);
PANGOLIN_EXPORT
void KeyboardUp(unsigned char key, int x, int y);
PANGOLIN_EXPORT
void SpecialFunc(int key, int x, int y);
PANGOLIN_EXPORT
void SpecialFuncUp(int key, int x, int y);
/// Tell pangolin base window size has changed
/// You will need to call this manually if you haven't let
/// Pangolin register callbacks from your windowing system
PANGOLIN_EXPORT
void Resize(int width, int height);
/// Event based rendering entry point. Not currently supported.
PANGOLIN_EXPORT
void Display();
PANGOLIN_EXPORT
void Mouse( int button, int state, int x, int y);
PANGOLIN_EXPORT
void MouseMotion( int x, int y);
PANGOLIN_EXPORT
void PassiveMouseMotion(int x, int y);
PANGOLIN_EXPORT
void Scroll(float x, float y);
PANGOLIN_EXPORT
void Zoom(float m);
PANGOLIN_EXPORT
void Rotate(float r);
PANGOLIN_EXPORT
void SubpixMotion(float x, float y, float pressure, float rotation, float tiltx, float tilty);
PANGOLIN_EXPORT
void SpecialInput(InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4);
}
/// Retrieve 'base' display, corresponding to entire window.
PANGOLIN_EXPORT
View& DisplayBase();
/// Create or retrieve named display managed by pangolin (automatically deleted).
PANGOLIN_EXPORT
View& Display(const std::string& name);
/// Create unnamed display managed by pangolin (automatically deleted).
PANGOLIN_EXPORT
View& CreateDisplay();
/// Switch between windowed and fullscreen mode.
PANGOLIN_EXPORT
void ToggleFullscreen();
/// Switch windows/fullscreenmode = fullscreen.
PANGOLIN_EXPORT
void SetFullscreen(bool fullscreen = true);
/// Toggle display of Pangolin console
PANGOLIN_EXPORT
void ToggleConsole();
/// Convenience functor for toggling pangolin::View.
/// Use with RegisterKeyPressCallback for example
struct ToggleViewFunctor {
inline ToggleViewFunctor(View& view);
inline ToggleViewFunctor(const std::string& name);
void operator()();
View& view;
};
}

View File

@@ -0,0 +1,138 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/display/window.h>
#include <pangolin/display/view.h>
#include <pangolin/display/user_app.h>
#include <functional>
#include <memory>
#include <map>
#include <queue>
#ifdef BUILD_PANGOLIN_VIDEO
# include <pangolin/video/video_output.h>
#endif // BUILD_PANGOLIN_VIDEO
namespace pangolin
{
// Forward Declarations
#ifdef HAVE_PYTHON
class ConsoleView;
#endif // HAVE_PYTHON
class GlFont;
typedef std::map<const std::string,View*> ViewMap;
typedef std::map<int,std::function<void(void)> > KeyhookMap;
struct PANGOLIN_EXPORT PangolinGl : public WindowInterface
{
PangolinGl();
~PangolinGl();
// Base container for displays
View base;
// Named views which are managed by pangolin (i.e. created / deleted by pangolin)
ViewMap named_managed_views;
// Optional user app
UserApp* user_app;
// Global keypress hooks
KeyhookMap keypress_hooks;
// Manage fullscreen (ToggleFullscreen is quite new)
bool is_double_buffered;
bool is_fullscreen;
GLint windowed_size[2];
bool is_high_res;
// State relating to interactivity
bool quit;
int had_input;
int has_resized;
int mouse_state;
View* activeDisplay;
std::queue<std::pair<std::string,Viewport> > screen_capture;
#ifdef BUILD_PANGOLIN_VIDEO
View* record_view;
VideoOutput recorder;
#endif
#ifdef HAVE_PYTHON
ConsoleView* console_view;
#endif
std::shared_ptr<GlFont> font;
virtual void ToggleFullscreen() override {
pango_print_warn("ToggleFullscreen: Not available with non-pangolin window.\n");
}
virtual void ProcessEvents() override {
pango_print_warn("ProcessEvents: Not available with non-pangolin window.\n");
}
virtual void SwapBuffers() override {
pango_print_warn("SwapBuffers: Not available with non-pangolin window.\n");
}
virtual void MakeCurrent() override {
pango_print_warn("MakeCurrent: Not available with non-pangolin window.\n");
}
virtual void RemoveCurrent() override {
pango_print_warn("RemoveCurrent: Not available with non-pangolin window.\n");
}
virtual void Move(int /*x*/, int /*y*/) override {
pango_print_warn("Move: Not available with non-pangolin window.\n");
}
virtual void Resize(unsigned int /*w*/, unsigned int /*h*/) override {
pango_print_warn("Resize: Not available with non-pangolin window.\n");
}
};
PangolinGl* GetCurrentContext();
void RegisterNewContext(const std::string& name, std::shared_ptr<PangolinGl> newcontext);
void DeleteContext(const std::string& name);
PangolinGl *FindContext(const std::string& name);
}

View File

@@ -0,0 +1,74 @@
#pragma once
#include <pangolin/display/display.h>
#include <pangolin/gl/glpixformat.h>
#include <pangolin/gl/glformattraits.h>
#include <pangolin/gl/glsl.h>
#include <pangolin/handler/handler_image.h>
#include <pangolin/image/image_utils.h>
#include <mutex>
namespace pangolin
{
class ImageView : public pangolin::View, public pangolin::ImageViewHandler
{
public:
ImageView();
~ImageView();
void Render() override;
void Mouse(View& view, pangolin::MouseButton button, int x, int y, bool pressed, int button_state) override;
void Keyboard(View& view, unsigned char key, int x, int y, bool pressed) override;
pangolin::GlTexture& Tex();
ImageView& SetImage(void* ptr, size_t w, size_t h, size_t pitch, pangolin::GlPixFormat img_fmt, bool delayed_upload = false);
ImageView& SetImage(const pangolin::Image<unsigned char>& img, const pangolin::GlPixFormat& glfmt, bool delayed_upload = false);
template<typename T> inline
ImageView& SetImage(const pangolin::Image<T>& img, bool delayed_upload = false)
{
return SetImage(img.template UnsafeReinterpret<unsigned char>(), GlPixFormat::FromType<T>(), delayed_upload);
}
ImageView& SetImage(const pangolin::TypedImage& img, bool delayed_upload = false);
ImageView& SetImage(const pangolin::GlTexture& texture);
void LoadPending();
ImageView& Clear();
std::pair<float, float>& GetOffsetScale();
bool MouseReleased() const;
bool MousePressed() const;
void SetRenderOverlay(const bool& val);
// private:
// img_to_load contains image data that should be uploaded to the texture on
// the next render cycle. The data is owned by this object and should be
// freed after use.
pangolin::ManagedImage<unsigned char> img_to_load;
pangolin::GlPixFormat img_fmt_to_load;
std::pair<float, float> offset_scale;
pangolin::GlPixFormat fmt;
pangolin::GlTexture tex;
bool lastPressed;
bool mouseReleased;
bool mousePressed;
bool overlayRender;
std::mutex texlock;
};
}

View File

@@ -0,0 +1,446 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/utils/simple_math.h>
#include <vector>
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#include <Eigen/Geometry>
#endif
#ifdef HAVE_TOON
#include <cstring>
#include <TooN/TooN.h>
#include <TooN/se3.h>
#endif
#ifdef HAVE_OCULUS
#include <pangolin/compat/ovr.h>
#endif
namespace pangolin {
#ifdef HAVE_GLES
typedef float GLprecision;
#else
typedef double GLprecision;
#endif
/// Capture OpenGL matrix types in enum to typing.
enum OpenGlStack {
GlModelViewStack = 0x1700, // GL_MODELVIEW
GlProjectionStack = 0x1701, // GL_PROJECTION
GlTextureStack = 0x1702 // GL_TEXTURE
};
enum AxisDirection
{
AxisNone,
AxisNegX, AxisX,
AxisNegY, AxisY,
AxisNegZ, AxisZ
};
struct CameraSpec {
GLprecision forward[3];
GLprecision up[3];
GLprecision right[3];
GLprecision img_up[2];
GLprecision img_right[2];
};
const static CameraSpec CameraSpecOpenGl = {{0,0,-1},{0,1,0},{1,0,0},{0,1},{1,0}};
const static CameraSpec CameraSpecYDownZForward = {{0,0,1},{0,-1,0},{1,0,0},{0,-1},{1,0}};
/// Direction vector for each AxisDirection enum
const static GLprecision AxisDirectionVector[7][3] = {
{0,0,0},
{-1,0,0}, {1,0,0},
{0,-1,0}, {0,1,0},
{0,0,-1}, {0,0,1}
};
/// Object representing OpenGl Matrix.
struct PANGOLIN_EXPORT OpenGlMatrix {
static OpenGlMatrix Translate(GLprecision x, GLprecision y, GLprecision z);
static OpenGlMatrix Scale(GLprecision x, GLprecision y, GLprecision z);
static OpenGlMatrix RotateX(GLprecision theta_rad);
static OpenGlMatrix RotateY(GLprecision theta_rad);
static OpenGlMatrix RotateZ(GLprecision theta_rad);
template<typename P>
static OpenGlMatrix ColMajor4x4(const P* col_major_4x4);
OpenGlMatrix();
#ifdef USE_EIGEN
template<typename P>
OpenGlMatrix(const Eigen::Matrix<P,4,4>& mat);
template<typename P>
OpenGlMatrix(const Eigen::Transform<P,3,Eigen::Affine>& mat) : OpenGlMatrix(mat.matrix()) { }
template<typename P>
operator Eigen::Matrix<P,4,4>() const;
template<typename P>
operator Eigen::Transform<P,3,Eigen::Affine>() const;
#endif // USE_EIGEN
#ifdef HAVE_TOON
OpenGlMatrix(const TooN::SE3<>& T);
OpenGlMatrix(const TooN::Matrix<4,4>& M);
operator const TooN::SE3<>() const;
operator const TooN::Matrix<4,4>() const;
#endif // HAVE_TOON
#ifdef HAVE_OCULUS
OpenGlMatrix(const OVR::Matrix4f& M);
operator const OVR::Matrix4f() const;
#endif // HAVE_OCULUS
// Load matrix on to OpenGl stack
void Load() const;
void Multiply() const;
void SetIdentity();
OpenGlMatrix Transpose() const;
OpenGlMatrix Inverse() const;
GLprecision& operator()(int r, int c) {
return m[4*c +r];
}
GLprecision operator()(int r, int c) const {
return m[4 * c + r];
}
// Column major Internal buffer
GLprecision m[16];
};
PANGOLIN_EXPORT
OpenGlMatrix operator*(const OpenGlMatrix& lhs, const OpenGlMatrix& rhs);
PANGOLIN_EXPORT
std::ostream& operator<<(std::ostream& os, const OpenGlMatrix& mat);
/// Deprecated.
struct PANGOLIN_EXPORT OpenGlMatrixSpec : public OpenGlMatrix {
// Specify which stack this refers to
OpenGlStack type;
};
/// Object representing attached OpenGl Matrices / transforms.
class PANGOLIN_EXPORT OpenGlRenderState
{
public:
OpenGlRenderState();
OpenGlRenderState(const OpenGlMatrix& projection_matrix);
OpenGlRenderState(const OpenGlMatrix& projection_matrix, const OpenGlMatrix& modelview_matrix);
static void ApplyIdentity();
void Apply() const;
OpenGlRenderState& SetProjectionMatrix(OpenGlMatrix m);
OpenGlRenderState& SetModelViewMatrix(OpenGlMatrix m);
OpenGlMatrix& GetProjectionMatrix();
OpenGlMatrix GetProjectionMatrix() const;
OpenGlMatrix& GetModelViewMatrix();
OpenGlMatrix GetModelViewMatrix() const;
OpenGlMatrix GetProjectionModelViewMatrix() const;
OpenGlMatrix GetProjectiveTextureMatrix() const;
void EnableProjectiveTexturing() const;
void DisableProjectiveTexturing() const;
//! Seemlessly move OpenGl camera relative to changes in T_wc,
//! whilst still enabling interaction
void Follow(const OpenGlMatrix& T_wc, bool follow = true);
void Unfollow();
// Experimental - subject to change
OpenGlMatrix& GetProjectionMatrix(unsigned int view);
OpenGlMatrix GetProjectionMatrix(unsigned int view) const;
OpenGlMatrix& GetViewOffset(unsigned int view);
OpenGlMatrix GetViewOffset(unsigned int view) const;
OpenGlMatrix GetModelViewMatrix(int i) const;
void ApplyNView(int view) const;
PANGOLIN_DEPRECATED
OpenGlRenderState& Set(OpenGlMatrixSpec spec);
protected:
OpenGlMatrix modelview;
std::vector<OpenGlMatrix> projection;
std::vector<OpenGlMatrix> modelview_premult;
OpenGlMatrix T_cw;
bool follow;
};
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRUB_BottomLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRUB_TopLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRDF_TopLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRDF_TopRight(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRDF_BottomLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixRDF_BottomRight(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
//! Use OpenGl's default frame RUB_BottomLeft
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrix(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar );
PANGOLIN_EXPORT
OpenGlMatrixSpec ProjectionMatrixOrthographic(GLprecision l, GLprecision r, GLprecision b, GLprecision t, GLprecision n, GLprecision f );
//! Generate glulookat style model view matrix, looking at (lx,ly,lz)
//! X-Right, Y-Up, Z-Back
PANGOLIN_EXPORT
OpenGlMatrix ModelViewLookAtRUB(GLprecision ex, GLprecision ey, GLprecision ez, GLprecision lx, GLprecision ly, GLprecision lz, GLprecision ux, GLprecision uy, GLprecision uz);
//! Generate glulookat style model view matrix, looking at (lx,ly,lz)
//! X-Right, Y-Down, Z-Forward
PANGOLIN_EXPORT
OpenGlMatrix ModelViewLookAtRDF(GLprecision ex, GLprecision ey, GLprecision ez, GLprecision lx, GLprecision ly, GLprecision lz, GLprecision ux, GLprecision uy, GLprecision uz);
//! Generate glulookat style model view matrix, OpenGL Default camera convention (XYZ=RUB), looking at (lx,ly,lz)
PANGOLIN_EXPORT
OpenGlMatrix ModelViewLookAt(GLprecision x, GLprecision y, GLprecision z, GLprecision lx, GLprecision ly, GLprecision lz, AxisDirection up);
PANGOLIN_EXPORT
OpenGlMatrix ModelViewLookAt(GLprecision ex, GLprecision ey, GLprecision ez, GLprecision lx, GLprecision ly, GLprecision lz, GLprecision ux, GLprecision uy, GLprecision uz);
PANGOLIN_EXPORT
OpenGlMatrix IdentityMatrix();
PANGOLIN_EXPORT
OpenGlMatrixSpec IdentityMatrix(OpenGlStack type);
PANGOLIN_EXPORT
OpenGlMatrixSpec negIdentityMatrix(OpenGlStack type);
#ifdef HAVE_TOON
OpenGlMatrixSpec FromTooN(const TooN::SE3<>& T_cw);
OpenGlMatrixSpec FromTooN(OpenGlStack type, const TooN::Matrix<4,4>& M);
TooN::Matrix<4,4> ToTooN(const OpenGlMatrixSpec& ms);
TooN::SE3<> ToTooN_SE3(const OpenGlMatrixSpec& ms);
#endif
#ifdef HAVE_EIGEN
template<typename P>
Eigen::Matrix<P,4,4> ToEigen(const OpenGlMatrix& ms);
#endif
}
// Inline definitions
namespace pangolin
{
template<typename P>
inline OpenGlMatrix OpenGlMatrix::ColMajor4x4(const P* col_major_4x4)
{
OpenGlMatrix mat;
std::copy(col_major_4x4, col_major_4x4 + 16, mat.m);
return mat;
}
inline OpenGlMatrix::OpenGlMatrix() {
}
#ifdef USE_EIGEN
template<typename P> inline
OpenGlMatrix::OpenGlMatrix(const Eigen::Matrix<P,4,4>& mat)
{
for(int r=0; r<4; ++r ) {
for(int c=0; c<4; ++c ) {
m[c*4+r] = mat(r,c);
}
}
}
template<typename P>
OpenGlMatrix::operator Eigen::Matrix<P,4,4>() const
{
return ToEigen<P>(*this);
}
template<typename P>
OpenGlMatrix::operator Eigen::Transform<P,3,Eigen::Affine>() const
{
return Eigen::Transform<P,3,Eigen::Affine>(ToEigen<P>(*this));
}
template<typename P> inline
Eigen::Matrix<P,4,4> ToEigen(const OpenGlMatrix& ms)
{
Eigen::Matrix<P,4,4> mat;
for(int r=0; r<4; ++r ) {
for(int c=0; c<4; ++c ) {
mat(r,c) = (P)ms.m[c*4+r];
}
}
return mat;
}
#endif // USE_EIGEN
#ifdef HAVE_TOON
inline OpenGlMatrix::OpenGlMatrix(const TooN::SE3<>& T)
{
TooN::Matrix<4,4,GLprecision,TooN::ColMajor> M;
M.slice<0,0,3,3>() = T.get_rotation().get_matrix();
M.T()[3].slice<0,3>() = T.get_translation();
M[3] = TooN::makeVector(0,0,0,1);
std::memcpy(m, &(M[0][0]),16*sizeof(GLprecision));
}
inline OpenGlMatrix::OpenGlMatrix(const TooN::Matrix<4,4>& M)
{
// Read in remembering col-major convension for our matrices
int el = 0;
for(int c=0; c<4; ++c)
for(int r=0; r<4; ++r)
m[el++] = M[r][c];
}
inline OpenGlMatrix::operator const TooN::SE3<>() const
{
const TooN::Matrix<4,4> m = *this;
const TooN::SO3<> R(m.slice<0,0,3,3>());
const TooN::Vector<3> t = m.T()[3].slice<0,3>();
return TooN::SE3<>(R,t);
}
inline OpenGlMatrix::operator const TooN::Matrix<4,4>() const
{
TooN::Matrix<4,4> M;
int el = 0;
for( int c=0; c<4; ++c )
for( int r=0; r<4; ++r )
M(r,c) = m[el++];
return M;
}
PANGOLIN_DEPRECATED
inline OpenGlMatrixSpec FromTooN(const TooN::SE3<>& T_cw)
{
TooN::Matrix<4,4,GLprecision,TooN::ColMajor> M;
M.slice<0,0,3,3>() = T_cw.get_rotation().get_matrix();
M.T()[3].slice<0,3>() = T_cw.get_translation();
M[3] = TooN::makeVector(0,0,0,1);
OpenGlMatrixSpec P;
P.type = GlModelViewStack;
std::memcpy(P.m, &(M[0][0]),16*sizeof(GLprecision));
return P;
}
PANGOLIN_DEPRECATED
inline OpenGlMatrixSpec FromTooN(OpenGlStack type, const TooN::Matrix<4,4>& M)
{
// Read in remembering col-major convension for our matrices
OpenGlMatrixSpec P;
P.type = type;
int el = 0;
for(int c=0; c<4; ++c)
for(int r=0; r<4; ++r)
P.m[el++] = M[r][c];
return P;
}
PANGOLIN_DEPRECATED
inline TooN::Matrix<4,4> ToTooN(const OpenGlMatrix& ms)
{
TooN::Matrix<4,4> m;
int el = 0;
for( int c=0; c<4; ++c )
for( int r=0; r<4; ++r )
m(r,c) = ms.m[el++];
return m;
}
PANGOLIN_DEPRECATED
inline TooN::SE3<> ToTooN_SE3(const OpenGlMatrix& ms)
{
TooN::Matrix<4,4> m = ms;
const TooN::SO3<> R(m.slice<0,0,3,3>());
const TooN::Vector<3> t = m.T()[3].slice<0,3>();
return TooN::SE3<>(R,t);
}
#endif // HAVE_TOON
#ifdef HAVE_OCULUS
inline OpenGlMatrix::OpenGlMatrix(const OVR::Matrix4f& mat)
{
for(int r=0; r<4; ++r )
for(int c=0; c<4; ++c )
m[c*4+r] = mat.M[r][c];
}
inline OpenGlMatrix::operator const OVR::Matrix4f() const
{
OVR::Matrix4f mat;
for(int r=0; r<4; ++r )
for(int c=0; c<4; ++c )
mat.M[r][c] = m[c*4+r];
return mat;
}
#endif // HAVE_OCULUS
}

View File

@@ -0,0 +1,43 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
namespace pangolin
{
class PANGOLIN_EXPORT UserApp
{
public:
virtual ~UserApp() {}
virtual void Init() {}
virtual void Render() = 0;
};
}

View File

@@ -0,0 +1,235 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <functional>
#include <vector>
#include <pangolin/display/viewport.h>
#include <pangolin/display/attach.h>
namespace pangolin
{
enum Layout
{
LayoutOverlay,
LayoutVertical,
LayoutHorizontal,
LayoutEqual,
LayoutEqualVertical,
LayoutEqualHorizontal
};
enum Lock {
LockLeft = 0,
LockBottom = 0,
LockCenter = 1,
LockRight = 2,
LockTop = 2
};
// Forward declarations
struct Handler;
class OpenGlRenderState;
/// A Display manages the location and resizing of an OpenGl viewport.
struct PANGOLIN_EXPORT View
{
View(double aspect=0.0)
: aspect(aspect), top(1.0),left(0.0),right(1.0),bottom(0.0), hlock(LockCenter),vlock(LockCenter),
layout(LayoutOverlay), scroll_offset(0), show(1), zorder(0), handler(0), scroll_show(1) {}
virtual ~View() {}
//! Activate Displays viewport for drawing within this area
void Activate() const;
//! Activate Displays and set State Matrices
void Activate(const OpenGlRenderState& state ) const;
//! Activate Displays viewport and Scissor for drawing within this area
void ActivateAndScissor() const;
//! Activate Displays viewport and Scissor for drawing within this area
void ActivateScissorAndClear() const;
//! Activate Display and set State Matrices
void ActivateAndScissor(const OpenGlRenderState& state ) const;
//! Activate Display and set State Matrices
void ActivateScissorAndClear(const OpenGlRenderState& state ) const;
//! Activate Display and setup coordinate system for 2d pixel View coordinates
void ActivatePixelOrthographic() const;
//! Activate Display and reset coordinate system to OpenGL default
void ActivateIdentity() const;
//! Return closest depth buffer value within radius of window (winx,winy)
GLfloat GetClosestDepth(int winx, int winy, int radius) const;
//! Obtain camera space coordinates of scene at pixel (winx, winy, winzdepth)
//! winzdepth can be obtained from GetClosestDepth
void GetCamCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const;
//! Obtain object space coordinates of scene at pixel (winx, winy, winzdepth)
//! winzdepth can be obtained from GetClosestDepth
void GetObjectCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const;
//! Given the specification of Display, compute viewport
virtual void Resize(const Viewport& parent);
//! Instruct all children to resize
virtual void ResizeChildren();
//! Perform any automatic rendering for this View.
//! Default implementation simply instructs children to render themselves.
virtual void Render();
//! Instruct all children to render themselves if appropriate
virtual void RenderChildren();
//! Set this view as the active View to receive input
View& SetFocus();
//! Returns true iff this view currently has focus and will receive user input
bool HasFocus() const;
//! Set bounds for the View using mixed fractional / pixel coordinates (OpenGl view coordinates)
View& SetBounds(Attach bottom, Attach top, Attach left, Attach right);
//! Set bounds for the View using mixed fractional / pixel coordinates (OpenGl view coordinates)
View& SetBounds(Attach bottom, Attach top, Attach left, Attach right, bool keep_aspect);
//! Set bounds for the View using mixed fractional / pixel coordinates (OpenGl view coordinates)
View& SetBounds(Attach bottom, Attach top, Attach left, Attach right, double aspect);
//! Designate handler for accepting mouse / keyboard input.
View& SetHandler(Handler* handler);
//! Set drawFunc as the drawing function for this view
View& SetDrawFunction(const std::function<void(View&)>& drawFunc);
//! Force this view to have the given aspect, whilst fitting snuggly
//! within the parent. A negative value with 'over-draw', fitting the
//! smaller side of the parent.
View& SetAspect(double aspect);
//! Set how this view should be positioned relative to its parent
View& SetLock(Lock horizontal, Lock vertical );
//! Set layout policy for this view
View& SetLayout(Layout layout);
//! Add view as child
View& AddDisplay(View& view);
//! Show / hide this view
View& Show(bool show=true);
//! Toggle this views visibility
void ToggleShow();
//! Return whether this view should be shown.
//! This method should be checked if drawing manually
bool IsShown() const;
//! Returns viewport reflecting space that will actually get drawn
//! The minimum of vp and v
Viewport GetBounds() const;
//! Specify that this views region in the framebuffer should be saved to
//! a file just before the buffer is flipped.
void SaveOnRender(const std::string& filename_prefix);
//! Specify that this views region in the framebuffer should be saved to
//! a video just before the buffer is flipped
void RecordOnRender(const std::string& record_uri);
//! Uses the views default render method to draw into an FBO 'scale' times
//! the size of the view and save to a file.
void SaveRenderNow(const std::string& filename_prefix, float scale = 1);
//! Return number of child views attached to this view
size_t NumChildren() const;
//! Return (i)th child of this view
View& operator[](size_t i);
//! Return number of visible child views attached to this view.
size_t NumVisibleChildren() const;
//! Return visible child by index.
View& VisibleChild(size_t i);
//! Return visible child at window coords x,y
View* FindChild(int x, int y);
// Desired width / height aspect (0 if dynamic)
double aspect;
// Bounds to fit display within
Attach top, left, right, bottom;
Lock hlock;
Lock vlock;
Layout layout;
int scroll_offset;
// Cached client area (space allocated from parent)
Viewport vp;
// Cached absolute viewport (recomputed on resize - respects aspect)
Viewport v;
// Should this view be displayed?
bool show;
// Child views are rendered in order of low to high z-order
// Views default to 0 z-order
int zorder;
// Input event handler (if any)
Handler* handler;
// Map for sub-displays (if any)
std::vector<View*> views;
// External draw function
std::function<void(View&)> extern_draw_function;
private:
// Private copy constructor
View(View&) { /* Do Not copy - take reference instead*/ }
bool scroll_show;
};
}

View File

@@ -0,0 +1,65 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glinclude.h>
#include <pangolin/display/opengl_render_state.h>
namespace pangolin
{
/// Encapsulates OpenGl Viewport.
struct PANGOLIN_EXPORT Viewport
{
Viewport() : l(0),b(0),w(0),h(0) {}
Viewport(GLint l,GLint b,GLint w,GLint h) : l(l),b(b),w(w),h(h) {}
void Activate() const;
void ActivateIdentity() const;
void ActivatePixelOrthographic() const;
void Scissor() const;
void ActivateAndScissor() const;
bool Contains(int x, int y) const;
Viewport Inset(int i) const;
Viewport Inset(int horiz, int vert) const;
Viewport Intersect(const Viewport& vp) const;
void GetCamCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const;
static void DisableScissor();
GLint r() const { return l+w;}
GLint t() const { return b+h;}
GLfloat aspect() const { return (GLfloat)w / (GLfloat)h; }
GLint l,b,w,h;
};
}

View File

@@ -0,0 +1,141 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/display/view.h>
#include <pangolin/var/var.h>
#include <pangolin/handler/handler.h>
#include <pangolin/gl/glfont.h>
#include <functional>
namespace pangolin
{
PANGOLIN_EXPORT
View& CreatePanel(const std::string& name);
struct PANGOLIN_EXPORT Panel : public View
{
Panel();
Panel(const std::string& auto_register_var_prefix);
void Render();
void ResizeChildren();
static void AddVariable(void* data, const std::string& name, VarValueGeneric& var, bool brand_new);
};
template<typename T>
struct Widget : public View, Handler, Var<T>
{
Widget(std::string title, VarValueGeneric& tv)
: Var<T>(tv), title(title)
{
handler = this;
}
std::string title;
};
struct PANGOLIN_EXPORT Button : public Widget<bool>
{
Button(std::string title, VarValueGeneric& tv);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void Render();
//Cache params on resize
void ResizeChildren();
GlText gltext;
GLfloat raster[2];
bool down;
};
struct PANGOLIN_EXPORT FunctionButton : public Widget<std::function<void(void)> >
{
FunctionButton(std::string title, VarValueGeneric& tv);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void Render();
//Cache params on resize
void ResizeChildren();
GlText gltext;
GLfloat raster[2];
bool down;
};
struct PANGOLIN_EXPORT Checkbox : public Widget<bool>
{
Checkbox(std::string title, VarValueGeneric& tv);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void Render();
//Cache params on resize
void ResizeChildren();
GlText gltext;
GLfloat raster[2];
Viewport vcb;
};
struct PANGOLIN_EXPORT Slider : public Widget<double>
{
Slider(std::string title, VarValueGeneric& tv);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void MouseMotion(View&, int x, int y, int mouse_state);
void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
void Render();
//Cache params on resize
void ResizeChildren();
GlText gltext;
GLfloat raster[2];
bool lock_bounds;
bool logscale;
bool is_integral_type;
};
struct PANGOLIN_EXPORT TextInput : public Widget<std::string>
{
TextInput(std::string title, VarValueGeneric& tv);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void MouseMotion(View&, int x, int y, int mouse_state);
void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
void Render();
std::string edit;
GlText gledit;
//Cache params on resize
void ResizeChildren();
GlText gltext;
GLfloat raster[2];
bool can_edit;
bool do_edit;
int sel[2];
};
}

View File

@@ -0,0 +1,90 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2016 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <exception>
#include <pangolin/platform.h>
#include <string>
namespace pangolin
{
class GlContextInterface
{
public:
virtual ~GlContextInterface() {}
};
class WindowInterface
{
public:
virtual ~WindowInterface() {}
virtual void ToggleFullscreen() = 0;
virtual void Move(int x, int y) = 0;
virtual void Resize(unsigned int w, unsigned int h) = 0;
/**
* @brief MakeCurrent set the current context
* to be called in a thread before accessing OpenGL
*/
virtual void MakeCurrent() = 0;
/**
* @brief RemoveCurrent remove the current context
* to be called at the end of a thread
*/
virtual void RemoveCurrent() = 0;
virtual void ProcessEvents() = 0;
virtual void SwapBuffers() = 0;
};
struct PANGOLIN_EXPORT WindowException : std::exception
{
WindowException(std::string str) : desc(str) {}
WindowException(std::string str, std::string detail) {
desc = str + "\n\t" + detail;
}
~WindowException() throw() {}
const char* what() const throw() { return desc.c_str(); }
std::string desc;
};
struct PANGOLIN_EXPORT WindowExceptionNoKnownHandler : public WindowException
{
WindowExceptionNoKnownHandler(const std::string& scheme)
: WindowException("No known window handler for URI '" + scheme + "'")
{
}
};
}

View File

@@ -0,0 +1,114 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011-2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <memory>
#include <vector>
#include <algorithm>
#include <pangolin/utils/uri.h>
namespace pangolin
{
template<typename T>
struct FactoryInterface
{
typedef T FactoryItem;
virtual ~FactoryInterface() = default;
virtual std::unique_ptr<T> Open(const Uri& uri) = 0;
};
template<typename T>
class FactoryRegistry
{
public:
// IMPORTANT: Implement for each templated instantiation within a seperate compilation unit.
static FactoryRegistry<T>& I();
~FactoryRegistry()
{
}
void RegisterFactory(std::shared_ptr<FactoryInterface<T>> factory, uint32_t precedence, const std::string& scheme_name )
{
FactoryItem item = {precedence, scheme_name, factory};
factories.push_back( item );
std::sort(factories.begin(), factories.end());
}
void UnregisterFactory(FactoryInterface<T>* factory)
{
for( auto i = factories.end()-1; i != factories.begin(); --i)
{
if( i->factory.get() == factory ) {
factories.erase(i);
}
}
}
void UnregisterAllFactories()
{
factories.clear();
}
std::unique_ptr<T> Open(const Uri& uri)
{
// Iterate over all registered factories in order of precedence.
for(auto& item : factories) {
if( item.scheme == uri.scheme) {
std::unique_ptr<T> video = item.factory->Open(uri);
if(video) {
return video;
}
}
}
return std::unique_ptr<T>();
}
private:
struct FactoryItem
{
uint32_t precedence;
std::string scheme;
std::shared_ptr<FactoryInterface<T>> factory;
bool operator<(const FactoryItem& rhs) const {
return precedence < rhs.precedence;
}
};
// Priority, Factory tuple
std::vector<FactoryItem> factories;
};
#define PANGOLIN_REGISTER_FACTORY(x) void Register ## x ## Factory()
}

View File

@@ -0,0 +1,95 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PANGOLIN_GEOMETRY_H
#define PANGOLIN_GEOMETRY_H
#include <map>
#include <unordered_map>
#include <vector>
#include <pangolin/image/typed_image.h>
#include <pangolin/compat/variant.h>
#ifdef HAVE_EIGEN
#include <Eigen/Geometry>
#endif
namespace pangolin
{
struct Geometry
{
struct Element : public ManagedImage<uint8_t> {
Element() = default;
Element(Element&&) = default;
Element& operator=(Element&&) = default;
Element(size_t stride_bytes, size_t num_elements)
: ManagedImage<uint8_t>(stride_bytes, num_elements)
{}
using Attribute = variant<Image<float>,Image<uint32_t>,Image<uint16_t>,Image<uint8_t>>;
// "vertex", "rgb", "normal", "uv", "tris", "quads", ...
std::map<std::string, Attribute> attributes;
};
// Store vertices and attributes
std::map<std::string, Element> buffers;
// Stores index buffers for each sub-object
std::multimap<std::string, Element> objects;
// Stores pixmaps
std::map<std::string, TypedImage> textures;
};
pangolin::Geometry::Element::Attribute MakeAttribute(uint32_t gldatatype, size_t num_items, size_t count_per_item, void* ptr, size_t pitch_bytes);
pangolin::Geometry LoadGeometry(const std::string& filename);
#ifdef HAVE_EIGEN
inline Eigen::AlignedBox3f GetAxisAlignedBox(const Geometry& geom)
{
Eigen::AlignedBox3f box;
box.setEmpty();
for(const auto& b : geom.buffers) {
const auto& it_vert = b.second.attributes.find("vertex");
if(it_vert != b.second.attributes.end()) {
const Image<float>& vs = get<Image<float>>(it_vert->second);
for(size_t i=0; i < vs.h; ++i) {
const Eigen::Map<const Eigen::Vector3f> v(vs.RowPtr(i));
box.extend(v);
}
}
}
return box;
}
#endif
}
#endif // PANGOLIN_GEOMETRY_H

View File

@@ -0,0 +1,34 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <pangolin/geometry/geometry.h>
namespace pangolin {
pangolin::Geometry LoadGeometryObj(const std::string& filename);
}

View File

@@ -0,0 +1,165 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <pangolin/platform.h>
#include <pangolin/compat/variant.h>
#include <pangolin/geometry/geometry.h>
#include <fstream>
#include <vector>
#include <algorithm>
namespace pangolin
{
#define PLY_GROUP_LIST(m) m(PlyHeader) m(PlyFormat) m(PlyType)
#define PLY_HEADER_LIST(m) m(ply) m(format) m(comment) m(property) m(element) m(end_header)
#define PLY_FORMAT_LIST(m) m(ascii) m(binary_big_endian) m(binary_little_endian)
#define PLY_TYPE_LIST(m) m(char) m(int8) m(uchar) m(uint8) m(short) m(int16) m(ushort) m(uint16) m(int) m(int32) m(uint) m(uint32) m(float) m(float32) m(double) m(float64) m(list)
// Define Enums / strings
enum PlyHeader {
#define FORMAT_ENUM(x) PlyHeader_##x,
PLY_HEADER_LIST(FORMAT_ENUM)
PlyHeaderSize
#undef FORMAT_ENUM
};
enum PlyFormat {
#define FORMAT_ENUM(x) PlyFormat_##x,
PLY_FORMAT_LIST(FORMAT_ENUM)
PlyFormatSize
#undef FORMAT_ENUM
};
enum PlyType {
#define FORMAT_ENUM(x) PlyType_##x,
PLY_TYPE_LIST(FORMAT_ENUM)
PlyTypeSize
#undef FORMAT_ENUM
};
const size_t PlyTypeGl[] = {
// char, int8 -> GL_BYTE
0x1400, 0x1400,
// uchar, uint8 -> GL_UNSIGNED_BYTE
0x1401, 0x1401,
// short, int16 -> GL_SHORT
0x1402, 0x1402,
// ushort, uint16 -> GL_UNSIGNED_SHORT
0x1403, 0x1403,
// int, int32 -> GL_INT
0x1404, 0x1404,
// uint, uint32 -> GL_UNSIGNED_INT
0x1405, 0x1405,
// float, float32 -> GL_FLOAT
0x1406, 0x1406,
// double, float64 -> GL_DOUBLE
0x140A, 0x140A,
// list -> GL_NONE
0
};
#undef FORMAT_ENUM
struct PlyPropertyDetails
{
std::string name;
// Type of property (GLenum)
size_t type;
// Type of list index if a list, or 0 otherwise. (GLenum)
size_t list_index_type;
// Offset from element start
size_t offset_bytes;
// Number of items in the list. 1 if not a list. -1 if unknown.
int num_items;
bool isList() const {
return list_index_type > 0;
}
};
struct PlyElementDetails
{
std::string name;
int num_items;
int stride_bytes;
std::vector<PlyPropertyDetails> properties;
inline std::vector<PlyPropertyDetails>::iterator FindProperty(const std::string& name)
{
return std::find_if(properties.begin(), properties.end(),
[&name](const PlyPropertyDetails& p){ return p.name == name;}
);
}
};
struct PlyHeaderDetails
{
PlyFormat format;
std::string version;
std::vector<PlyElementDetails> elements;
inline std::vector<PlyElementDetails>::iterator FindElement(const std::string& name)
{
return std::find_if(elements.begin(), elements.end(),
[&name](const PlyElementDetails& el){ return el.name == name;}
);
}
};
void ParsePlyHeader(PlyHeaderDetails& ply, std::istream& is);
struct PlyBuffer
{
size_t index_size_bytes;
size_t element_item_size_bytes;
std::vector<unsigned char> data;
};
void ParsePlyAscii(pangolin::Geometry& /*geom*/, const PlyHeaderDetails& /*ply*/, std::istream& /*is*/);
// Convert Seperate "x","y","z" attributes into a single "vertex" attribute
void StandardizeXyzToVertex(pangolin::Geometry& geom);
// The Artec scanner saves with these attributes, for example
void StandardizeMultiTextureFaceToXyzuv(pangolin::Geometry& geom);
void Standardize(pangolin::Geometry& geom);
void ParsePlyLE(pangolin::Geometry& geom, PlyHeaderDetails& ply, std::istream& is);
void ParsePlyBE(pangolin::Geometry& /*geom*/, const PlyHeaderDetails& /*ply*/, std::istream& /*is*/);
void AttachAssociatedTexturesPly(pangolin::Geometry& geom, const std::string& filename);
pangolin::Geometry LoadGeometryPly(const std::string& filename);
}

View File

@@ -0,0 +1,87 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/geometry/geometry.h>
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glsl.h>
namespace pangolin {
struct GlGeometry
{
GlGeometry() = default;
GlGeometry(GlGeometry&&) = default;
GlGeometry& operator=(GlGeometry&&) = default;
struct Element : public GlBufferData
{
Element() = default;
Element(Element&&) = default;
Element& operator=(Element&&) = default;
Element(GlBufferType buffer_type, size_t size_bytes, GLenum gluse, uint8_t* data)
: GlBufferData(buffer_type, size_bytes, gluse, data)
{}
inline bool HasAttribute(const std::string& name) const {
return attributes.find(name) != attributes.end();
}
struct Attribute {
// Stuff needed by glVertexAttribPointer
GLenum gltype;
size_t count_per_element;
size_t num_elements;
size_t offset;
size_t stride_bytes;
};
std::map<std::string, Attribute> attributes;
};
inline bool HasAttribute(const std::string& name) const
{
for(const auto& b : buffers) if(b.second.HasAttribute(name)) return true;
return false;
}
// Store vertices and attributes
std::map<std::string, Element> buffers;
// Stores index buffers for each sub-object
std::multimap<std::string, Element> objects;
// Stores pixmaps
std::map<std::string, GlTexture> textures;
};
GlGeometry::Element ToGlGeometry(const Geometry::Element& el, GlBufferType buffertype);
GlGeometry ToGlGeometry(const Geometry& geom);
void GlDraw(GlSlProgram& prog, const GlGeometry& geom, const GlTexture *matcap);
}

View File

@@ -0,0 +1,283 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <sstream>
#include <algorithm>
// Cg includes
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include "gl.h"
#ifdef HAVE_TOON
#include <TooN/TooN.h>
#endif // HAVE_TOON
namespace pangolin
{
////////////////////////////////////////////////
// Interface
////////////////////////////////////////////////
/// Lightweight object wrapper for NVidia Cg Shader program objects.
class CgProgram
{
friend class CgLoader;
public:
void SetUniform(const std::string& name, GlTexture& tex);
void SetUniform(const std::string& name, float f);
void SetUniform(const std::string& name, float v0, float v1);
void SetUniform(const std::string& name, float v0, float v1, float v2, float v3);
#ifdef HAVE_TOON
void SetUniform(const std::string& name, const TooN::Vector<2>& v );
void SetUniform(const std::string& name, const TooN::Vector<3>& v );
template <int R, int C>
void SetUniform(const std::string& name, const TooN::Matrix<R,C>& M );
#endif
void UpdateParams();
protected:
CGprogram mProg;
CGcontext mContext;
CGprofile mProfile;
};
class CgLoader
{
public:
CgLoader();
~CgLoader();
// Call AFTER glewInit (or similar)
void Initialise();
CgProgram LoadProgramFromFile(const std::string& file, const std::string& function, bool isVertexShader );
void EnableProgram(CgProgram program);
void DisablePrograms();
void RenderDummyQuad();
void RenderDummyQuadWithTexCoords(int w, int h);
protected:
CGcontext mContext;
CGprofile mFragmentProfile;
CGprofile mVertexProfile;
};
////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////
inline bool cgOkay()
{
CGerror error;
const char *string = cgGetLastErrorString(&error);
if (error != CG_NO_ERROR) {
std::cout << "CG Error: " << string << std::endl;
// assert(0);
return false;
}
return true;
}
inline CgLoader::CgLoader()
:mContext(0)
{
}
inline CgLoader::~CgLoader()
{
if(mContext)
{
// Destroying context destroys all programs associated with it
cgDestroyContext(mContext);
}
}
inline void CgLoader::Initialise()
{
mContext = cgCreateContext();
cgSetParameterSettingMode(mContext, CG_DEFERRED_PARAMETER_SETTING);
cgOkay();
mFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
cgGLSetOptimalOptions(mFragmentProfile);
cgOkay();
mVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
cgGLSetOptimalOptions(mVertexProfile);
cgOkay();
}
inline CgProgram CgLoader::LoadProgramFromFile(const std::string& file, const std::string& function, bool isVertexShader )
{
if( !mContext ) {
Initialise();
}
CgProgram prog;
prog.mContext = mContext;
prog.mProfile = isVertexShader ? mVertexProfile : mFragmentProfile;
prog.mProg = cgCreateProgramFromFile( prog.mContext, CG_SOURCE, file.c_str(), prog.mProfile, function.c_str(), NULL);
if( !cgOkay() )
{
std::cout << cgGetLastListing(mContext) << std::endl;
assert(0);
}
cgGLLoadProgram(prog.mProg);
if( !cgOkay() )
{
const char* err = cgGetProgramString( prog.mProg, CG_COMPILED_PROGRAM );
int pos;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
std::cout << err << std::endl;
std::cout << "@ " << pos << std::endl;
assert(0);
}
return prog;
}
inline void CgLoader::EnableProgram(CgProgram program)
{
cgGLBindProgram(program.mProg);
cgGLEnableProfile(program.mProfile);
cgOkay();
}
inline void CgLoader::DisablePrograms()
{
cgGLDisableProfile(mFragmentProfile);
cgGLDisableProfile(mVertexProfile);
}
inline void CgLoader::RenderDummyQuad()
{
glBegin(GL_QUADS);
glVertex2d(-1,1);
glVertex2d(1,1);
glVertex2d(1,-1);
glVertex2d(-1,-1);
glEnd();
}
inline void CgLoader::RenderDummyQuadWithTexCoords(int w, int h)
{
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2d(-1,-1);
glTexCoord2f(w, 0);
glVertex2d(1,-1);
glTexCoord2f(w, h);
glVertex2d(1,1);
glTexCoord2f(0, h);
glVertex2d(-1,1);
glEnd();
}
void CgProgram::SetUniform(const std::string& name, float f)
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgSetParameter1f( p, f );
cgUpdateProgramParameters(mProg);
}
void CgProgram::SetUniform(const std::string& name, GlTexture& tex)
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgGLSetTextureParameter(p, tex.tid );
cgGLEnableTextureParameter(p);
cgUpdateProgramParameters(mProg);
}
void CgProgram::SetUniform(const std::string& name, float v0, float v1, float v2, float v3)
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgGLSetParameter4f(p, v0,v1,v2,v3);
cgUpdateProgramParameters(mProg);
}
void CgProgram::SetUniform(const std::string& name, float v0, float v1)
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgGLSetParameter2f(p, v0,v1);
cgUpdateProgramParameters(mProg);
}
#ifdef HAVE_TOON
void CgProgram::SetUniform(const std::string& name, const TooN::Vector<2>& v )
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgGLSetParameter2f(p, v[0],v[1] );
cgUpdateProgramParameters(mProg);
}
void CgProgram::SetUniform(const std::string& name, const TooN::Vector<3>& v )
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
cgGLSetParameter3f(p, v[0],v[1],v[2] );
cgUpdateProgramParameters(mProg);
}
template <int R, int C>
void CgProgram::SetUniform(const std::string& name, const TooN::Matrix<R,C>& M )
{
CGparameter p = cgGetNamedParameter( mProg, name.c_str());
float Mdata[R*C];
int i=0;
for( int r=0; r<R; ++r )
for( int c=0; c<C; ++c )
Mdata[i++] = (float)(M[r][c]);
cgGLSetMatrixParameterfr(p, Mdata );
cgUpdateProgramParameters(mProg);
}
#endif
void CgProgram::UpdateParams()
{
cgUpdateProgramParameters(mProg);
}
}

View File

@@ -0,0 +1,178 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <cmath>
#include <stdexcept>
namespace pangolin
{
/// Represent OpenGL floating point colour: Red, Green and Blue with alpha.
struct Colour
{
inline static Colour White() {
return Colour(1.0f,1.0f,1.0f,1.0f);
}
inline static Colour Black() {
return Colour(0.0f,0.0f,0.0f,1.0f);
}
inline static Colour Red() {
return Colour(1.0f,0.0f,0.0f,1.0f);
}
inline static Colour Green() {
return Colour(0.0f,1.0f,0.0f,1.0f);
}
inline static Colour Blue() {
return Colour(0.0f,0.0f,1.0f,1.0f);
}
inline static Colour Unspecified() {
return Colour(
std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::quiet_NaN(),
std::numeric_limits<float>::quiet_NaN(), std::numeric_limits<float>::quiet_NaN()
);
}
/// Default constructs white.
inline Colour()
: red(1.0f), green(1.0f), blue(1.0f), alpha(1.0f)
{
}
/// Construct from component values
inline Colour(const float red, const float green, const float blue, const float alpha = 1.0f)
: red(red), green(green), blue(blue), alpha(alpha)
{
}
/// Construct from rgba array.
inline Colour(const float rgba[4])
{
r = rgba[0];
g = rgba[1];
b = rgba[2];
a = rgba[3];
}
/// Return pointer to OpenGL compatible RGBA array.
inline float* Get()
{
return c;
}
/// Return this colour with alpha adjusted.
inline Colour WithAlpha(const float alpha)
{
return Colour(r,g,b,alpha);
}
/// Construct from HSV Colour
/// @param hue Colour hue in range [0,1]
/// @param sat Saturation in range [0,1]
/// @param val Value / Brightness in range [0,1].
static inline Colour Hsv(const float hue, const float sat = 1.0f, const float val = 1.0f, const float alpha = 1.0f)
{
const float h = 6.0f * hue;
const int i = (int)floor(h);
const float f = (i%2 == 0) ? 1-(h-i) : h-i;
const float m = val * (1-sat);
const float n = val * (1-sat*f);
switch(i)
{
case 0: return Colour(val,n,m,alpha);
case 1: return Colour(n,val,m,alpha);
case 2: return Colour(m,val,n,alpha);
case 3: return Colour(m,n,val,alpha);
case 4: return Colour(n,m,val,alpha);
case 5: return Colour(val,m,n,alpha);
default:
throw std::runtime_error("Found extra colour in rainbow.");
}
}
union {
struct {
float red;
float green;
float blue;
float alpha;
};
struct {
float r;
float g;
float b;
float a;
};
float c[4];
};
};
/// A ColourWheel is like a continuous colour palate that can be sampled.
/// In the future, different ColourWheels will be supported, but this one
/// is based on sampling hues in HSV colourspace. An indefinite number of
/// unique colours are sampled using the golden angle.
class ColourWheel
{
public:
/// Construct ColourWheel with Saturation, Value and Alpha constant.
inline ColourWheel(float saturation = 0.5f, float value = 1.0f, float alpha = 1.0f)
: unique_colours(0), sat(saturation), val(value), alpha(alpha)
{
}
/// Use Golden ratio (/angle) to pick well spaced colours.
inline Colour GetColourBin(int i) const
{
float hue = i * 0.5f * (3.0f - sqrt(5.0f));
hue -= (int)hue;
return Colour::Hsv(hue,sat,val,alpha);
}
/// Return next unique colour from ColourWheel.
inline Colour GetUniqueColour()
{
return GetColourBin(unique_colours++);
}
/// Reset colour wheel counter to initial state
inline void Reset() {
unique_colours = 0;
}
protected:
int unique_colours;
float sat;
float val;
float alpha;
};
}

View File

@@ -0,0 +1,320 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <stack>
#include <pangolin/opengl_render_state.h>
#include <pangolin/glsl.h>
namespace pangolin {
class GlEngine
{
public:
const char* vert =
"attribute vec4 a_position;\n"
"attribute vec4 a_color;\n"
"attribute vec3 a_normal;\n"
"attribute vec2 a_texcoord;\n"
"uniform vec4 u_color;\n"
"uniform mat4 u_modelViewMatrix;\n"
"uniform mat4 u_modelViewProjectionMatrix;\n"
"varying vec4 v_frontColor;\n"
"varying vec2 v_texcoord;\n"
"void main() {\n"
" gl_Position = u_modelViewProjectionMatrix * a_position;\n"
" v_frontColor = u_color;\n"
" v_texcoord = a_texcoord;\n"
"}\n";
const char* frag =
#ifdef HAVE_GLES_2
"precision mediump float;\n"
#endif // HAVE_GLES_2
"varying vec4 v_frontColor;\n"
"varying vec2 v_texcoord;\n"
"uniform sampler2D u_texture;\n"
"uniform bool u_textureEnable;\n"
"void main() {\n"
" gl_FragColor = v_frontColor;\n"
" if(u_textureEnable) {\n"
" gl_FragColor *= texture2D(u_texture, v_texcoord);\n"
" }\n"
"}\n";
GlEngine()
{
// Initialise default state
projection.push(IdentityMatrix());
modelview.push(IdentityMatrix());
currentmatrix = &modelview;
// Set GL_TEXTURE0 as default active texture
glActiveTexture(GL_TEXTURE0);
// Compile and link shaders
prog_fixed.AddShader(GlSlVertexShader, vert);
prog_fixed.AddShader(GlSlFragmentShader, frag);
prog_fixed.BindPangolinDefaultAttribLocationsAndLink();
// Save locations of uniforms
u_color = prog_fixed.GetUniformHandle("u_color");
u_modelViewMatrix = prog_fixed.GetUniformHandle("u_modelViewMatrix");
u_modelViewProjectionMatrix = prog_fixed.GetUniformHandle("u_modelViewProjectionMatrix");
u_texture = prog_fixed.GetUniformHandle("u_texture");
u_textureEnable = prog_fixed.GetUniformHandle("u_textureEnable");
// Initialise default uniform values
UpdateMatrices();
SetColor(1.0,1.0,1.0,1.0);
}
void UpdateMatrices()
{
OpenGlMatrix pmv = projection.top() * modelview.top();
prog_fixed.SaveBind();
glUniformMatrix4fv( u_modelViewMatrix, 1, false, modelview.top().m );
glUniformMatrix4fv( u_modelViewProjectionMatrix, 1, false, pmv.m );
prog_fixed.Unbind();
}
void SetColor(float r, float g, float b, float a)
{
prog_fixed.SaveBind();
glUniform4f( u_color, r, g, b, a);
prog_fixed.Unbind();
}
void EnableTexturing(GLboolean v)
{
prog_fixed.SaveBind();
glUniform1i( u_textureEnable, v);
prog_fixed.Unbind();
}
//protected:
std::stack<OpenGlMatrix> projection;
std::stack<OpenGlMatrix> modelview;
std::stack<OpenGlMatrix>* currentmatrix;
GLenum matrixmode;
float color[4];
GlSlProgram prog_fixed;
GLint u_color;
GLint u_modelViewMatrix;
GLint u_modelViewProjectionMatrix;
GLint u_texture;
GLint u_textureEnable;
};
GlEngine& glEngine();
}
///////////////////////////////////////////////////////////////////////////////
// OpenGL 1.0 compatibility - Emulate fixed pipeline
///////////////////////////////////////////////////////////////////////////////
// Missing defines that we'll be using
#define GL_MODELVIEW 0x1700
#define GL_PROJECTION 0x1701
#define GL_SHADE_MODEL 0x0B54
#define GL_POINT_SIZE 0x0B11
#define GL_MULTISAMPLE 0x809D
#define GL_LIGHTING 0x0B50
#define GL_POINT_SMOOTH 0x0B10
#define GL_LINE_SMOOTH 0x0B20
#define GL_SCISSOR_TEST 0x0C11
#define GL_COLOR_MATERIAL 0x0B57
#define GL_FLAT 0x1D00
#define GL_SMOOTH 0x1D01
#define GL_MODULATE 0x2100
#define GL_DECAL 0x2101
#define GL_ADD 0x0104
#define GL_TEXTURE_ENV_MODE 0x2200
#define GL_TEXTURE_ENV_COLOR 0x2201
#define GL_TEXTURE_ENV 0x2300
#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
#define GL_POINT_SMOOTH_HINT 0x0C51
#define GL_LINE_SMOOTH_HINT 0x0C52
#define GL_VERTEX_ARRAY 0x8074
#define GL_NORMAL_ARRAY 0x8075
#define GL_COLOR_ARRAY 0x8076
#define GL_TEXTURE_COORD_ARRAY 0x8078
inline void glEnableClientState(GLenum cap)
{
pangolin::GlEngine& gl = pangolin::glEngine();
if(cap == GL_VERTEX_ARRAY) {
glEnableVertexAttribArray(pangolin::DEFAULT_LOCATION_POSITION);
}else if(cap == GL_COLOR_ARRAY) {
glEnableVertexAttribArray(pangolin::DEFAULT_LOCATION_COLOUR);
}else if(cap == GL_NORMAL_ARRAY) {
glEnableVertexAttribArray(pangolin::DEFAULT_LOCATION_NORMAL);
}else if(cap == GL_TEXTURE_COORD_ARRAY) {
glEnableVertexAttribArray(pangolin::DEFAULT_LOCATION_TEXCOORD);
gl.EnableTexturing(true);
}else{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
}
inline void glDisableClientState(GLenum cap)
{
pangolin::GlEngine& gl = pangolin::glEngine();
if(cap == GL_VERTEX_ARRAY) {
glDisableVertexAttribArray(pangolin::DEFAULT_LOCATION_POSITION);
}else if(cap == GL_COLOR_ARRAY) {
glDisableVertexAttribArray(pangolin::DEFAULT_LOCATION_COLOUR);
}else if(cap == GL_NORMAL_ARRAY) {
glDisableVertexAttribArray(pangolin::DEFAULT_LOCATION_NORMAL);
}else if(cap == GL_TEXTURE_COORD_ARRAY) {
glDisableVertexAttribArray(pangolin::DEFAULT_LOCATION_TEXCOORD);
gl.EnableTexturing(false);
}else{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
}
inline void glVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
{
glVertexAttribPointer(pangolin::DEFAULT_LOCATION_POSITION, size, type, GL_FALSE, stride, pointer);
}
inline void glTexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)
{
glVertexAttribPointer(pangolin::DEFAULT_LOCATION_TEXCOORD, size, type, GL_FALSE, stride, pointer);
}
inline void glMatrixMode(GLenum mode)
{
pangolin::GlEngine& gl = pangolin::glEngine();
gl.currentmatrix = (mode == pangolin::GlProjectionStack) ? &gl.projection : &gl.modelview;
}
inline void glLoadIdentity()
{
pangolin::GlEngine& gl = pangolin::glEngine();
gl.currentmatrix->top() = pangolin::IdentityMatrix();
gl.UpdateMatrices();
}
inline void glLoadMatrixf(const GLfloat* m)
{
pangolin::GlEngine& gl = pangolin::glEngine();
pangolin::GLprecision* cm = gl.currentmatrix->top().m;
for(int i=0; i<16; ++i) cm[i] = (pangolin::GLprecision)m[i];
gl.UpdateMatrices();
}
inline void glLoadMatrixd(const GLdouble* m)
{
pangolin::GlEngine& gl = pangolin::glEngine();
pangolin::GLprecision* cm = gl.currentmatrix->top().m;
for(int i=0; i<16; ++i) cm[i] = (pangolin::GLprecision)m[i];
gl.UpdateMatrices();
}
inline void glMultMatrixf(const GLfloat* m)
{
// pangolin::GlEngine& gl = pangolin::glEngine();
// float res[16];
// pangolin::MatMul<4,4,4,float>(res, m, gl.currentmatrix->m );
// std::memcpy(gl.currentmatrix->m, res, sizeof(float) * 16 );
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
inline void glMultMatrixd(const GLdouble* m)
{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
inline void glPushMatrix(void)
{
pangolin::GlEngine& gl = pangolin::glEngine();
gl.currentmatrix->push(gl.currentmatrix->top());
}
inline void glPopMatrix(void)
{
pangolin::GlEngine& gl = pangolin::glEngine();
gl.currentmatrix->pop();
gl.UpdateMatrices();
}
inline void glTranslatef(GLfloat x, GLfloat y, GLfloat z )
{
pangolin::GlEngine& gl = pangolin::glEngine();
pangolin::GLprecision* cm = gl.currentmatrix->top().m;
cm[12] += x;
cm[13] += y;
cm[14] += z;
gl.UpdateMatrices();
}
inline void glOrtho(
GLdouble l, GLdouble r,
GLdouble b, GLdouble t,
GLdouble n, GLdouble f)
{
pangolin::GlEngine& gl = pangolin::glEngine();
gl.currentmatrix->top() = pangolin::ProjectionMatrixOrthographic(l,r,b,t,n,f);
gl.UpdateMatrices();
}
inline void glColor4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
{
pangolin::glEngine().SetColor(red,green,blue,alpha);
}
inline void glShadeModel( GLenum mode)
{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
inline void glPointSize(GLfloat size)
{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}
inline void glTexEnvf( GLenum target,
GLenum pname,
GLfloat param)
{
pango_print_error("Not Implemented: %s, %s, %d", __FUNCTION__, __FILE__, __LINE__);
}

View File

@@ -0,0 +1,60 @@
#pragma once
#include <pangolin/platform.h>
#define GLdouble GLfloat
#define glClearDepth glClearDepthf
#define glFrustum glFrustumf
#define glColor4fv(a) glColor4f(a[0], a[1], a[2], a[3])
#define glColor3fv(a) glColor4f(a[0], a[1], a[2], 1.0f)
#define glColor3f(a,b,c) glColor4f(a, b, c, 1.0f)
#define GL_CLAMP GL_CLAMP_TO_EDGE
#ifdef HAVE_GLES_2
#define glGenFramebuffersEXT glGenFramebuffers
#define glDeleteFramebuffersEXT glDeleteFramebuffers
#define glBindFramebufferEXT glBindFramebuffer
#define glDrawBuffers glDrawBuffers
#define glFramebufferTexture2DEXT glFramebufferTexture2D
#define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER
#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT16 // <----
#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0
#define GL_DEPTH_ATTACHMENT_EXT GL_DEPTH_ATTACHMENT
#else
#define glOrtho glOrthof
#define glGenFramebuffersEXT glGenFramebuffersOES
#define glDeleteFramebuffersEXT glDeleteFramebuffersOES
#define glBindFramebufferEXT glBindFramebufferOES
#define glDrawBuffers glDrawBuffersOES
#define glFramebufferTexture2DEXT glFramebufferTexture2DOES
#define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER_OES
#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES
#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0_OES
#endif
#define glGetDoublev glGetFloatv
#ifdef HAVE_GLES_2
#include <pangolin/gl2engine.h>
#endif
inline void glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
{
GLfloat verts[] = { x1,y1, x2,y1, x2,y2, x1,y2 };
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, verts);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
}
inline void glRecti(int x1, int y1, int x2, int y2)
{
GLfloat verts[] = { (float)x1,(float)y1, (float)x2,(float)y1,
(float)x2,(float)y2, (float)x1,(float)y2 };
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, verts);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
}

View File

@@ -0,0 +1,273 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/display/viewport.h>
#include <pangolin/gl/glinclude.h>
#include <pangolin/image/image_io.h>
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#endif
#include <cstdlib>
#include <iostream>
#include <math.h>
namespace pangolin
{
////////////////////////////////////////////////
// Interface
////////////////////////////////////////////////
class PANGOLIN_EXPORT GlTexture
{
public:
//! internal_format normally one of GL_RGBA8, GL_LUMINANCE8, GL_INTENSITY16
GlTexture(GLint width, GLint height, GLint internal_format = GL_RGBA8, bool sampling_linear = true, int border = 0, GLenum glformat = GL_RGBA, GLenum gltype = GL_UNSIGNED_BYTE, GLvoid* data = NULL );
// Construct this texture from a CPU image
GlTexture(const TypedImage& img, bool sampling_linear=true);
//! Move Constructor / asignment
GlTexture(GlTexture&& tex);
GlTexture& operator=(GlTexture&& tex);
//! Default constructor represents 'no texture'
GlTexture();
virtual ~GlTexture();
bool IsValid() const;
//! Delete OpenGL resources and fall back to representing 'no texture'
void Delete();
//! Reinitialise teture width / height / format
virtual void Reinitialise(GLsizei width, GLsizei height, GLint internal_format = GL_RGBA8, bool sampling_linear = true, int border = 0, GLenum glformat = GL_RGBA, GLenum gltype = GL_UNSIGNED_BYTE, GLvoid* data = NULL );
void Bind() const;
void Unbind() const;
//! data_layout normally one of GL_LUMINANCE, GL_RGB, ...
//! data_type normally one of GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT
void Upload(const void* image, GLenum data_format = GL_LUMINANCE, GLenum data_type = GL_FLOAT);
//! Upload data to texture, overwriting a sub-region of it.
//! data ptr contains packed data_w x data_h of pixel data.
void Upload(const void* data,
GLsizei tex_x_offset, GLsizei tex_y_offset,
GLsizei data_w, GLsizei data_h,
GLenum data_format, GLenum data_type
);
void Load(const TypedImage& image, bool sampling_linear = true);
void LoadFromFile(const std::string& filename, bool sampling_linear = true);
void Download(void* image, GLenum data_layout = GL_LUMINANCE, GLenum data_type = GL_FLOAT) const;
void Download(TypedImage& image) const;
void CopyFrom(const GlTexture& tex);
void Save(const std::string& filename, bool top_line_first = true);
void SetLinear();
void SetNearestNeighbour();
void RenderToViewport(const bool flip) const;
void RenderToViewport() const;
void RenderToViewport(Viewport tex_vp, bool flipx=false, bool flipy=false) const;
void RenderToViewportFlipY() const;
void RenderToViewportFlipXFlipY() const;
GLint internal_format;
GLuint tid;
GLint width;
GLint height;
private:
// Private copy constructor
GlTexture(const GlTexture&) {}
};
struct PANGOLIN_EXPORT GlRenderBuffer
{
GlRenderBuffer();
GlRenderBuffer(GLint width, GLint height, GLint internal_format = GL_DEPTH_COMPONENT24);
void Reinitialise(GLint width, GLint height, GLint internal_format = GL_DEPTH_COMPONENT24);
//! Move Constructor
GlRenderBuffer(GlRenderBuffer&& tex);
~GlRenderBuffer();
GLint width;
GLint height;
GLuint rbid;
private:
// Private copy constructor
GlRenderBuffer(const GlRenderBuffer&) {}
};
struct PANGOLIN_EXPORT GlFramebuffer
{
GlFramebuffer();
~GlFramebuffer();
GlFramebuffer(GlTexture& colour, GlRenderBuffer& depth);
GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlRenderBuffer& depth);
GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlTexture& colour2, GlRenderBuffer& depth);
GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlTexture& colour2, GlTexture& colour3, GlRenderBuffer& depth);
void Bind() const;
void Unbind() const;
void Reinitialise();
// Attach Colour texture to frame buffer
// Return attachment texture is bound to (e.g. GL_COLOR_ATTACHMENT0_EXT)
GLenum AttachColour(GlTexture& tex);
// Attach Depth render buffer to frame buffer
void AttachDepth(GlRenderBuffer& rb);
GLuint fbid;
unsigned attachments;
};
enum GlBufferType
{
GlUndefined = 0,
GlArrayBuffer = GL_ARRAY_BUFFER, // VBO's, CBO's, NBO's
GlElementArrayBuffer = GL_ELEMENT_ARRAY_BUFFER, // IBO's
#ifndef HAVE_GLES
GlPixelPackBuffer = GL_PIXEL_PACK_BUFFER, // PBO's
GlPixelUnpackBuffer = GL_PIXEL_UNPACK_BUFFER,
GlShaderStorageBuffer = GL_SHADER_STORAGE_BUFFER
#endif
};
// This encapsulates a GL Buffer object.
struct PANGOLIN_EXPORT GlBufferData
{
//! Default constructor represents 'no buffer'
GlBufferData();
GlBufferData(GlBufferType buffer_type, GLuint size_bytes, GLenum gluse = GL_DYNAMIC_DRAW, const unsigned char* data = 0 );
virtual ~GlBufferData();
void Free();
//! Move Constructor
GlBufferData(GlBufferData&& tex);
GlBufferData& operator=(GlBufferData&& tex);
bool IsValid() const;
size_t SizeBytes() const;
void Reinitialise(GlBufferType buffer_type, GLuint size_bytes, GLenum gluse = GL_DYNAMIC_DRAW, const unsigned char* data = 0 );
void Bind() const;
void Unbind() const;
void Upload(const GLvoid* data, GLsizeiptr size_bytes, GLintptr offset = 0);
void Download(GLvoid* ptr, GLsizeiptr size_bytes, GLintptr offset = 0) const;
GLuint bo;
GlBufferType buffer_type;
GLenum gluse;
GLuint size_bytes;
private:
GlBufferData(const GlBufferData&) {}
};
// This encapsulates a GL Buffer object, also storing information about its contents.
// You should try to use GlBufferData instead.
struct PANGOLIN_EXPORT GlBuffer : public GlBufferData
{
//! Default constructor represents 'no buffer'
GlBuffer();
GlBuffer(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse = GL_DYNAMIC_DRAW );
GlBuffer(const GlBuffer&) = delete;
//! Move Constructor
GlBuffer(GlBuffer&& tex);
GlBuffer& operator=(GlBuffer&& tex);
void Reinitialise(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse, const unsigned char* data = nullptr );
void Reinitialise(GlBuffer const& other );
void Resize(GLuint num_elements);
GLenum datatype;
GLuint num_elements;
GLuint count_per_element;
};
class PANGOLIN_EXPORT GlSizeableBuffer
: public pangolin::GlBuffer
{
public:
GlSizeableBuffer(pangolin::GlBufferType buffer_type, GLuint initial_num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse = GL_DYNAMIC_DRAW );
void Clear();
#ifdef USE_EIGEN
template<typename Derived>
void Add(const Eigen::DenseBase<Derived>& vec);
template<typename Derived>
void Update(const Eigen::DenseBase<Derived>& vec, size_t position = 0);
#endif
size_t start() const;
size_t size() const;
protected:
void CheckResize(size_t num_verts);
size_t NextSize(size_t min_size) const;
size_t m_num_verts;
};
size_t GlFormatChannels(GLenum data_layout);
size_t GlDataTypeBytes(GLenum type);
}
// Include implementation
#include <pangolin/gl/gl.hpp>

View File

@@ -0,0 +1,866 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glpixformat.h>
#include <pangolin/display/display.h>
#include <pangolin/image/image_io.h>
#include <algorithm>
#include <stdexcept>
namespace pangolin
{
////////////////////////////////////////////////
// Implementation of gl.h
////////////////////////////////////////////////
#ifndef HAVE_GLES
const int MAX_ATTACHMENTS = 8;
const static GLuint attachment_buffers[] = {
GL_COLOR_ATTACHMENT0_EXT,
GL_COLOR_ATTACHMENT1_EXT,
GL_COLOR_ATTACHMENT2_EXT,
GL_COLOR_ATTACHMENT3_EXT,
GL_COLOR_ATTACHMENT4_EXT,
GL_COLOR_ATTACHMENT5_EXT,
GL_COLOR_ATTACHMENT6_EXT,
GL_COLOR_ATTACHMENT7_EXT
};
#else // HAVE_GLES
const int MAX_ATTACHMENTS = 1;
const static GLuint attachment_buffers[] = {
GL_COLOR_ATTACHMENT0_EXT
};
#endif // HAVE_GLES
const static size_t datatype_bytes[] = {
1, // #define GL_BYTE 0x1400
1, // #define GL_UNSIGNED_BYTE 0x1401
2, // #define GL_SHORT 0x1402
2, // #define GL_UNSIGNED_SHORT 0x1403
4, // #define GL_INT 0x1404
4, // #define GL_UNSIGNED_INT 0x1405
4, // #define GL_FLOAT 0x1406
2, // #define GL_2_BYTES 0x1407
3, // #define GL_3_BYTES 0x1408
4, // #define GL_4_BYTES 0x1409
8 // #define GL_DOUBLE 0x140A
};
const static size_t format_channels[] = {
1, // #define GL_RED 0x1903
1, // #define GL_GREEN 0x1904
1, // #define GL_BLUE 0x1905
1, // #define GL_ALPHA 0x1906
3, // #define GL_RGB 0x1907
4, // #define GL_RGBA 0x1908
1, // #define GL_LUMINANCE 0x1909
2 // #define GL_LUMINANCE_ALPHA 0x190A
};
inline size_t GlDataTypeBytes(GLenum type)
{
return datatype_bytes[type - GL_BYTE];
}
inline size_t GlFormatChannels(GLenum data_layout)
{
if (data_layout == GL_BGR) return 3;
if (data_layout == GL_BGRA) return 4;
return format_channels[data_layout - GL_RED];
}
//template<typename T>
//struct GlDataTypeTrait {};
//template<> struct GlDataTypeTrait<float>{ static const GLenum type = GL_FLOAT; };
//template<> struct GlDataTypeTrait<int>{ static const GLenum type = GL_INT; };
//template<> struct GlDataTypeTrait<unsigned char>{ static const GLenum type = GL_UNSIGNED_BYTE; };
inline GlTexture::GlTexture()
: internal_format(0), tid(0), width(0), height(0)
{
// Not a texture constructor
}
inline GlTexture::GlTexture(GLint width, GLint height, GLint internal_format, bool sampling_linear, int border, GLenum glformat, GLenum gltype, GLvoid* data )
: internal_format(0), tid(0)
{
Reinitialise(width,height,internal_format,sampling_linear,border,glformat,gltype,data);
}
inline GlTexture::GlTexture(const TypedImage& img, bool sampling_linear)
{
this->Load(img, sampling_linear);
}
inline GlTexture::GlTexture(GlTexture&& tex)
{
*this = std::move(tex);
}
inline GlTexture& GlTexture::operator=(GlTexture&& tex)
{
if (&tex != this) {
internal_format = tex.internal_format;
tid = tex.tid;
width = tex.width;
height = tex.height;
tex.internal_format = 0;
tex.tid = 0;
}
return *this;
}
inline bool GlTexture::IsValid() const
{
return tid != 0;
}
inline void GlTexture::Delete()
{
// We have no GL context whilst exiting.
if(internal_format!=0 && !pangolin::ShouldQuit() ) {
glDeleteTextures(1,&tid);
internal_format = 0;
tid = 0;
width = 0;
height = 0;
}
}
inline GlTexture::~GlTexture()
{
// We have no GL context whilst exiting.
if(internal_format!=0 && !pangolin::ShouldQuit() ) {
glDeleteTextures(1,&tid);
}
}
inline void GlTexture::Bind() const
{
glBindTexture(GL_TEXTURE_2D, tid);
}
inline void GlTexture::Unbind() const
{
glBindTexture(GL_TEXTURE_2D, 0);
}
inline void GlTexture::Reinitialise(GLsizei w, GLsizei h, GLint int_format, bool sampling_linear, int border, GLenum glformat, GLenum gltype, GLvoid* data )
{
if(tid!=0) {
glDeleteTextures(1,&tid);
}
internal_format = int_format;
width = w;
height = h;
glGenTextures(1,&tid);
Bind();
// GL_LUMINANCE and GL_FLOAT don't seem to actually affect buffer, but some values are required
// for call to succeed.
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, border, glformat, gltype, data);
if(sampling_linear) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}else{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
CheckGlDieOnError();
}
inline void GlTexture::Upload(
const void* data,
GLenum data_format, GLenum data_type
) {
Bind();
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,data_format,data_type,data);
CheckGlDieOnError();
}
inline void GlTexture::Upload(
const void* data,
GLsizei tex_x_offset, GLsizei tex_y_offset,
GLsizei data_w, GLsizei data_h,
GLenum data_format, GLenum data_type )
{
Bind();
glTexSubImage2D(GL_TEXTURE_2D,0,tex_x_offset,tex_y_offset,data_w,data_h,data_format,data_type,data);
CheckGlDieOnError();
}
inline void GlTexture::Load(const TypedImage& image, bool sampling_linear)
{
GlPixFormat fmt(image.fmt);
Reinitialise((GLint)image.w, (GLint)image.h, GL_RGBA32F, sampling_linear, 0, fmt.glformat, fmt.gltype, image.ptr );
}
inline void GlTexture::LoadFromFile(const std::string& filename, bool sampling_linear)
{
TypedImage image = LoadImage(filename);
Load(image, sampling_linear);
}
#ifndef HAVE_GLES
inline void GlTexture::Download(void* image, GLenum data_layout, GLenum data_type) const
{
Bind();
glGetTexImage(GL_TEXTURE_2D, 0, data_layout, data_type, image);
Unbind();
}
inline void GlTexture::Download(TypedImage& image) const
{
switch (internal_format)
{
case GL_LUMINANCE8:
image.Reinitialise(width, height, PixelFormatFromString("GRAY8") );
Download(image.ptr, GL_LUMINANCE, GL_UNSIGNED_BYTE);
break;
case GL_LUMINANCE16:
image.Reinitialise(width, height, PixelFormatFromString("GRAY16LE") );
Download(image.ptr, GL_LUMINANCE, GL_UNSIGNED_SHORT);
break;
case GL_RGB8:
image.Reinitialise(width, height, PixelFormatFromString("RGB24"));
Download(image.ptr, GL_RGB, GL_UNSIGNED_BYTE);
break;
case GL_RGBA8:
image.Reinitialise(width, height, PixelFormatFromString("RGBA32"));
Download(image.ptr, GL_RGBA, GL_UNSIGNED_BYTE);
break;
case GL_RGB16:
image.Reinitialise(width, height, PixelFormatFromString("RGB48"));
Download(image.ptr, GL_RGB, GL_UNSIGNED_SHORT);
break;
case GL_RGBA16:
image.Reinitialise(width, height, PixelFormatFromString("RGBA64"));
Download(image.ptr, GL_RGBA, GL_UNSIGNED_SHORT);
break;
case GL_LUMINANCE:
case GL_LUMINANCE32F_ARB:
image.Reinitialise(width, height, PixelFormatFromString("GRAY32F"));
Download(image.ptr, GL_LUMINANCE, GL_FLOAT);
break;
case GL_RGB:
case GL_RGB32F:
image.Reinitialise(width, height, PixelFormatFromString("RGB96F"));
Download(image.ptr, GL_RGB, GL_FLOAT);
break;
case GL_RGBA:
case GL_RGBA32F:
image.Reinitialise(width, height, PixelFormatFromString("RGBA128F"));
Download(image.ptr, GL_RGBA, GL_FLOAT);
break;
default:
throw std::runtime_error(
"GlTexture::Download - Unknown internal format (" +
pangolin::Convert<std::string,GLint>::Do(internal_format) +
")"
);
}
}
inline void GlTexture::CopyFrom(const GlTexture& tex)
{
if(!tid || width != tex.width || height != tex.height ||
internal_format != tex.internal_format)
{
Reinitialise(tex.width, tex.height, tex.internal_format, true);
}
glCopyImageSubData(tex.tid, GL_TEXTURE_2D, 0, 0, 0, 0,
tid, GL_TEXTURE_2D, 0, 0, 0, 0,
width, height, 1);
CheckGlDieOnError();
}
inline void GlTexture::Save(const std::string& filename, bool top_line_first)
{
TypedImage image;
Download(image);
pangolin::SaveImage(image, filename, top_line_first);
}
#endif // HAVE_GLES
inline void GlTexture::SetLinear()
{
Bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Unbind();
}
inline void GlTexture::SetNearestNeighbour()
{
Bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Unbind();
}
inline void GlTexture::RenderToViewport(const bool flip) const
{
if(flip) {
RenderToViewportFlipY();
}else{
RenderToViewport();
}
}
inline void GlTexture::RenderToViewport() const
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
GLfloat sq_tex[] = { 0,0, 1,0, 1,1, 0,1 };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
Bind();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
inline void GlTexture::RenderToViewport(Viewport tex_vp, bool flipx, bool flipy) const
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
GLfloat l = tex_vp.l / (float)(width);
GLfloat b = tex_vp.b / (float)(height);
GLfloat r = (tex_vp.l+tex_vp.w) / (float)(width);
GLfloat t = (tex_vp.b+tex_vp.h) / (float)(height);
if(flipx) std::swap(l,r);
if(flipy) std::swap(b,t);
GLfloat sq_tex[] = { l,b, r,b, r,t, l,t };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
Bind();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
inline void GlTexture::RenderToViewportFlipY() const
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
GLfloat sq_tex[] = { 0,1, 1,1, 1,0, 0,0 };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
Bind();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
inline void GlTexture::RenderToViewportFlipXFlipY() const
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat sq_vert[] = { 1,1, -1,1, -1,-1, 1,-1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
GLfloat sq_tex[] = { 0,0, 1,0, 1,1, 0,1 };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
Bind();
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
////////////////////////////////////////////////////////////////////////////
inline GlRenderBuffer::GlRenderBuffer()
: width(0), height(0), rbid(0)
{
}
inline GlRenderBuffer::GlRenderBuffer(GLint width, GLint height, GLint internal_format )
: width(0), height(0), rbid(0)
{
Reinitialise(width,height,internal_format);
}
#ifndef HAVE_GLES
inline void GlRenderBuffer::Reinitialise(GLint width, GLint height, GLint internal_format)
{
if( this->width != 0 ) {
glDeleteRenderbuffersEXT(1, &rbid);
}
this->width = width;
this->height = height;
glGenRenderbuffersEXT(1, &rbid);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbid);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internal_format, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
}
inline GlRenderBuffer::~GlRenderBuffer()
{
// We have no GL context whilst exiting.
if( width!=0 && !pangolin::ShouldQuit() ) {
glDeleteRenderbuffersEXT(1, &rbid);
}
}
#else
inline void GlRenderBuffer::Reinitialise(GLint width, GLint height, GLint internal_format)
{
if( width!=0 ) {
glDeleteTextures(1, &rbid);
}
// Use a texture instead...
glGenTextures(1, &rbid);
glBindTexture(GL_TEXTURE_2D, rbid);
glTexImage2D(GL_TEXTURE_2D, 0, internal_format,
width, height,
0, internal_format, GL_UNSIGNED_SHORT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
inline GlRenderBuffer::~GlRenderBuffer()
{
// We have no GL context whilst exiting.
if( width!=0 && !pangolin::ShouldQuit() ) {
glDeleteTextures(1, &rbid);
}
}
#endif // HAVE_GLES
inline GlRenderBuffer::GlRenderBuffer(GlRenderBuffer&& tex)
: width(tex.width), height(tex.height), rbid(tex.rbid)
{
tex.rbid = tex.width = tex.height = 0;
}
////////////////////////////////////////////////////////////////////////////
inline GlFramebuffer::GlFramebuffer()
: fbid(0), attachments(0)
{
}
inline GlFramebuffer::~GlFramebuffer()
{
if(fbid) {
glDeleteFramebuffersEXT(1, &fbid);
}
}
inline GlFramebuffer::GlFramebuffer(GlTexture& colour, GlRenderBuffer& depth)
: attachments(0)
{
glGenFramebuffersEXT(1, &fbid);
AttachColour(colour);
AttachDepth(depth);
CheckGlDieOnError();
}
inline GlFramebuffer::GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlRenderBuffer& depth)
: attachments(0)
{
glGenFramebuffersEXT(1, &fbid);
AttachColour(colour0);
AttachColour(colour1);
AttachDepth(depth);
CheckGlDieOnError();
}
inline GlFramebuffer::GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlTexture& colour2, GlRenderBuffer& depth)
: attachments(0)
{
glGenFramebuffersEXT(1, &fbid);
AttachColour(colour0);
AttachColour(colour1);
AttachColour(colour2);
AttachDepth(depth);
CheckGlDieOnError();
}
inline GlFramebuffer::GlFramebuffer(GlTexture& colour0, GlTexture& colour1, GlTexture& colour2, GlTexture& colour3, GlRenderBuffer& depth)
: attachments(0)
{
glGenFramebuffersEXT(1, &fbid);
AttachColour(colour0);
AttachColour(colour1);
AttachColour(colour2);
AttachColour(colour3);
AttachDepth(depth);
CheckGlDieOnError();
}
inline void GlFramebuffer::Bind() const
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbid);
#ifndef HAVE_GLES
glDrawBuffers( attachments, attachment_buffers );
#endif
}
inline void GlFramebuffer::Reinitialise()
{
if(fbid) {
glDeleteFramebuffersEXT(1, &fbid);
}
glGenFramebuffersEXT(1, &fbid);
}
inline void GlFramebuffer::Unbind() const
{
#ifndef HAVE_GLES
glDrawBuffers( 1, attachment_buffers );
#endif
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
inline GLenum GlFramebuffer::AttachColour(GlTexture& tex )
{
if(!fbid) Reinitialise();
const GLenum color_attachment = GL_COLOR_ATTACHMENT0_EXT + attachments;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbid);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, color_attachment, GL_TEXTURE_2D, tex.tid, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
attachments++;
CheckGlDieOnError();
return color_attachment;
}
inline void GlFramebuffer::AttachDepth(GlRenderBuffer& rb )
{
if(!fbid) Reinitialise();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbid);
#if !defined(HAVE_GLES)
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rb.rbid);
#elif defined(HAVE_GLES_2)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, rb.rbid, 0);
#else
throw std::exception();
#endif
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
CheckGlDieOnError();
}
////////////////////////////////////////////////////////////////////////////
inline GlBufferData::GlBufferData()
: bo(0)
{
}
inline GlBufferData::GlBufferData(GlBufferType buffer_type, GLuint size_bytes, GLenum gluse, const unsigned char* data )
: bo(0)
{
Reinitialise(buffer_type, size_bytes, gluse, data );
}
//! Move Constructor
inline GlBufferData::GlBufferData(GlBufferData&& tex)
: bo(0)
{
*this = std::move(tex);
}
inline GlBufferData& GlBufferData::operator=(GlBufferData&& tex)
{
Free();
this->bo = tex.bo;
this->buffer_type = tex.buffer_type;
this->gluse = tex.gluse;
this->size_bytes = tex.size_bytes;
tex.bo = 0;
return *this;
}
inline GlBufferData::~GlBufferData()
{
Free();
}
inline void GlBufferData::Free()
{
if(bo!=0) {
glDeleteBuffers(1, &bo);
}
}
inline bool GlBufferData::IsValid() const
{
return bo != 0;
}
inline size_t GlBufferData::SizeBytes() const
{
return size_bytes;
}
inline void GlBufferData::Reinitialise(GlBufferType buffer_type, GLuint size_bytes, GLenum gluse, const unsigned char* data )
{
if(!bo) {
glGenBuffers(1, &bo);
}
this->buffer_type = buffer_type;
this->gluse = gluse;
this->size_bytes = size_bytes;
Bind();
glBufferData(buffer_type, size_bytes, data, gluse);
Unbind();
}
inline void GlBufferData::Bind() const
{
glBindBuffer(buffer_type, bo);
}
inline void GlBufferData::Unbind() const
{
glBindBuffer(buffer_type, 0);
}
inline void GlBufferData::Upload(const GLvoid* data, GLsizeiptr size_bytes, GLintptr offset)
{
if(offset + size_bytes > this->size_bytes) {
throw std::runtime_error("GlBufferData: Trying to upload past capacity.");
}
Bind();
glBufferSubData(buffer_type,offset,size_bytes,data);
Unbind();
}
inline void GlBufferData::Download(GLvoid* data, GLsizeiptr size_bytes, GLintptr offset) const
{
Bind();
glGetBufferSubData(buffer_type, offset, size_bytes, data);
Unbind();
}
////////////////////////////////////////////////////////////////////////////
inline GlBuffer::GlBuffer()
: GlBufferData(), num_elements(0)
{
}
inline GlBuffer::GlBuffer(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse )
: GlBufferData(buffer_type, num_elements * count_per_element * GlDataTypeBytes(datatype), gluse),
datatype(datatype), num_elements(num_elements), count_per_element(count_per_element)
{
}
inline GlBuffer::GlBuffer(GlBuffer&& o)
: GlBufferData()
{
*this = std::move(o);
}
inline GlBuffer& GlBuffer::operator=(GlBuffer&& o)
{
datatype = o.datatype;
num_elements = o.num_elements;
count_per_element = o.count_per_element;
GlBufferData::operator =(std::move(o));
return *this;
}
inline void GlBuffer::Reinitialise(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse, const unsigned char* data )
{
this->datatype = datatype;
this->num_elements = num_elements;
this->count_per_element = count_per_element;
const GLuint size_bytes = num_elements * count_per_element * GlDataTypeBytes(datatype);
GlBufferData::Reinitialise(buffer_type, size_bytes, gluse, data);
}
inline void GlBuffer::Reinitialise(GlBuffer const& other )
{
Reinitialise(other.buffer_type, other.num_elements, other.datatype, other.count_per_element, other.gluse);
}
inline void GlBuffer::Resize(GLuint new_num_elements)
{
if(bo!=0) {
#ifndef HAVE_GLES
// Backup current data, reinit memory, restore old data
const size_t backup_elements = std::min(new_num_elements,num_elements);
const size_t backup_size_bytes = backup_elements*GlDataTypeBytes(datatype)*count_per_element;
unsigned char* backup = new unsigned char[backup_size_bytes];
Bind();
glGetBufferSubData(buffer_type, 0, backup_size_bytes, backup);
glBufferData(buffer_type, new_num_elements*GlDataTypeBytes(datatype)*count_per_element, 0, gluse);
glBufferSubData(buffer_type, 0, backup_size_bytes, backup);
Unbind();
delete[] backup;
#else
throw std::exception();
#endif
}else{
Reinitialise(buffer_type, new_num_elements, datatype, count_per_element, gluse);
}
num_elements = new_num_elements;
}
////////////////////////////////////////////////////////////////////////////
inline GlSizeableBuffer::GlSizeableBuffer(GlBufferType buffer_type, GLuint initial_num_elements, GLenum datatype, GLuint count_per_element, GLenum gluse )
: GlBuffer(buffer_type, initial_num_elements, datatype, count_per_element, gluse), m_num_verts(0)
{
}
inline void GlSizeableBuffer::Clear()
{
m_num_verts = 0;
}
#ifdef USE_EIGEN
template<typename Derived> inline
void GlSizeableBuffer::Add(const Eigen::DenseBase<Derived>& vec)
{
typedef typename Eigen::DenseBase<Derived>::Scalar Scalar;
assert(vec.rows()==GlBuffer::count_per_element);
CheckResize(m_num_verts + 1);
// TODO: taking address of first element is really dodgey. Need to work out
// when this is okay!
Upload(&vec(0,0), sizeof(Scalar)*vec.rows()*vec.cols(), sizeof(Scalar)*vec.rows()*m_num_verts);
m_num_verts += vec.cols();
}
template<typename Derived> inline
void GlSizeableBuffer::Update(const Eigen::DenseBase<Derived>& vec, size_t position )
{
typedef typename Eigen::DenseBase<Derived>::Scalar Scalar;
assert(vec.rows()==GlBuffer::count_per_element);
CheckResize(position + vec.cols() );
// TODO: taking address of first element is really dodgey. Need to work out
// when this is okay!
Upload(&vec(0,0), sizeof(Scalar)*vec.rows()*vec.cols(), sizeof(Scalar)*vec.rows()*position );
m_num_verts = std::max(position+vec.cols(), m_num_verts);
}
#endif
inline size_t GlSizeableBuffer::start() const {
return 0;
}
inline size_t GlSizeableBuffer::size() const {
return m_num_verts;
}
inline void GlSizeableBuffer::CheckResize(size_t num_verts)
{
if( num_verts > GlBuffer::num_elements) {
const size_t new_size = NextSize(num_verts);
GlBuffer::Resize((GLuint)new_size);
}
}
inline size_t GlSizeableBuffer::NextSize(size_t min_size) const
{
size_t new_size = std::max(GlBuffer::num_elements, 1u);
while(new_size < min_size) {
new_size *= 2;
}
return new_size;
}
}

View File

@@ -0,0 +1,78 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#include <map>
namespace pangolin {
struct PANGOLIN_EXPORT XYUV
{
XYUV() {}
XYUV(GLfloat x, GLfloat y, GLfloat tu, GLfloat tv)
: x(x), y(y), tu(tu), tv(tv) {}
XYUV operator+(float dx) const {
return XYUV(x+dx,y,tu,tv);
}
GLfloat x, y, tu, tv;
};
class PANGOLIN_EXPORT GlChar
{
public:
GlChar();
GlChar(int tw, int th, int x, int y, int w, int h, GLfloat x_step, GLfloat ox, GLfloat oy);
inline const XYUV& GetVert(size_t i) const {
return vs[i];
}
inline GLfloat StepX() const {
return x_step;
}
inline GLfloat YMin() const {
return y_min;
}
inline GLfloat YMax() const {
return y_max;
}
void Draw() const;
protected:
XYUV vs[4];
GLfloat x_step;
GLfloat y_min, y_max;
};
}

View File

@@ -0,0 +1,258 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <algorithm>
#include <cuda_runtime.h>
#include <cuda_gl_interop.h>
#include "gl.h"
namespace pangolin
{
////////////////////////////////////////////////
// Interface
////////////////////////////////////////////////
struct GlBufferCudaPtr : public GlBuffer
{
//! Default constructor represents 'no buffer'
GlBufferCudaPtr();
GlBufferCudaPtr(GlBufferType buffer_type, GLuint size_bytes, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ );
GlBufferCudaPtr(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ );
PANGOLIN_DEPRECATED
GlBufferCudaPtr(GlBufferType buffer_type, GLuint width, GLuint height, GLenum datatype, GLuint count_per_element, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ );
~GlBufferCudaPtr();
void Reinitialise(GlBufferType buffer_type, GLuint size_bytes, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ );
void Reinitialise(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ );
/**
* Use parameters from another @c GlBufferCudaPtr to initialize this buffer.
*/
void Reinitialise(const GlBufferCudaPtr& other);
unsigned int cuda_use;
cudaGraphicsResource* cuda_res;
};
struct GlTextureCudaArray : GlTexture
{
GlTextureCudaArray();
// Some internal_formats aren't accepted. I have trouble with GL_RGB8
GlTextureCudaArray(int width, int height, GLint internal_format, bool sampling_linear = true, int border = 0, GLenum glformat = GL_RGBA, GLenum gltype = GL_UNSIGNED_BYTE, GLvoid* data = NULL);
~GlTextureCudaArray();
void Reinitialise(int width, int height, GLint internal_format, bool sampling_linear = true, int border = 0, GLenum glformat = GL_RGBA, GLenum gltype = GL_UNSIGNED_BYTE, GLvoid* data = NULL) override;
cudaGraphicsResource* cuda_res;
};
struct CudaScopedMappedPtr
{
CudaScopedMappedPtr(const GlBufferCudaPtr& buffer);
~CudaScopedMappedPtr();
void* operator*();
cudaGraphicsResource* res;
private:
CudaScopedMappedPtr(const CudaScopedMappedPtr&) {}
};
struct CudaScopedMappedArray
{
CudaScopedMappedArray(const GlTextureCudaArray& tex);
~CudaScopedMappedArray();
cudaArray* operator*();
cudaGraphicsResource* res;
private:
CudaScopedMappedArray(const CudaScopedMappedArray&) {}
};
void CopyPboToTex(GlBufferCudaPtr& buffer, GlTexture& tex);
void swap(GlBufferCudaPtr& a, GlBufferCudaPtr& b);
////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////
inline GlBufferCudaPtr::GlBufferCudaPtr()
: cuda_res(0)
{
}
inline GlBufferCudaPtr::GlBufferCudaPtr(GlBufferType buffer_type, GLuint size_bytes, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ )
: cuda_res(0)
{
Reinitialise(buffer_type, size_bytes, cudause, gluse);
}
inline GlBufferCudaPtr::GlBufferCudaPtr(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, unsigned int cudause, GLenum gluse )
: cuda_res(0)
{
Reinitialise(buffer_type, num_elements, datatype, count_per_element, cudause, gluse);
}
inline GlBufferCudaPtr::GlBufferCudaPtr(GlBufferType buffer_type, GLuint width, GLuint height, GLenum datatype, GLuint count_per_element, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ )
: cuda_res(0)
{
Reinitialise(buffer_type, width*height, datatype, count_per_element, cudause, gluse);
}
inline GlBufferCudaPtr::~GlBufferCudaPtr()
{
if(cuda_res) {
cudaGraphicsUnregisterResource(cuda_res);
}
}
inline void GlBufferCudaPtr::Reinitialise(GlBufferType buffer_type, GLuint size_bytes, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ )
{
GlBufferCudaPtr::Reinitialise(buffer_type, size_bytes, GL_BYTE, 1, cudause, gluse);
}
inline void GlBufferCudaPtr::Reinitialise(GlBufferType buffer_type, GLuint num_elements, GLenum datatype, GLuint count_per_element, unsigned int cudause /*= cudaGraphicsMapFlagsNone*/, GLenum gluse /*= GL_DYNAMIC_DRAW*/ )
{
if(cuda_res) {
cudaGraphicsUnregisterResource(cuda_res);
}
GlBuffer::Reinitialise(buffer_type, num_elements, datatype, count_per_element, gluse);
cuda_use = cudause;
cudaGraphicsGLRegisterBuffer( &cuda_res, bo, cudause );
}
inline void GlBufferCudaPtr::Reinitialise(const GlBufferCudaPtr& other)
{
Reinitialise(other.buffer_type, other.num_elements, other.datatype, other.count_per_element, other.cuda_use, other.gluse);
}
inline GlTextureCudaArray::GlTextureCudaArray()
: GlTexture(), cuda_res(0)
{
// Not a texture
}
inline GlTextureCudaArray::GlTextureCudaArray(int width, int height, GLint internal_format, bool sampling_linear, int border, GLenum glformat, GLenum gltype, GLvoid *data)
:GlTexture(width,height,internal_format, sampling_linear, border, glformat, gltype, data)
{
// TODO: specify flags too
const cudaError_t err = cudaGraphicsGLRegisterImage(&cuda_res, tid, GL_TEXTURE_2D, cudaGraphicsMapFlagsNone);
if( err != cudaSuccess ) {
std::cout << "cudaGraphicsGLRegisterImage failed: " << err << std::endl;
}
}
inline GlTextureCudaArray::~GlTextureCudaArray()
{
if(cuda_res) {
cudaGraphicsUnregisterResource(cuda_res);
}
}
inline void GlTextureCudaArray::Reinitialise(int width, int height, GLint internal_format, bool sampling_linear, int border, GLenum glformat, GLenum gltype, GLvoid* data)
{
if(cuda_res) {
cudaGraphicsUnregisterResource(cuda_res);
}
GlTexture::Reinitialise(width, height, internal_format, sampling_linear, border, glformat, gltype, data);
const cudaError_t err = cudaGraphicsGLRegisterImage(&cuda_res, tid, GL_TEXTURE_2D, cudaGraphicsMapFlagsNone);
if( err != cudaSuccess ) {
std::cout << "cudaGraphicsGLRegisterImage failed: " << err << std::endl;
}
}
inline CudaScopedMappedPtr::CudaScopedMappedPtr(const GlBufferCudaPtr& buffer)
: res(buffer.cuda_res)
{
cudaGraphicsMapResources(1, &res, 0);
}
inline CudaScopedMappedPtr::~CudaScopedMappedPtr()
{
cudaGraphicsUnmapResources(1, &res, 0);
}
inline void* CudaScopedMappedPtr::operator*()
{
size_t num_bytes;
void* d_ptr;
cudaGraphicsResourceGetMappedPointer(&d_ptr,&num_bytes,res);
return d_ptr;
}
inline CudaScopedMappedArray::CudaScopedMappedArray(const GlTextureCudaArray& tex)
: res(tex.cuda_res)
{
cudaGraphicsMapResources(1, &res);
}
inline CudaScopedMappedArray::~CudaScopedMappedArray()
{
cudaGraphicsUnmapResources(1, &res);
}
inline cudaArray* CudaScopedMappedArray::operator*()
{
cudaArray* array;
cudaGraphicsSubResourceGetMappedArray(&array, res, 0, 0);
return array;
}
inline void CopyPboToTex(const GlBufferCudaPtr& buffer, GlTexture& tex, GLenum buffer_layout, GLenum buffer_data_type )
{
buffer.Bind();
tex.Bind();
glTexImage2D(GL_TEXTURE_2D, 0, tex.internal_format, tex.width, tex.height, 0, buffer_layout, buffer_data_type, 0);
buffer.Unbind();
tex.Unbind();
}
template<typename T>
inline void CopyDevMemtoTex(T* d_img, size_t pitch, GlTextureCudaArray& tex )
{
CudaScopedMappedArray arr_tex(tex);
cudaMemcpy2DToArray(*arr_tex, 0, 0, d_img, pitch, tex.width*sizeof(T), tex.height, cudaMemcpyDeviceToDevice );
}
inline void swap(GlBufferCudaPtr& a, GlBufferCudaPtr& b)
{
std::swap(a.bo, b.bo);
std::swap(a.cuda_res, b.cuda_res);
std::swap(a.buffer_type, b.buffer_type);
}
}

View File

@@ -0,0 +1,518 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glinclude.h>
#include <pangolin/gl/glformattraits.h>
#include <pangolin/display/opengl_render_state.h>
#include <vector>
#include <math.h>
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#include <Eigen/src/Geometry/AlignedBox.h>
#endif // USE_EIGEN
namespace pangolin
{
// h [0,360)
// s [0,1]
// v [0,1]
inline void glColorHSV( GLfloat hue, GLfloat s=1.0f, GLfloat v=1.0f )
{
const GLfloat h = hue / 60.0f;
const int i = (int)floor(h);
const GLfloat f = (i%2 == 0) ? 1-(h-i) : h-i;
const GLfloat m = v * (1-s);
const GLfloat n = v * (1-s*f);
switch(i)
{
case 0: glColor4f(v,n,m,1); break;
case 1: glColor4f(n,v,m,1); break;
case 2: glColor4f(m,v,n,1); break;
case 3: glColor4f(m,n,v,1); break;
case 4: glColor4f(n,m,v,1); break;
case 5: glColor4f(v,m,n,1); break;
default:
break;
}
}
inline void glColorBin( int bin, int max_bins, GLfloat sat=1.0f, GLfloat val=1.0f )
{
if( bin >= 0 ) {
const GLfloat hue = (GLfloat)(bin%max_bins) * 360.0f / (GLfloat)max_bins;
glColorHSV(hue,sat,val);
}else{
glColor4f(1,1,1,1);
}
}
template<typename T>
inline void glDrawVertices(
size_t num_vertices, const T* const vertex_ptr, GLenum mode,
size_t elements_per_vertex = GlFormatTraits<T>::components,
size_t vertex_stride_bytes = 0 )
{
if(num_vertices > 0)
{
PANGO_ENSURE(vertex_ptr != nullptr);
PANGO_ENSURE(mode != GL_LINES || num_vertices % 2 == 0, "number of vertices (%) must be even in GL_LINES mode", num_vertices );
glVertexPointer(elements_per_vertex, GlFormatTraits<T>::gltype, vertex_stride_bytes, vertex_ptr);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(mode, 0, num_vertices);
glDisableClientState(GL_VERTEX_ARRAY);
}
}
template<typename TV, typename TC>
inline void glDrawColoredVertices(
size_t num_vertices, const TV* const vertex_ptr, const TC* const color_ptr, GLenum mode,
size_t elements_per_vertex = GlFormatTraits<TV>::components,
size_t elements_per_color = GlFormatTraits<TC>::components,
size_t vertex_stride_bytes = 0,
size_t color_stride_bytes = 0
) {
if(color_ptr) {
glColorPointer(elements_per_color, GlFormatTraits<TC>::gltype, color_stride_bytes, color_ptr);
glEnableClientState(GL_COLOR_ARRAY);
glDrawVertices<TV>(num_vertices, vertex_ptr, mode, elements_per_vertex, vertex_stride_bytes);
glDisableClientState(GL_COLOR_ARRAY);
}else{
glDrawVertices<TV>(num_vertices, vertex_ptr, mode, elements_per_vertex, vertex_stride_bytes);
}
}
inline void glDrawLine( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
{
const GLfloat verts[] = { x1,y1, x2,y2 };
glDrawVertices<float>(2, verts, GL_LINES, 2);
}
inline void glDrawLine( GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2)
{
const GLfloat verts[] = { x1,y1,z1, x2,y2,z2 };
glDrawVertices<float>(2, verts, GL_LINES, 3);
}
inline void glDrawCross( GLfloat x, GLfloat y, GLfloat rad )
{
const GLfloat verts[] = { x-rad,y, x+rad, y, x,y-rad, x, y+rad};
glDrawVertices<float>(4, verts, GL_LINES, 2);
}
inline void glDrawCross( GLfloat x, GLfloat y, GLfloat z, GLfloat rad )
{
const GLfloat verts[] = { x-rad,y,z, x+rad,y,z, x,y-rad,z, x,y+rad,z, x,y,z-rad, x,y,z+rad };
glDrawVertices<float>(6, verts, GL_LINES, 3);
}
inline void glDrawAxis(float s)
{
const GLfloat cols[] = { 1,0,0, 1,0,0, 0,1,0, 0,1,0, 0,0,1, 0,0,1 };
const GLfloat verts[] = { 0,0,0, s,0,0, 0,0,0, 0,s,0, 0,0,0, 0,0,s };
glDrawColoredVertices<float,float>(6, verts, cols, GL_LINES, 3, 3);
}
inline void glDrawRect( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLenum mode = GL_TRIANGLE_FAN )
{
const GLfloat verts[] = { x1,y1, x2,y1, x2,y2, x1,y2 };
glDrawVertices<float>(4, verts, mode, 2);
}
inline void glDrawRectPerimeter( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
{
glDrawRect(x1,y1, x2,y2, GL_LINE_LOOP);
}
inline void glDrawCirclePerimeter( float x, float y, float rad )
{
const int N = 50;
GLfloat verts[N*2];
const float TAU_DIV_N = 2*(float)M_PI/N;
for(int i = 0; i < N*2; i+=2) {
verts[i] = x + rad * cos(i*TAU_DIV_N);
verts[i+1] = y + rad * sin(i*TAU_DIV_N);
}
glDrawVertices<float>(N, verts, GL_LINES, 2);
}
inline void glDrawCircle( GLfloat x, GLfloat y, GLfloat rad )
{
const int N = 50;
GLfloat verts[N*2];
// Draw vertices anticlockwise for front face
const float TAU_DIV_N = 2*(float)M_PI/N;
for(int i = 0; i < N*2; i+=2) {
verts[i] = x + rad * cos(-i*TAU_DIV_N);
verts[i+1] = y + rad * sin(-i*TAU_DIV_N);
}
// Render filled shape and outline (to make it look smooth)
glVertexPointer(2, GL_FLOAT, 0, verts);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_FAN, 0, N);
glDrawArrays(GL_LINE_STRIP, 0, N);
glDisableClientState(GL_VERTEX_ARRAY);
}
inline void glDrawColouredCube(GLfloat axis_min=-0.5f, GLfloat axis_max = +0.5f)
{
const GLfloat l = axis_min;
const GLfloat h = axis_max;
const GLfloat verts[] = {
l,l,h, h,l,h, l,h,h, h,h,h, // FRONT
l,l,l, l,h,l, h,l,l, h,h,l, // BACK
l,l,h, l,h,h, l,l,l, l,h,l, // LEFT
h,l,l, h,h,l, h,l,h, h,h,h, // RIGHT
l,h,h, h,h,h, l,h,l, h,h,l, // TOP
l,l,h, l,l,l, h,l,h, h,l,l // BOTTOM
};
glVertexPointer(3, GL_FLOAT, 0, verts);
glEnableClientState(GL_VERTEX_ARRAY);
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
glDisableClientState(GL_VERTEX_ARRAY);
}
inline void glDraw_x0(GLfloat scale, int grid)
{
const GLfloat maxord = grid*scale;
for (int i = -grid; i <= grid; ++i) {
glDrawLine(0.0, i*scale, -maxord, 0.0, i*scale, +maxord);
glDrawLine(0.0, -maxord, i*scale, 0.0, +maxord, i*scale);
}
}
inline void glDraw_y0(GLfloat scale, int grid)
{
const GLfloat maxord = grid*scale;
for (int i = -grid; i <= grid; ++i) {
glDrawLine(i*scale, 0.0, -maxord, i*scale, 0.0, +maxord);
glDrawLine(-maxord, 0.0, i*scale, +maxord, 0.0, i*scale);
}
}
inline void glDraw_z0(GLfloat scale, int grid)
{
const GLfloat maxord = grid*scale;
for(int i=-grid; i<=grid; ++i ) {
glDrawLine(i*scale,-maxord, i*scale,+maxord);
glDrawLine(-maxord, i*scale, +maxord, i*scale);
}
}
inline void glDrawFrustum( GLfloat u0, GLfloat v0, GLfloat fu, GLfloat fv, int w, int h, GLfloat scale )
{
const GLfloat xl = scale * u0;
const GLfloat xh = scale * (w*fu + u0);
const GLfloat yl = scale * v0;
const GLfloat yh = scale * (h*fv + v0);
const GLfloat verts[] = {
xl,yl,scale, xh,yl,scale,
xh,yh,scale, xl,yh,scale,
xl,yl,scale, 0,0,0,
xh,yl,scale, 0,0,0,
xl,yh,scale, 0,0,0,
xh,yh,scale
};
glDrawVertices(11, verts, GL_LINE_STRIP, 3);
}
inline void glDrawTexture(GLenum target, GLuint texid)
{
glBindTexture(target, texid);
glEnable(target);
const GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
const GLfloat sq_tex[] = { 0,0, 1,0, 1,1, 0,1 };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4f(1,1,1,1);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(target);
}
inline void glDrawTextureFlipY(GLenum target, GLuint texid)
{
glBindTexture(target, texid);
glEnable(target);
const GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
glEnableClientState(GL_VERTEX_ARRAY);
const GLfloat sq_tex[] = { 0,1, 1,1, 1,0, 0,0 };
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4f(1,1,1,1);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(target);
}
#ifdef USE_EIGEN
#ifndef HAVE_GLES
inline void glVertex( const Eigen::Vector3d& p )
{
glVertex3dv(p.data());
}
#endif
inline void glDrawLine( const Eigen::Vector2d& p1, const Eigen::Vector2d& p2 )
{
glDrawLine((GLfloat)p1(0), (GLfloat)p1(1), (GLfloat)p2(0), (GLfloat)p2(1));
}
// Draws a vector of 2d or 3d vertices using provided ``mode``.
//
// Preconditions:
// - ``mode`` must be GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, etc
// - If ``mode == GL_LINES``, then ``vertices.size()`` must be a multiple of 2.
//
template<typename P, int N, class Allocator>
void glDrawVertices(const std::vector<Eigen::Matrix<P, N, 1>, Allocator>& vertices, GLenum mode)
{
glDrawVertices(vertices.size(), vertices.data(), mode);
}
// Draws a vector of 2d or 3d points.
//
template<typename P, int N, class Allocator>
void glDrawPoints(const std::vector<Eigen::Matrix<P, N, 1>, Allocator>& vertices)
{
glDrawVertices(vertices, GL_POINTS);
}
// Draws a vector of 2d or 3d lines.
//
// Precondition: ``vertices.size()`` must be a multiple of 2.
//
template<typename P, int N, class Allocator>
void glDrawLines(const std::vector<Eigen::Matrix<P, N, 1>, Allocator>& vertices)
{
glDrawVertices(vertices, GL_LINES);
}
// Draws a 2d or 3d line strip.
//
template<typename P, int N, class Allocator>
void glDrawLineStrip(const std::vector<Eigen::Matrix<P, N, 1>, Allocator>& vertices)
{
glDrawVertices(vertices, GL_LINE_STRIP);
}
// Draws a 2d or 3d line loop.
//
template<typename P, int N, class Allocator>
void glDrawLineLoop(const std::vector<Eigen::Matrix<P, N, 1>, Allocator>& vertices)
{
glDrawVertices(vertices, GL_LINE_LOOP);
}
inline void glDrawCross( const Eigen::Vector2d& p, double r = 5.0 )
{
glDrawCross((GLfloat)p(0), (GLfloat)p(1), (GLfloat)r);
}
inline void glDrawCross( const Eigen::Vector3d& p, double r = 5.0 )
{
glDrawCross((GLfloat)p(0), (GLfloat)p(1), (GLfloat)p(2), (GLfloat)r);
}
inline void glDrawCircle( const Eigen::Vector2d& p, double radius = 5.0 )
{
glDrawCircle((GLfloat)p(0), (GLfloat)p(1), (GLfloat)radius);
}
inline void glDrawCirclePerimeter( const Eigen::Vector2d& p, double radius = 5.0 )
{
glDrawCirclePerimeter((GLfloat)p(0), (GLfloat)p(1), (GLfloat)radius);
}
inline void glSetFrameOfReference( const Eigen::Matrix4f& T_wf )
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMultMatrixf( T_wf.data() );
}
inline void glSetFrameOfReference( const Eigen::Matrix4d& T_wf )
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
#ifndef HAVE_GLES
glMultMatrixd( T_wf.data() );
#else
const Eigen::Matrix4f fT_wf = T_wf.cast<GLfloat>();
glMultMatrixf( fT_wf.data() );
#endif
}
inline void glSetFrameOfReference( const pangolin::OpenGlMatrix& T_wf )
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMultMatrixd( T_wf.m );
}
inline void glUnsetFrameOfReference()
{
glPopMatrix();
}
template<typename T, typename S>
inline void glDrawAxis( const T& T_wf, S scale )
{
glSetFrameOfReference(T_wf);
glDrawAxis(scale);
glUnsetFrameOfReference();
}
template<typename T>
inline void glDrawFrustum( const Eigen::Matrix<T,3,3>& Kinv, int w, int h, GLfloat scale )
{
glDrawFrustum((GLfloat)Kinv(0,2), (GLfloat)Kinv(1,2), (GLfloat)Kinv(0,0), (GLfloat)Kinv(1,1), w, h, scale);
}
template<typename T>
inline void glDrawFrustum( const Eigen::Matrix<T,3,3>& Kinv, int w, int h, const Eigen::Matrix<T,4,4>& T_wf, T scale )
{
glSetFrameOfReference(T_wf);
glDrawFrustum(Kinv,w,h,scale);
glUnsetFrameOfReference();
}
template<typename T>
inline void glDrawAlignedBox( const Eigen::AlignedBox<T,2>& box, GLenum mode = GL_TRIANGLE_FAN )
{
const Eigen::Matrix<float,2,1> l = box.min().template cast<float>();
const Eigen::Matrix<float,2,1> h = box.max().template cast<float>();
GLfloat verts[] = {
l[0], l[1],
h[0], l[1],
h[0], h[1],
l[0], h[1]
};
glDrawVertices(4, verts, mode, 2);
}
template<typename T>
inline void glDrawAlignedBoxPerimeter( const Eigen::AlignedBox<T,2>& box)
{
glDrawAlignedBox<T>(box, GL_LINE_LOOP);
}
template<typename T>
inline void glDrawAlignedBox( const Eigen::AlignedBox<T,3>& box)
{
const Eigen::Matrix<float,3,1> l = box.min().template cast<float>();
const Eigen::Matrix<float,3,1> h = box.max().template cast<float>();
GLfloat verts[] = {
l[0], l[1], l[2],
l[0], l[1], h[2],
h[0], l[1], h[2],
h[0], l[1], l[2],
l[0], l[1], l[2],
l[0], h[1], l[2],
h[0], h[1], l[2],
h[0], l[1], l[2],
h[0], h[1], l[2],
h[0], h[1], h[2],
l[0], h[1], h[2],
l[0], h[1], l[2],
l[0], h[1], h[2],
l[0], l[1], h[2],
h[0], l[1], h[2],
h[0], h[1], h[2]
};
glDrawVertices(16, verts, GL_LINE_STRIP, 3);
}
#endif // USE_EIGEN
#ifndef HAVE_GLES
inline void glPixelTransferScale( float r, float g, float b )
{
glPixelTransferf(GL_RED_SCALE,r);
glPixelTransferf(GL_GREEN_SCALE,g);
glPixelTransferf(GL_BLUE_SCALE,b);
}
inline void glPixelTransferScale( float scale )
{
glPixelTransferScale(scale,scale,scale);
}
#endif
void glRecordGraphic(float x, float y, float radius);
}

View File

@@ -0,0 +1,78 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2015 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/gltext.h>
#include <cstdio>
#include <cstdarg>
namespace pangolin {
class PANGOLIN_EXPORT GlFont
{
public:
// Singleton instance if requested.
static GlFont& I();
// Load GL Font data. Delay uploading as texture until first use.
GlFont(const unsigned char* ttf_buffer, float pixel_height, int tex_w=512, int tex_h=512);
GlFont(const std::string& filename, float pixel_height, int tex_w=512, int tex_h=512);
virtual ~GlFont();
// Generate renderable GlText object from this font.
GlText Text( const char* fmt, ... );
GlText Text( const std::string& str );
inline float Height() const {
return font_height_px;
}
protected:
void InitialiseFont(const unsigned char* ttf_buffer, float pixel_height, int tex_w, int tex_h);
// This can only be called once GL context is initialised
void InitialiseGlTexture();
const static int FIRST_CHAR = 32;
const static int NUM_CHARS = 96;
float font_height_px;
int tex_w;
int tex_h;
unsigned char* font_bitmap;
GlTexture mTex;
GlChar chardata[NUM_CHARS];
GLfloat kern_table[NUM_CHARS*NUM_CHARS];
};
}

View File

@@ -0,0 +1,214 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#ifdef HAVE_EIGEN
# include <Eigen/Core>
#endif
namespace pangolin
{
template<typename T>
struct GlFormatTraits;
//{
// static const GLint glinternalformat = 0;
// static const GLenum glformat = 0;
// static const GLenum gltype = 0;
// static const T glmin = 0;
// static const T glmax = 0;
//};
template<>
struct GlFormatTraits<unsigned char>
{
static const GLint glinternalformat = GL_LUMINANCE8;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_UNSIGNED_BYTE;
static const size_t components = 1;
};
template<>
struct GlFormatTraits<unsigned short>
{
static const GLint glinternalformat = GL_LUMINANCE16;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_UNSIGNED_SHORT;
static const size_t components = 1;
};
template<>
struct GlFormatTraits<unsigned int>
{
static const GLint glinternalformat = GL_LUMINANCE32I_EXT;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_UNSIGNED_INT;
static const size_t components = 1;
};
template<>
struct GlFormatTraits<int>
{
static const GLint glinternalformat = GL_LUMINANCE32I_EXT;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_INT;
static const size_t components = 1;
};
template<>
struct GlFormatTraits<float>
{
static const GLint glinternalformat = GL_LUMINANCE32F_ARB;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_FLOAT;
static const size_t components = 1;
};
template<>
struct GlFormatTraits<double>
{
static const GLint glinternalformat = GL_LUMINANCE32F_ARB;
static const GLenum glformat = GL_LUMINANCE;
static const GLenum gltype = GL_DOUBLE;
static const size_t components = 1;
};
#ifdef HAVE_EIGEN
//////////////////////////////////////////////////////////////////
template <>
struct GlFormatTraits<Eigen::Vector2i>
{
static const GLint glinternalformat = GL_RG32I;
static const GLenum glformat = GL_RG;
static const GLenum gltype = GL_INT;
static const size_t components = 2;
};
template <>
struct GlFormatTraits<Eigen::Vector2f>
{
static const GLint glinternalformat = GL_RG32F;
static const GLenum glformat = GL_RG;
static const GLenum gltype = GL_FLOAT;
static const size_t components = 2;
};
template <>
struct GlFormatTraits<Eigen::Vector2d>
{
static const GLint glinternalformat = GL_RG32F;
static const GLenum glformat = GL_RG;
static const GLenum gltype = GL_DOUBLE;
static const size_t components = 2;
};
//////////////////////////////////////////////////////////////////
template <>
struct GlFormatTraits<Eigen::Matrix<unsigned char,3,1>>
{
static const GLint glinternalformat = GL_RGB8;
static const GLenum glformat = GL_RGB;
static const GLenum gltype = GL_UNSIGNED_BYTE;
static const size_t components = 3;
};
template <>
struct GlFormatTraits<Eigen::Matrix<unsigned short,3,1>>
{
static const GLint glinternalformat = GL_RGBA16;
static const GLenum glformat = GL_RGB;
static const GLenum gltype = GL_UNSIGNED_SHORT;
static const size_t components = 3;
};
template <>
struct GlFormatTraits<Eigen::Vector3f>
{
static const GLint glinternalformat = GL_RGB32F;
static const GLenum glformat = GL_RGB;
static const GLenum gltype = GL_FLOAT;
static const size_t components = 3;
};
template <>
struct GlFormatTraits<Eigen::Vector3d>
{
static const GLint glinternalformat = GL_RGB32F;
static const GLenum glformat = GL_RGB;
static const GLenum gltype = GL_DOUBLE;
static const size_t components = 3;
};
//////////////////////////////////////////////////////////////////
template <>
struct GlFormatTraits<Eigen::Matrix<unsigned char,4,1>>
{
static const GLint glinternalformat = GL_RGBA8;
static const GLenum glformat = GL_RGBA;
static const GLenum gltype = GL_UNSIGNED_BYTE;
static const size_t components = 4;
};
template <>
struct GlFormatTraits<Eigen::Matrix<unsigned short,4,1>>
{
static const GLint glinternalformat = GL_RGBA16;
static const GLenum glformat = GL_RGBA;
static const GLenum gltype = GL_UNSIGNED_SHORT;
static const size_t components = 4;
};
template <>
struct GlFormatTraits<Eigen::Vector4f>
{
static const GLint glinternalformat = GL_RGBA32F;
static const GLenum glformat = GL_RGBA;
static const GLenum gltype = GL_FLOAT;
static const size_t components = 4;
};
template <>
struct GlFormatTraits<Eigen::Vector4d>
{
static const GLint glinternalformat = GL_RGBA32F;
static const GLenum glformat = GL_RGBA;
static const GLenum gltype = GL_DOUBLE;
static const size_t components = 4;
};
#endif // HAVE_EIGEN
}

View File

@@ -0,0 +1,46 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#ifdef HAVE_GLES
#include <pangolin/gl/compat/gl_es_compat.h>
#endif
#define CheckGlDieOnError() pangolin::_CheckGlDieOnError( __FILE__, __LINE__ );
namespace pangolin {
inline void _CheckGlDieOnError( const char *sFile, const int nLine )
{
const GLenum glError = glGetError();
if( glError != GL_NO_ERROR ) {
pango_print_error("OpenGL Error %x: %s\n", glError, glErrorString(glError));
pango_print_error("In: %s, line %d\n", sFile, nLine);
}
}
}

View File

@@ -0,0 +1,79 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
namespace pangolin {
PANGOLIN_EXPORT
const char* glErrorString(GLenum error);
/// Clone of gluProject
PANGOLIN_EXPORT
GLint glProject(
float objx, float objy, float objz,
const float modelMatrix[16],
const float projMatrix[16],
const GLint viewport[4],
float* winx, float* winy, float* winz
);
/// Clone of gluUnProject
PANGOLIN_EXPORT
GLint glUnProject(
float winx, float winy, float winz,
const float modelMatrix[16],
const float projMatrix[16],
const GLint viewport[4],
float* objx, float* objy, float* objz
);
/// Clone of gluProject
PANGOLIN_EXPORT
GLint glProject(
double objx, double objy, double objz,
const double modelMatrix[16],
const double projMatrix[16],
const GLint viewport[4],
double* winx, double* winy, double* winz
);
/// Clone of gluUnProject
PANGOLIN_EXPORT
GLint glUnProject(
double winx, double winy, double winz,
const double modelMatrix[16],
const double projMatrix[16],
const GLint viewport[4],
double* objx, double* objy, double* objz
);
}

View File

@@ -0,0 +1,95 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#include <pangolin/gl/glformattraits.h>
#include <pangolin/image/pixel_format.h>
#include <stdexcept>
namespace pangolin {
// This class may dissapear in the future
struct GlPixFormat
{
GlPixFormat() {}
GlPixFormat(const PixelFormat& fmt)
{
switch( fmt.channels) {
case 1: glformat = GL_LUMINANCE; break;
case 3: glformat = (fmt.format == "BGR24" || fmt.format == "BGR48") ? GL_BGR : GL_RGB; break;
case 4: glformat = (fmt.format == "BGRA24" || fmt.format == "BGRA32" || fmt.format == "BGRA48") ? GL_BGRA : GL_RGBA; break;
default: throw std::runtime_error("Unable to form OpenGL format from video format: '" + fmt.format + "'.");
}
const bool is_integral = fmt.format.find('F') == std::string::npos;
switch (fmt.channel_bits[0]) {
case 8: gltype = GL_UNSIGNED_BYTE; break;
case 16: gltype = GL_UNSIGNED_SHORT; break;
case 32: gltype = (is_integral ? GL_UNSIGNED_INT : GL_FLOAT); break;
case 64: gltype = (is_integral ? GL_UNSIGNED_INT64_NV : GL_DOUBLE); break;
default: throw std::runtime_error("Unknown OpenGL data type for video format: '" + fmt.format + "'.");
}
if(glformat == GL_LUMINANCE) {
if(gltype == GL_UNSIGNED_BYTE) {
scalable_internal_format = GL_LUMINANCE8;
}else if(gltype == GL_UNSIGNED_SHORT){
scalable_internal_format = GL_LUMINANCE16;
}else{
scalable_internal_format = GL_LUMINANCE32F_ARB;
}
}else{
if(gltype == GL_UNSIGNED_BYTE) {
scalable_internal_format = GL_RGBA8;
}else if(gltype == GL_UNSIGNED_SHORT) {
scalable_internal_format = GL_RGBA16;
}else{
scalable_internal_format = GL_RGBA32F;
}
}
}
template<typename T>
static GlPixFormat FromType()
{
GlPixFormat fmt;
fmt.glformat = GlFormatTraits<T>::glformat;
fmt.gltype = GlFormatTraits<T>::gltype;
fmt.scalable_internal_format = GlFormatTraits<T>::glinternalformat;
return fmt;
}
GLint glformat;
GLenum gltype;
GLint scalable_internal_format;
};
}

View File

@@ -0,0 +1,83 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
//////////////////////////////////////////////////////////
// Attempt to portably include Necessary OpenGL headers
//////////////////////////////////////////////////////////
#include <pangolin/platform.h>
#ifdef _WIN_
// Define maths quantities when using <cmath> to match posix systems
#ifndef _USE_MATH_DEFINES
# define _USE_MATH_DEFINES
#endif
// Don't define min / max macros in windows.h or other unnecessary macros
#ifndef NOMINMAX
# define NOMINMAX
#endif
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
// Undef nuisance Windows.h macros which interfere with our methods
#undef LoadImage
#undef near
#undef far
#undef ERROR
#endif
#include <GL/glew.h>
#ifdef HAVE_GLES
#if defined(_ANDROID_)
#include <EGL/egl.h>
#ifdef HAVE_GLES_2
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#else
#include <GLES/gl.h>
#define GL_GLEXT_PROTOTYPES
#include <GLES/glext.h>
#endif
#elif defined(_APPLE_IOS_)
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#endif
#else
#ifdef _OSX_
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif
#endif // HAVE_GLES
#include <pangolin/gl/glpangoglu.h>

View File

@@ -0,0 +1,738 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <sstream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <pangolin/gl/glplatform.h>
#include <pangolin/gl/colour.h>
#include <pangolin/utils/file_utils.h>
#include <pangolin/display/opengl_render_state.h>
#ifdef HAVE_GLES
#define GLhandleARB GLuint
#endif
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#endif // USE_EIGEN
namespace pangolin
{
////////////////////////////////////////////////
// Standard attribute locations
////////////////////////////////////////////////
const GLuint DEFAULT_LOCATION_POSITION = 0;
const GLuint DEFAULT_LOCATION_COLOUR = 1;
const GLuint DEFAULT_LOCATION_NORMAL = 2;
const GLuint DEFAULT_LOCATION_TEXCOORD = 3;
const char DEFAULT_NAME_POSITION[] = "a_position";
const char DEFAULT_NAME_COLOUR[] = "a_color";
const char DEFAULT_NAME_NORMAL[] = "a_normal";
const char DEFAULT_NAME_TEXCOORD[] = "a_texcoord";
////////////////////////////////////////////////
// Interface
////////////////////////////////////////////////
enum GlSlShaderType
{
GlSlAnnotatedShader = 0,
GlSlFragmentShader = GL_FRAGMENT_SHADER,
GlSlVertexShader = GL_VERTEX_SHADER,
GlSlGeometryShader = 0x8DD9 /*GL_GEOMETRY_SHADER*/,
GlSlComputeShader = 0x91B9 /*GL_COMPUTE_SHADER*/
};
class GlSlProgram
{
public:
GlSlProgram();
//! Move Constructor
GlSlProgram(GlSlProgram&& tex);
~GlSlProgram();
bool AddShader(
GlSlShaderType shader_type,
const std::string& source_code,
const std::map<std::string,std::string>& program_defines = std::map<std::string,std::string>(),
const std::vector<std::string>& search_path = std::vector<std::string>()
);
bool AddShaderFromFile(
GlSlShaderType shader_type,
const std::string& filename,
const std::map<std::string,std::string>& program_defines = std::map<std::string,std::string>(),
const std::vector<std::string>& search_path = std::vector<std::string>()
);
bool Link();
// Remove all shaders from this program, and reload from files.
bool ReloadShaderFiles();
GLint GetAttributeHandle(const std::string& name);
GLint GetUniformHandle(const std::string& name);
// Before setting uniforms, be sure to Bind() the GlSl program first.
void SetUniform(const std::string& name, int x);
void SetUniform(const std::string& name, int x1, int x2);
void SetUniform(const std::string& name, int x1, int x2, int x3);
void SetUniform(const std::string& name, int x1, int x2, int x3, int x4);
void SetUniform(const std::string& name, float f);
void SetUniform(const std::string& name, float f1, float f2);
void SetUniform(const std::string& name, float f1, float f2, float f3);
void SetUniform(const std::string& name, float f1, float f2, float f3, float f4);
void SetUniform(const std::string& name, Colour c);
void SetUniform(const std::string& name, const OpenGlMatrix& m);
#ifdef HAVE_EIGEN
void SetUniform(const std::string& name, const Eigen::Matrix3f& m);
void SetUniform(const std::string& name, const Eigen::Matrix4f& m);
void SetUniform(const std::string& name, const Eigen::Matrix3d& m);
void SetUniform(const std::string& name, const Eigen::Matrix4d& m);
#endif
#if GL_VERSION_4_3
GLint GetProgramResourceIndex(const std::string& name);
void SetShaderStorageBlock(const std::string& name, const int& bindingIndex);
#endif
void Bind();
void SaveBind();
void Unbind();
void BindPangolinDefaultAttribLocationsAndLink();
// Unlink all shaders from program
void ClearShaders();
GLint ProgramId() const {
return prog;
}
bool Valid() const {
return ProgramId() != 0;
}
protected:
struct ShaderFileOrCode
{
GlSlShaderType shader_type;
std::string filename;
std::string code;
std::map<std::string,std::string> program_defines;
std::vector<std::string> search_path;
};
// Convenience method to load shader description
bool AddShaderFile(const ShaderFileOrCode &shader_file);
std::string ParseIncludeFilename(
const std::string& location
);
std::string SearchIncludePath(
const std::string& filename,
const std::vector<std::string>& search_path,
const std::string& current_path
);
bool AddPreprocessedShader(
GlSlShaderType shader_type,
const std::string& source_code,
const std::string& name_for_errors
);
void PreprocessGLSL(
std::istream& input,
std::ostream& output,
const std::map<std::string,std::string>& program_defines,
const std::vector<std::string>& search_path,
const std::string& current_path
);
// Split 'code' into several code blocks per shader type
// shader blocks in 'code' must be annotated with:
// @start vertex, @start fragment, @start geometry or @start compute
static std::map<GlSlShaderType,std::string>
SplitAnnotatedShaders(const std::string& code);
bool linked;
std::vector<GLhandleARB> shaders;
GLenum prog;
GLint prev_prog;
std::vector<ShaderFileOrCode> shader_files;
};
class GlSlUtilities
{
public:
inline static GlSlProgram& OffsetAndScale(float offset, float scale) {
GlSlProgram& prog = Instance().prog_offsetscale;
prog.Bind();
prog.SetUniform("offset", offset);
prog.SetUniform("scale", scale);
return prog;
}
inline static GlSlProgram& Scale(float scale, float bias = 0.0f) {
GlSlProgram& prog = Instance().prog_scale;
prog.Bind();
prog.SetUniform("scale", scale);
prog.SetUniform("bias", bias);
return prog;
}
inline static void UseNone()
{
glUseProgram(0);
}
protected:
static GlSlUtilities& Instance() {
// TODO: BUG: The GlSLUtilities instance needs to be tied
// to the OpenGL context, not the thread, or globally.
#ifndef PANGO_NO_THREADLOCAL
thread_local
#else
static
#endif
GlSlUtilities instance;
return instance;
}
// protected constructor
GlSlUtilities() {
const char* source_scale =
"uniform float scale;"
"uniform float bias;"
"uniform sampler2D tex;"
"void main() {"
" vec2 uv = gl_TexCoord[0].st;"
" if(0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0) {"
" gl_FragColor = texture2D(tex,uv);"
" gl_FragColor.xyz *= scale;"
" gl_FragColor.xyz += vec3(bias,bias,bias);"
" }else{"
" float v = 0.1;"
" gl_FragColor.xyz = vec3(v,v,v);"
" }"
"}";
prog_scale.AddShader(GlSlFragmentShader, source_scale);
prog_scale.Link();
const char* source_offsetscale =
"uniform float offset;"
"uniform float scale;"
"uniform sampler2D tex;"
"void main() {"
" vec2 uv = gl_TexCoord[0].st;"
" if(0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0) {"
" gl_FragColor = texture2D(tex,gl_TexCoord[0].st);"
" gl_FragColor.xyz += vec3(offset,offset,offset);"
" gl_FragColor.xyz *= scale;"
" }else{"
" float v = 0.1;"
" gl_FragColor.xyz = vec3(v,v,v);"
" }"
"}";
prog_offsetscale.AddShader(GlSlFragmentShader, source_offsetscale);
prog_offsetscale.Link();
}
GlSlProgram prog_scale;
GlSlProgram prog_offsetscale;
};
////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////
inline bool IsLinkSuccessPrintLog(GLhandleARB prog)
{
GLint status;
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if(status != GL_TRUE) {
pango_print_error("GLSL Program link failed: ");
const int PROGRAM_LOG_MAX_LEN = 10240;
char infolog[PROGRAM_LOG_MAX_LEN];
GLsizei len;
glGetProgramInfoLog(prog, PROGRAM_LOG_MAX_LEN, &len, infolog);
if(len) {
pango_print_error("%s\n",infolog);
}else{
pango_print_error("No details provided.\n");
}
return false;
}
return true;
}
inline bool IsCompileSuccessPrintLog(GLhandleARB shader, const std::string& name_for_errors)
{
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status != GL_TRUE) {
pango_print_error("GLSL Shader compilation failed: ");
const int SHADER_LOG_MAX_LEN = 10240;
char infolog[SHADER_LOG_MAX_LEN];
GLsizei len;
glGetShaderInfoLog(shader, SHADER_LOG_MAX_LEN, &len, infolog);
if(len) {
pango_print_error("%s:\n%s\n",name_for_errors.c_str(), infolog);
}else{
pango_print_error("%s:\nNo details provided.\n",name_for_errors.c_str());
}
return false;
}
return true;
}
inline GlSlProgram::GlSlProgram()
: linked(false), prog(0), prev_prog(0)
{
}
//! Move Constructor
inline GlSlProgram::GlSlProgram(GlSlProgram&& o)
: linked(o.linked), shaders(o.shaders), prog(o.prog), prev_prog(o.prev_prog)
{
o.prog = 0;
}
inline GlSlProgram::~GlSlProgram()
{
if(prog) {
ClearShaders();
glDeleteProgram(prog);
}
}
inline void PrintSourceCode(const std::string& src)
{
std::stringstream ss(src);
std::string line;
for(int linenum=1; std::getline(ss,line,'\n'); ++linenum) {
std::cout << linenum << ":\t" << line << std::endl;
}
}
inline bool GlSlProgram::AddPreprocessedShader(
GlSlShaderType shader_type,
const std::string& source_code,
const std::string& name_for_errors
) {
if(!prog) {
prog = glCreateProgram();
}
// PrintSourceCode(source_code);
GLhandleARB shader = glCreateShader(shader_type);
const char* source = source_code.c_str();
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
bool success = IsCompileSuccessPrintLog(shader, name_for_errors);
if(success) {
glAttachShader(prog, shader);
shaders.push_back(shader);
linked = false;
}
return success;
}
inline std::string GlSlProgram::ParseIncludeFilename(const std::string& location)
{
size_t start = location.find_first_of("\"<");
if(start != std::string::npos) {
size_t end = location.find_first_of("\">", start+1);
if(end != std::string::npos) {
return location.substr(start+1, end - start - 1);
}
}
throw std::runtime_error("GLSL Parser: Unable to parse include location " + location );
}
inline std::string GlSlProgram::SearchIncludePath(
const std::string& filename,
const std::vector<std::string>& search_path,
const std::string& current_path
) {
if(FileExists(current_path + "/" + filename)) {
return current_path + "/" + filename;
}else{
for(size_t i=0; i < search_path.size(); ++i) {
const std::string hypoth = search_path[i] + "/" + filename;
if( FileExists(hypoth) ) {
return hypoth;
}
}
}
return "";
}
inline void GlSlProgram::PreprocessGLSL(
std::istream& input, std::ostream& output,
const std::map<std::string,std::string>& program_defines,
const std::vector<std::string> &search_path,
const std::string &current_path
) {
const size_t MAXLINESIZE = 10240;
char line[MAXLINESIZE] = "";
while(!input.eof()) {
// Take like from source
input.getline(line,MAXLINESIZE);
// Transform
if( !strncmp(line, "#include", 8 ) ) {
// C++ / G3D style include directive
const std::string import_file = ParseIncludeFilename(line+8);
const std::string resolved_file = SearchIncludePath(import_file, search_path, current_path);
std::ifstream ifs(resolved_file.c_str());
if(ifs.good()) {
const std::string file_path = pangolin::PathParent(resolved_file);
PreprocessGLSL(ifs, output, program_defines, search_path, file_path);
}else{
throw std::runtime_error("GLSL Parser: Unable to open " + import_file );
}
}else if( !strncmp(line, "#expect", 7) ) {
// G3D style 'expect' directive, annotating expected preprocessor
// definition with document string
// Consume whitespace before token
size_t token_start = 7;
while( std::isspace(line[token_start]) ) ++token_start;
// Iterate over contigous charecters until \0 or whitespace
size_t token_end = token_start;
while( line[token_end] && !std::isspace(line[token_end]) ) ++token_end;
std::string token(line+token_start, line+token_end);
std::map<std::string,std::string>::const_iterator it = program_defines.find(token);
if( it == program_defines.end() ) {
pango_print_warn("Expected define missing (defaulting to 0): '%s'\n%s\n", token.c_str(), line + token_end );
output << "#define " << token << " 0" << std::endl;
}else{
output << "#define " << token << " " << it->second << std::endl;
}
}else{
// Output directly
output << line << std::endl;
}
}
}
inline void GlSlProgram::ClearShaders()
{
// Remove and delete each shader
for(size_t i=0; i<shaders.size(); ++i ) {
glDetachShader(prog, shaders[i]);
glDeleteShader(shaders[i]);
}
shaders.clear();
}
inline bool GlSlProgram::AddShaderFile(const ShaderFileOrCode& shader_file)
{
std::stringstream buffer;
if(shader_file.code.empty()) {
std::ifstream ifs(shader_file.filename.c_str());
if(ifs.is_open()) {
PreprocessGLSL(ifs, buffer, shader_file.program_defines, shader_file.search_path, ".");
}else{
throw std::runtime_error(FormatString("Unable to open shader file '%'", shader_file.filename));
}
}else{
std::istringstream iss(shader_file.code);
PreprocessGLSL(iss, buffer, shader_file.program_defines, shader_file.search_path, ".");
}
const std::string code = buffer.str();
const std::string input_name = !shader_file.filename.empty() ? shader_file.filename : "<string>";
if(shader_file.shader_type == GlSlAnnotatedShader) {
const std::map<GlSlShaderType,std::string> split_progs = SplitAnnotatedShaders(code);
for(const auto& type_code : split_progs) {
if(!AddPreprocessedShader(type_code.first, type_code.second, input_name )) {
return false;
}
}
return true;
}else{
return AddPreprocessedShader(shader_file.shader_type, code, input_name);
}
}
inline bool GlSlProgram::AddShaderFromFile(
GlSlShaderType shader_type,
const std::string& filename,
const std::map<std::string,std::string>& program_defines,
const std::vector<std::string>& search_path
) {
ShaderFileOrCode shader_file = {
shader_type,
pangolin::PathExpand(filename),
std::string(),
program_defines,
search_path
};
shader_files.push_back(shader_file);
return AddShaderFile(shader_file);
}
inline bool GlSlProgram::AddShader(
GlSlShaderType shader_type,
const std::string& source_code,
const std::map<std::string,std::string>& program_defines,
const std::vector<std::string>& search_path
) {
ShaderFileOrCode shader_file = {
shader_type,
std::string(),
source_code,
program_defines,
search_path
};
shader_files.push_back(shader_file);
return AddShaderFile(shader_file);
}
inline bool GlSlProgram::ReloadShaderFiles()
{
ClearShaders();
for(const auto& sf : shader_files) {
if(!AddShaderFile(sf)) {
return false;
}
}
Link();
return true;
}
inline std::map<GlSlShaderType,std::string>
GlSlProgram::SplitAnnotatedShaders(const std::string& code)
{
std::map<GlSlShaderType,std::string> ret;
std::stringstream input(code);
std::stringstream output;
const size_t MAXLINESIZE = 10240;
char line[MAXLINESIZE];
GlSlShaderType current_type = GlSlAnnotatedShader;
auto finish_block = [&](GlSlShaderType type){
if(current_type != GlSlAnnotatedShader) {
ret[current_type] = output.str();
}
output.str(std::string());
current_type = type;
};
while(!input.eof()) {
// Take like from source
input.getline(line,MAXLINESIZE);
// Transform
if( !strncmp(line, "@start", 6 ) ) {
const std::string str_shader_type = pangolin::Trim(std::string(line).substr(6));
if(str_shader_type == "vertex") {
finish_block(GlSlVertexShader);
}else if(str_shader_type == "fragment") {
finish_block(GlSlFragmentShader);
}else if(str_shader_type == "geometry") {
finish_block(GlSlGeometryShader);
}else if(str_shader_type == "compute") {
finish_block(GlSlComputeShader);
}
}else{
output << line << std::endl;
}
}
finish_block(GlSlAnnotatedShader);
return ret;
}
inline bool GlSlProgram::Link()
{
glLinkProgram(prog);
return IsLinkSuccessPrintLog(prog);
}
inline void GlSlProgram::Bind()
{
prev_prog = 0;
glUseProgram(prog);
}
inline void GlSlProgram::SaveBind()
{
glGetIntegerv(GL_CURRENT_PROGRAM, &prev_prog);
glUseProgram(prog);
}
inline void GlSlProgram::Unbind()
{
glUseProgram(prev_prog);
}
inline GLint GlSlProgram::GetAttributeHandle(const std::string& name)
{
return glGetAttribLocation(prog, name.c_str());
}
inline GLint GlSlProgram::GetUniformHandle(const std::string& name)
{
return glGetUniformLocation(prog, name.c_str());
}
inline void GlSlProgram::SetUniform(const std::string& name, int x)
{
glUniform1i( GetUniformHandle(name), x);
}
inline void GlSlProgram::SetUniform(const std::string& name, int x1, int x2)
{
glUniform2i( GetUniformHandle(name), x1, x2);
}
inline void GlSlProgram::SetUniform(const std::string& name, int x1, int x2, int x3)
{
glUniform3i( GetUniformHandle(name), x1, x2, x3);
}
inline void GlSlProgram::SetUniform(const std::string& name, int x1, int x2, int x3, int x4)
{
glUniform4i( GetUniformHandle(name), x1, x2, x3, x4);
}
inline void GlSlProgram::SetUniform(const std::string& name, float f)
{
glUniform1f( GetUniformHandle(name), f);
}
inline void GlSlProgram::SetUniform(const std::string& name, float f1, float f2)
{
glUniform2f( GetUniformHandle(name), f1,f2);
}
inline void GlSlProgram::SetUniform(const std::string& name, float f1, float f2, float f3)
{
glUniform3f( GetUniformHandle(name), f1,f2,f3);
}
inline void GlSlProgram::SetUniform(const std::string& name, float f1, float f2, float f3, float f4)
{
glUniform4f( GetUniformHandle(name), f1,f2,f3,f4);
}
inline void GlSlProgram::SetUniform(const std::string& name, Colour c)
{
glUniform4f( GetUniformHandle(name), c.r, c.g, c.b, c.a);
}
inline void GlSlProgram::SetUniform(const std::string& name, const OpenGlMatrix& mat)
{
// glUniformMatrix4dv seems to be crashing...
float m[16];
for (int i = 0; i < 16; ++i) {
m[i] = (float)mat.m[i];
}
glUniformMatrix4fv( GetUniformHandle(name), 1, GL_FALSE, m);
}
#ifdef HAVE_EIGEN
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix3f& m)
{
glUniformMatrix3fv( GetUniformHandle(name), 1, GL_FALSE, m.data());
}
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix4f& m)
{
glUniformMatrix4fv( GetUniformHandle(name), 1, GL_FALSE, m.data());
}
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix3d& m)
{
glUniformMatrix3dv( GetUniformHandle(name), 1, GL_FALSE, m.data());
}
inline void GlSlProgram::SetUniform(const std::string& name, const Eigen::Matrix4d& m)
{
glUniformMatrix4dv( GetUniformHandle(name), 1, GL_FALSE, m.data());
}
#endif
inline void GlSlProgram::BindPangolinDefaultAttribLocationsAndLink()
{
glBindAttribLocation(prog, DEFAULT_LOCATION_POSITION, DEFAULT_NAME_POSITION);
glBindAttribLocation(prog, DEFAULT_LOCATION_COLOUR, DEFAULT_NAME_COLOUR);
glBindAttribLocation(prog, DEFAULT_LOCATION_NORMAL, DEFAULT_NAME_NORMAL);
glBindAttribLocation(prog, DEFAULT_LOCATION_TEXCOORD, DEFAULT_NAME_TEXCOORD);
Link();
}
#if GL_VERSION_4_3
inline GLint GlSlProgram::GetProgramResourceIndex(const std::string& name)
{
return glGetProgramResourceIndex(prog, GL_SHADER_STORAGE_BLOCK, name.c_str());
}
inline void GlSlProgram::SetShaderStorageBlock(const std::string& name, const int& bindingIndex)
{
glShaderStorageBlockBinding(prog, GetProgramResourceIndex(name), bindingIndex);
}
#endif
}

View File

@@ -0,0 +1,220 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Vincent Mamo, Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glinclude.h>
#include <stack>
namespace pangolin
{
class GlState {
class CapabilityState {
public:
CapabilityState(GLenum cap, GLboolean enable)
: m_cap(cap), m_enable(enable)
{
}
void Apply() {
if(m_enable) {
::glEnable(m_cap);
}else{
::glDisable(m_cap);
}
}
void UnApply() {
if(m_enable) {
::glDisable(m_cap);
}else{
::glEnable(m_cap);
}
}
protected:
GLenum m_cap;
GLboolean m_enable;
};
public:
GlState()
: m_DepthMaskCalled(false),
m_ShadeModelCalled(false),
m_CullFaceCalled(false),
m_PointSizeCalled(false),
m_LineWidthCalled(false),
m_ColorMaskCalled(false),
m_ViewportCalled(false)
{
}
~GlState() {
// Restore original state
while (!m_history.empty()) {
m_history.top().UnApply();
m_history.pop();
}
if (m_DepthMaskCalled) {
::glDepthMask(m_OriginalDepthMask);
}
if (m_ShadeModelCalled) {
::glShadeModel(m_OriginalShadeModel);
}
if (m_CullFaceCalled) {
::glCullFace(m_OriginalCullFace);
}
if(m_PointSizeCalled) {
::glPointSize(m_OriginalPointSize);
}
if(m_LineWidthCalled) {
::glLineWidth(m_OriginalLineWidth);
}
if (m_ColorMaskCalled) {
::glColorMask(m_OriginalColorMask[0], m_OriginalColorMask[1], m_OriginalColorMask[2], m_OriginalColorMask[3]);
}
if (m_ViewportCalled) {
::glViewport(m_OriginalViewport[0], m_OriginalViewport[1], m_OriginalViewport[2], m_OriginalViewport[3]);
}
}
static inline GLboolean IsEnabled(GLenum cap)
{
GLboolean curVal;
glGetBooleanv(cap, &curVal);
return curVal;
}
inline void glEnable(GLenum cap)
{
if(!IsEnabled(cap)) {
m_history.push(CapabilityState(cap,true));
::glEnable(cap);
}
}
inline void glDisable(GLenum cap)
{
if(IsEnabled(cap)) {
m_history.push(CapabilityState(cap,false));
::glDisable(cap);
}
}
bool m_DepthMaskCalled;
GLboolean m_OriginalDepthMask;
inline void glDepthMask(GLboolean flag)
{
if(!m_DepthMaskCalled) {
m_DepthMaskCalled = true;
glGetBooleanv(GL_DEPTH_WRITEMASK, &m_OriginalDepthMask);
}
::glDepthMask(flag);
}
bool m_ShadeModelCalled;
GLint m_OriginalShadeModel;
inline void glShadeModel(GLint mode)
{
if(!m_ShadeModelCalled) {
m_ShadeModelCalled = true;
glGetIntegerv(GL_SHADE_MODEL, &m_OriginalShadeModel);
}
::glShadeModel(mode);
}
bool m_CullFaceCalled;
GLint m_OriginalCullFace;
void glCullFace(GLenum mode)
{
if(!m_ShadeModelCalled) {
m_ShadeModelCalled = true;
glGetIntegerv(GL_CULL_FACE_MODE, &m_OriginalCullFace);
}
::glCullFace(mode);
}
bool m_PointSizeCalled;
GLfloat m_OriginalPointSize;
void glPointSize(GLfloat size)
{
if(!m_PointSizeCalled) {
m_PointSizeCalled = true;
glGetFloatv(GL_POINT_SIZE, &m_OriginalPointSize);
}
::glPointSize(size);
}
bool m_LineWidthCalled;
GLfloat m_OriginalLineWidth;
void glLineWidth(GLfloat width)
{
if(!m_LineWidthCalled) {
m_LineWidthCalled = true;
glGetFloatv(GL_LINE_WIDTH, &m_OriginalLineWidth);
}
::glLineWidth(width);
}
bool m_ColorMaskCalled;
GLboolean m_OriginalColorMask[4];
inline void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
{
if(!m_ColorMaskCalled) {
m_ColorMaskCalled = true;
glGetBooleanv(GL_COLOR_WRITEMASK, m_OriginalColorMask);
}
::glColorMask(red, green, blue, alpha);
}
bool m_ViewportCalled;
GLint m_OriginalViewport[4];
inline void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
{
if(!m_ViewportCalled) {
m_ViewportCalled = true;
glGetIntegerv(GL_VIEWPORT, m_OriginalViewport);
}
::glViewport(x, y, width, height);
}
std::stack<CapabilityState> m_history;
};
}

View File

@@ -0,0 +1,98 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glchar.h>
#include <vector>
#include <string>
namespace pangolin {
class PANGOLIN_EXPORT GlText
{
public:
GlText();
GlText(const GlText& txt);
GlText(const GlTexture& font_tex);
void AddSpace(GLfloat s);
// Add specified charector to this string.
void Add(unsigned char c, const GlChar& glc);
// Clear text
void Clear();
// Render without transform in text-centric pixel coordinates
void Draw() const;
void DrawGlSl() const;
#ifdef BUILD_PANGOLIN_GUI
// Render at (x,y,z)' in object coordinates,
// keeping text size and orientation constant
void Draw(GLfloat x, GLfloat y, GLfloat z = 0.0f) const;
// Render at (x,y,z)' in window coordinates.
void DrawWindow(GLfloat x, GLfloat y, GLfloat z = 0.0f) const;
#endif // BUILD_PANGOLIN_GUI
// Return text that this object signifies.
const std::string& Text() const {
return str;
}
// Return width in pixels of this text.
GLfloat Width() const {
return width;
}
// Return height in pixels of this text.
GLfloat Height() const {
return ymax;
}
// Return height in pixels of this text, including under baseline
GLfloat FullHeight() const {
return ymax - ymin;
}
//protected:
const GlTexture* tex;
std::string str;
GLfloat width;
GLfloat ymin;
GLfloat ymax;
std::vector<XYUV> vs;
};
}

View File

@@ -0,0 +1,116 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glformattraits.h>
#include <pangolin/gl/glpixformat.h>
#include <pangolin/image/image.h>
#include <memory>
#include <map>
namespace pangolin
{
class PANGOLIN_EXPORT TextureCache
{
public:
static TextureCache& I();
GlTexture& GlTex(GLsizei w, GLsizei h, GLint internal_format, GLint glformat, GLenum gltype)
{
const long key =
(((long)internal_format)<<20) ^
(((long)glformat)<<10) ^ gltype;
// Lookup texture
std::shared_ptr<GlTexture>& ptex = texture_map[key];
if(!ptex) {
ptex = std::shared_ptr<GlTexture>(new GlTexture());
}
GlTexture& tex = *ptex;
// Initialise if it didn't already exist or the size was too small
if(!tex.tid || tex.width < w || tex.height < h) {
tex.Reinitialise(
std::max(tex.width,w), std::max(tex.height,h),
internal_format, default_sampling_linear, 0,
glformat, gltype
);
}
return tex;
}
template<typename T>
GlTexture& GlTex(GLsizei w, GLsizei h)
{
return GlTex( w, h,
GlFormatTraits<T>::glinternalformat,
GlFormatTraits<T>::glformat,
GlFormatTraits<T>::gltype
);
}
protected:
bool default_sampling_linear;
std::map<long, std::shared_ptr<GlTexture> > texture_map;
// Protected constructor
TextureCache()
: default_sampling_linear(true)
{
}
};
template<typename T>
void RenderToViewport(Image<T>& image, bool flipx=false, bool flipy=false)
{
// Retrieve texture that is at least as large as image and of appropriate type.
GlTexture& tex = TextureCache::I().GlTex<T>(image.w, image.h);
tex.Upload(image.ptr,0,0, image.w, image.h, GlFormatTraits<T>::glformat, GlFormatTraits<T>::gltype);
tex.RenderToViewport(Viewport(0,0,image.w, image.h), flipx, flipy);
}
// This method may dissapear in the future
inline void RenderToViewport(
Image<unsigned char>& image,
const pangolin::GlPixFormat& fmt,
bool flipx=false, bool flipy=false,
bool linear_sampling = true
) {
pangolin::GlTexture& tex = pangolin::TextureCache::I().GlTex((GLsizei)image.w, (GLsizei)image.h, fmt.scalable_internal_format, fmt.glformat, fmt.gltype);
tex.Bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear_sampling ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear_sampling ? GL_LINEAR : GL_NEAREST);
tex.Upload(image.ptr,0,0, (GLsizei)image.w, (GLsizei)image.h, fmt.glformat, fmt.gltype);
tex.RenderToViewport(pangolin::Viewport(0,0,(GLint)image.w, (GLint)image.h), flipx, flipy);
}
}

View File

@@ -0,0 +1,225 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/gl.h>
namespace pangolin
{
////////////////////////////////////////////////
// Interface
////////////////////////////////////////////////
void MakeTriangleStripIboForVbo(GlBuffer& ibo, int w, int h);
GlBuffer MakeTriangleStripIboForVbo(int w, int h);
void RenderVbo(GlBuffer& vbo, GLenum mode = GL_POINTS);
void RenderVboCbo(GlBuffer& vbo, GlBuffer& cbo, bool draw_color = true, GLenum mode = GL_POINTS);
void RenderVboIbo(GlBuffer& vbo, GlBuffer& ibo, bool draw_mesh = true);
void RenderVboIboCbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& cbo, bool draw_mesh = true, bool draw_color = true);
void RenderVboIboNbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& nbo, bool draw_mesh = true, bool draw_normals = true);
void RenderVboIboCboNbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& cbo, GlBuffer& nbo, bool draw_mesh = true, bool draw_color = true, bool draw_normals = true);
////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////
inline void MakeTriangleStripIboForVbo(GlBuffer& ibo, int w, int h)
{
const int num_elements = w*(h-1)*2;
unsigned int* buffer = new unsigned int[num_elements];
unsigned int* ptr = buffer;
for(int y=0; y < (h-1);)
{
for(int x=0; x<w; ++x) {
(*ptr++) = y*w+x;
(*ptr++) = (y+1)*w+x;
}
++y;
if(y>=(h-1)) break;
for(int x=w-1; x>=0; --x) {
(*ptr++) = y*w+x;
(*ptr++) = (y+1)*w+x;
}
++y;
}
ibo.Reinitialise(GlElementArrayBuffer, num_elements, GL_UNSIGNED_INT, 1, GL_STATIC_DRAW );
ibo.Upload(buffer, sizeof(unsigned int)*num_elements );
delete[] buffer;
}
inline GlBuffer MakeTriangleStripIboForVbo(int w, int h)
{
GlBuffer ibo;
MakeTriangleStripIboForVbo(ibo,w,h);
return ibo;
}
inline void RenderVbo(GlBuffer& vbo, GLenum mode)
{
vbo.Bind();
glVertexPointer(vbo.count_per_element, vbo.datatype, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(mode, 0, vbo.num_elements);
glDisableClientState(GL_VERTEX_ARRAY);
vbo.Unbind();
}
inline void RenderVboCbo(GlBuffer& vbo, GlBuffer& cbo, bool draw_color, GLenum mode )
{
if(draw_color) {
cbo.Bind();
glColorPointer(cbo.count_per_element, cbo.datatype, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
}
RenderVbo(vbo,mode);
if(draw_color) {
glDisableClientState(GL_COLOR_ARRAY);
cbo.Unbind();
}
}
inline void RenderVboIbo(GlBuffer& vbo, GlBuffer& ibo, bool draw_mesh)
{
vbo.Bind();
glVertexPointer(vbo.count_per_element, vbo.datatype, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
if(draw_mesh) {
ibo.Bind();
glDrawElements(GL_TRIANGLE_STRIP,ibo.num_elements, ibo.datatype, 0);
ibo.Unbind();
}else{
glDrawArrays(GL_POINTS, 0, vbo.num_elements);
}
glDisableClientState(GL_VERTEX_ARRAY);
vbo.Unbind();
}
inline void RenderVboIboCbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& cbo, bool draw_mesh, bool draw_color )
{
if(draw_color) {
cbo.Bind();
glColorPointer(cbo.count_per_element, cbo.datatype, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
}
RenderVboIbo(vbo,ibo,draw_mesh);
if(draw_color) {
glDisableClientState(GL_COLOR_ARRAY);
cbo.Unbind();
}
}
inline void RenderVboIboCboNbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& cbo, GlBuffer& nbo, bool draw_mesh, bool draw_color, bool draw_normals)
{
if(draw_color) {
cbo.Bind();
glColorPointer(cbo.count_per_element, cbo.datatype, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
}
if(draw_normals) {
nbo.Bind();
glNormalPointer(nbo.datatype, (GLsizei)(nbo.count_per_element * GlDataTypeBytes(nbo.datatype)),0);
glEnableClientState(GL_NORMAL_ARRAY);
}
vbo.Bind();
glVertexPointer(vbo.count_per_element, vbo.datatype, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
if(draw_mesh) {
ibo.Bind();
glDrawElements(GL_TRIANGLE_STRIP,ibo.num_elements, ibo.datatype, 0);
ibo.Unbind();
}else{
glDrawArrays(GL_POINTS, 0, vbo.num_elements);
}
if(draw_color) {
glDisableClientState(GL_COLOR_ARRAY);
cbo.Unbind();
}
if(draw_normals) {
glDisableClientState(GL_NORMAL_ARRAY);
nbo.Unbind();
}
glDisableClientState(GL_VERTEX_ARRAY);
vbo.Unbind();
}
inline void RenderVboIboNbo(GlBuffer& vbo, GlBuffer& ibo, GlBuffer& nbo, bool draw_mesh, bool draw_normals)
{
vbo.Bind();
glVertexPointer(vbo.count_per_element, vbo.datatype, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
if(draw_normals) {
nbo.Bind();
glNormalPointer(nbo.datatype, (GLsizei)(nbo.count_per_element * GlDataTypeBytes(nbo.datatype)), 0);
glEnableClientState(GL_NORMAL_ARRAY);
}
if(draw_mesh) {
ibo.Bind();
glDrawElements(GL_TRIANGLE_STRIP,ibo.num_elements, ibo.datatype, 0);
ibo.Unbind();
}else{
glDrawArrays(GL_POINTS, 0, vbo.num_elements);
}
if(draw_normals) {
glDisableClientState(GL_NORMAL_ARRAY);
nbo.Unbind();
}
glDisableClientState(GL_VERTEX_ARRAY);
vbo.Unbind();
}
}

View File

@@ -0,0 +1,116 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/display/opengl_render_state.h>
#include <pangolin/handler/handler_enums.h>
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#endif
#ifdef _OSX_
#define PANGO_DFLT_HANDLER3D_ZF (1.0f/50.0f)
#else
#define PANGO_DFLT_HANDLER3D_ZF (1.0f/10.0f)
#endif
namespace pangolin
{
// Forward declarations
struct View;
/// Input Handler base class.
/// Virtual methods which recurse into sub-displays.
struct PANGOLIN_EXPORT Handler
{
virtual ~Handler() {}
virtual void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
virtual void Mouse(View&, MouseButton button, int x, int y, bool pressed, int button_state);
virtual void MouseMotion(View&, int x, int y, int button_state);
virtual void PassiveMouseMotion(View&, int x, int y, int button_state);
virtual void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
};
struct PANGOLIN_EXPORT HandlerScroll : Handler
{
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int button_state);
void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
};
struct PANGOLIN_EXPORT Handler3D : Handler
{
Handler3D(OpenGlRenderState& cam_state, AxisDirection enforce_up=AxisNone, float trans_scale=0.01f, float zoom_fraction= PANGO_DFLT_HANDLER3D_ZF);
virtual bool ValidWinDepth(GLprecision depth);
virtual void PixelUnproject( View& view, GLprecision winx, GLprecision winy, GLprecision winz, GLprecision Pc[3]);
virtual void GetPosNormal(View& view, int x, int y, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision nw[3], GLprecision default_z = 1.0);
void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int button_state);
void MouseMotion(View&, int x, int y, int button_state);
void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
#ifdef USE_EIGEN
// Return selected point in world coordinates
inline Eigen::Vector3d Selected_P_w() const {
return Eigen::Map<const Eigen::Matrix<GLprecision,3,1>>(Pw).cast<double>();
}
#endif
inline int KeyState() const{
return funcKeyState;
}
protected:
OpenGlRenderState* cam_state;
const static int hwin = 8;
AxisDirection enforce_up;
float tf; // translation factor
float zf; // zoom fraction
CameraSpec cameraspec;
GLprecision last_z;
float last_pos[2];
GLprecision rot_center[3];
GLprecision p[3];
GLprecision Pw[3];
GLprecision Pc[3];
GLprecision n[3];
int funcKeyState;
};
static Handler StaticHandler;
static HandlerScroll StaticHandlerScroll;
}

View File

@@ -0,0 +1,94 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
namespace pangolin
{
// Supported Key modifiers for GlobalKeyPressCallback.
// e.g. PANGO_CTRL + 'r', PANGO_SPECIAL + PANGO_KEY_RIGHT, etc.
const int PANGO_SPECIAL = 128;
const int PANGO_CTRL = -96;
const int PANGO_OPTN = 132;
// Ordinary keys
const int PANGO_KEY_TAB = 9;
const int PANGO_KEY_ESCAPE = 27;
// Special Keys (same as GLUT_ defines)
const int PANGO_KEY_F1 = 1;
const int PANGO_KEY_F2 = 2;
const int PANGO_KEY_F3 = 3;
const int PANGO_KEY_F4 = 4;
const int PANGO_KEY_F5 = 5;
const int PANGO_KEY_F6 = 6;
const int PANGO_KEY_F7 = 7;
const int PANGO_KEY_F8 = 8;
const int PANGO_KEY_F9 = 9;
const int PANGO_KEY_F10 = 10;
const int PANGO_KEY_F11 = 11;
const int PANGO_KEY_F12 = 12;
const int PANGO_KEY_LEFT = 100;
const int PANGO_KEY_UP = 101;
const int PANGO_KEY_RIGHT = 102;
const int PANGO_KEY_DOWN = 103;
const int PANGO_KEY_PAGE_UP = 104;
const int PANGO_KEY_PAGE_DOWN = 105;
const int PANGO_KEY_HOME = 106;
const int PANGO_KEY_END = 107;
const int PANGO_KEY_INSERT = 108;
enum MouseButton
{
MouseButtonLeft = 1,
MouseButtonMiddle = 2,
MouseButtonRight = 4,
MouseWheelUp = 8,
MouseWheelDown = 16,
MouseWheelRight = 32,
MouseWheelLeft = 64,
};
enum KeyModifier
{
KeyModifierShift = 1<<16,
KeyModifierCtrl = 1<<17,
KeyModifierAlt = 1<<18,
KeyModifierCmd = 1<<19,
KeyModifierFnc = 1<<20
};
enum InputSpecial
{
InputSpecialScroll,
InputSpecialZoom,
InputSpecialRotate,
InputSpecialTablet
};
}

View File

@@ -0,0 +1,48 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef HANDLER_GLBUFFER_H
#define HANDLER_GLBUFFER_H
#include <pangolin/handler/handler.h>
#include <pangolin/gl/gl.h>
namespace pangolin
{
struct Handler3DFramebuffer : public pangolin::Handler3D
{
Handler3DFramebuffer(GlFramebuffer& fb, pangolin::OpenGlRenderState& cam_state, pangolin::AxisDirection enforce_up=pangolin::AxisNone, float trans_scale=0.01f);
void GetPosNormal(pangolin::View& view, int x, int y, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision /*n*/[3], GLprecision default_z);
protected:
GlFramebuffer& fb;
};
}
#endif // HANDLER_GLBUFFER_H

View File

@@ -0,0 +1,162 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/image/image_utils.h>
#include <pangolin/display/viewport.h>
#include <pangolin/display/view.h>
#include <pangolin/handler/handler.h>
#include <pangolin/plot/range.h>
#include <pangolin/gl/gl.h>
#include <functional>
namespace pangolin
{
class ImageViewHandler : public Handler
{
public:
struct EventData {
EventData(View& v, ImageViewHandler& h) : view(v), handler(h) {}
View& view;
ImageViewHandler& handler;
};
struct OnSelectionEventData : public EventData {
OnSelectionEventData(View& v, ImageViewHandler& h, bool dragging)
: EventData(v,h), dragging(dragging) {}
bool dragging;
};
typedef std::function<void(OnSelectionEventData)> OnSelectionCallbackFn;
// Default constructor: User must call SetDimensions() once image dimensions are known.
// Default range is [0,1] in x and y.
ImageViewHandler();
// View ranges store extremes of image (boundary of pixels)
// in 'discrete' coords, where 0,0 is center of top-left pixel.
ImageViewHandler(size_t w, size_t h);
void SetDimensions(size_t w, size_t h);
void UpdateView();
void glSetViewOrtho();
void glRenderTexture(pangolin::GlTexture& tex);
void glRenderTexture(GLuint tex, GLint width, GLint height);
void glRenderOverlay();
void ScreenToImage(Viewport& v, float xpix, float ypix, float& ximg, float& yimg);
void ImageToScreen(Viewport& v, float ximg, float yimg, float& xpix, float& ypix);
bool UseNN() const;
bool& UseNN();
bool& FlipTextureX();
bool& FlipTextureY();
pangolin::XYRangef& GetViewToRender();
float GetViewScale();
pangolin::XYRangef& GetView();
pangolin::XYRangef& GetDefaultView();
pangolin::XYRangef& GetSelection();
void GetHover(float& x, float& y);
void SetView(const pangolin::XYRangef& range);
void SetViewSmooth(const pangolin::XYRangef& range);
void ScrollView(float x, float y);
void ScrollViewSmooth(float x, float y);
void ScaleView(float x, float y, float cx, float cy);
void ScaleViewSmooth(float x, float y, float cx, float cy);
void ResetView();
///////////////////////////////////////////////////////
/// pangolin::Handler
///////////////////////////////////////////////////////
void Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed) override;
void Mouse(View& view, pangolin::MouseButton button, int x, int y, bool pressed, int button_state) override;
void MouseMotion(View& view, int x, int y, int button_state) override;
void PassiveMouseMotion(View&, int /*x*/, int /*y*/, int /*button_state*/) override;
void Special(View& view, pangolin::InputSpecial inType, float x, float y, float p1, float p2, float /*p3*/, float /*p4*/, int /*button_state*/) override;
///////////////////////////////////////////////////////
/// Callbacks
///////////////////////////////////////////////////////
OnSelectionCallbackFn OnSelectionCallback;
protected:
void FixSelection(XYRangef& sel);
void AdjustScale();
void AdjustTranslation();
static ImageViewHandler* to_link;
static float animate_factor;
ImageViewHandler* linked_view_handler;
pangolin::XYRangef rview_default;
pangolin::XYRangef rview_max;
pangolin::XYRangef rview;
pangolin::XYRangef target;
pangolin::XYRangef selection;
float hover_img[2];
int last_mouse_pos[2];
bool use_nn;
bool flipTextureX;
bool flipTextureY;
};
}

View File

@@ -0,0 +1,45 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
namespace pangolin {
// Hold a reference to an object to be copied
template<typename T>
struct CopyObject {
CopyObject(const T& obj) : obj(obj) { }
const T& obj;
};
// Return copy wrapper for assignment to another object.
template<typename T>
typename pangolin::CopyObject<T> Copy(const T& obj) {
return typename pangolin::CopyObject<T>(obj);
}
}

View File

@@ -0,0 +1,428 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/image/memcpy.h>
#include <cstddef>
#include <functional>
#include <limits>
#include <cstring>
#ifdef PANGO_ENABLE_BOUNDS_CHECKS
# define PANGO_BOUNDS_ASSERT(...) PANGO_ENSURE(##__VA_ARGS__)
#else
# define PANGO_BOUNDS_ASSERT(...) ((void)0)
#endif
// Allow user defined macro to be inserted into Image class.
#ifndef PANGO_EXTENSION_IMAGE
# define PANGO_EXTENSION_IMAGE
#endif
namespace pangolin
{
// Simple image wrapper
template<typename T>
struct Image
{
using PixelType = T;
inline Image()
: pitch(0), ptr(0), w(0), h(0)
{
}
inline Image(T* ptr, size_t w, size_t h, size_t pitch)
: pitch(pitch), ptr(ptr), w(w), h(h)
{
}
PANGO_HOST_DEVICE inline
size_t SizeBytes() const
{
return pitch * h;
}
PANGO_HOST_DEVICE inline
size_t Area() const
{
return w * h;
}
PANGO_HOST_DEVICE inline
bool IsValid() const
{
return ptr != 0;
}
PANGO_HOST_DEVICE inline
bool IsContiguous() const
{
return w*sizeof(T) == pitch;
}
//////////////////////////////////////////////////////
// Iterators
//////////////////////////////////////////////////////
PANGO_HOST_DEVICE inline
T* begin()
{
return ptr;
}
PANGO_HOST_DEVICE inline
T* end()
{
return RowPtr(h-1) + w;
}
PANGO_HOST_DEVICE inline
const T* begin() const
{
return ptr;
}
PANGO_HOST_DEVICE inline
const T* end() const
{
return RowPtr(h-1) + w;
}
PANGO_HOST_DEVICE inline
size_t size() const
{
return w*h;
}
//////////////////////////////////////////////////////
// Image transforms
//////////////////////////////////////////////////////
template<typename UnaryOperation>
PANGO_HOST_DEVICE inline
void Transform(UnaryOperation unary_op)
{
PANGO_ASSERT(IsValid());
for(size_t y=0; y < h; ++y) {
T* el = RowPtr(y);
const T* el_end = el+w;
for( ; el != el_end; ++el) {
*el = unary_op(*el);
}
}
}
PANGO_HOST_DEVICE inline
void Fill(const T& val)
{
Transform( [&](const T&) {return val;} );
}
PANGO_HOST_DEVICE inline
void Replace(const T& oldval, const T& newval)
{
Transform( [&](const T& val) {
return (val == oldval) ? newval : val;
});
}
inline
void Memset(unsigned char v = 0)
{
PANGO_ASSERT(IsValid());
if(IsContiguous()) {
::pangolin::Memset((char*)ptr, v, pitch*h);
}else{
for(size_t y=0; y < h; ++y) {
::pangolin::Memset((char*)RowPtr(y), v, pitch);
}
}
}
inline
void CopyFrom(const Image<T>& img)
{
if(IsValid() && img.IsValid()) {
PANGO_ASSERT(w >= img.w && h >= img.h);
PitchedCopy((char*)ptr,pitch,(char*)img.ptr,img.pitch, std::min(img.w,w)*sizeof(T), std::min(img.h,h) );
}else if( img.IsValid() != IsValid() ){
PANGO_ASSERT(false && "Cannot copy from / to an unasigned image." );
}
}
//////////////////////////////////////////////////////
// Reductions
//////////////////////////////////////////////////////
template<typename BinaryOperation>
PANGO_HOST_DEVICE inline
T Accumulate(const T init, BinaryOperation binary_op)
{
PANGO_ASSERT(IsValid());
T val = init;
for(size_t y=0; y < h; ++y) {
T* el = RowPtr(y);
const T* el_end = el+w;
for(; el != el_end; ++el) {
val = binary_op(val, *el);
}
}
return val;
}
std::pair<T,T> MinMax() const
{
PANGO_ASSERT(IsValid());
std::pair<T,T> minmax(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest());
for(size_t r=0; r < h; ++r) {
const T* ptr = RowPtr(r);
const T* end = ptr + w;
while( ptr != end) {
minmax.first = std::min(*ptr, minmax.first);
minmax.second = std::max(*ptr, minmax.second);
++ptr;
}
}
return minmax;
}
template<typename Tout=T>
Tout Sum() const
{
return Accumulate((T)0, [](const T& lhs, const T& rhs){ return lhs + rhs; });
}
template<typename Tout=T>
Tout Mean() const
{
return Sum<Tout>() / Area();
}
//////////////////////////////////////////////////////
// Direct Pixel Access
//////////////////////////////////////////////////////
PANGO_HOST_DEVICE inline
T* RowPtr(size_t y)
{
return (T*)((unsigned char*)(ptr) + y*pitch);
}
PANGO_HOST_DEVICE inline
const T* RowPtr(size_t y) const
{
return (T*)((unsigned char*)(ptr) + y*pitch);
}
PANGO_HOST_DEVICE inline
T& operator()(size_t x, size_t y)
{
PANGO_BOUNDS_ASSERT( InBounds(x,y) );
return RowPtr(y)[x];
}
PANGO_HOST_DEVICE inline
const T& operator()(size_t x, size_t y) const
{
PANGO_BOUNDS_ASSERT( InBounds(x,y) );
return RowPtr(y)[x];
}
template<typename TVec>
PANGO_HOST_DEVICE inline
T& operator()(const TVec& p)
{
PANGO_BOUNDS_ASSERT( InBounds(p[0],p[1]) );
return RowPtr(p[1])[p[0]];
}
template<typename TVec>
PANGO_HOST_DEVICE inline
const T& operator()(const TVec& p) const
{
PANGO_BOUNDS_ASSERT( InBounds(p[0],p[1]) );
return RowPtr(p[1])[p[0]];
}
PANGO_HOST_DEVICE inline
T& operator[](size_t ix)
{
PANGO_BOUNDS_ASSERT( InImage(ptr+ix) );
return ptr[ix];
}
PANGO_HOST_DEVICE inline
const T& operator[](size_t ix) const
{
PANGO_BOUNDS_ASSERT( InImage(ptr+ix) );
return ptr[ix];
}
//////////////////////////////////////////////////////
// Bounds Checking
//////////////////////////////////////////////////////
PANGO_HOST_DEVICE
bool InImage(const T* ptest) const
{
return ptr <= ptest && ptest < RowPtr(h);
}
PANGO_HOST_DEVICE inline
bool InBounds(int x, int y) const
{
return 0 <= x && x < (int)w && 0 <= y && y < (int)h;
}
PANGO_HOST_DEVICE inline
bool InBounds(float x, float y, float border) const
{
return border <= x && x < (w-border) && border <= y && y < (h-border);
}
template<typename TVec, typename TBorder>
PANGO_HOST_DEVICE inline
bool InBounds( const TVec& p, const TBorder border = (TBorder)0 ) const
{
return border <= p[0] && p[0] < ((int)w - border) && border <= p[1] && p[1] < ((int)h - border);
}
//////////////////////////////////////////////////////
// Obtain slices / subimages
//////////////////////////////////////////////////////
PANGO_HOST_DEVICE inline
const Image<const T> SubImage(size_t x, size_t y, size_t width, size_t height) const
{
PANGO_ASSERT( (x+width) <= w && (y+height) <= h);
return Image<const T>( RowPtr(y)+x, width, height, pitch);
}
PANGO_HOST_DEVICE inline
Image<T> SubImage(size_t x, size_t y, size_t width, size_t height)
{
PANGO_ASSERT( (x+width) <= w && (y+height) <= h);
return Image<T>( RowPtr(y)+x, width, height, pitch);
}
PANGO_HOST_DEVICE inline
const Image<T> Row(int y) const
{
return SubImage(0,y,w,1);
}
PANGO_HOST_DEVICE inline
Image<T> Row(int y)
{
return SubImage(0,y,w,1);
}
PANGO_HOST_DEVICE inline
const Image<T> Col(int x) const
{
return SubImage(x,0,1,h);
}
PANGO_HOST_DEVICE inline
Image<T> Col(int x)
{
return SubImage(x,0,1,h);
}
//////////////////////////////////////////////////////
// Data mangling
//////////////////////////////////////////////////////
template<typename TRecast>
PANGO_HOST_DEVICE inline
Image<TRecast> Reinterpret() const
{
PANGO_ASSERT(sizeof(TRecast) == sizeof(T), "sizeof(TRecast) must match sizeof(T): % != %", sizeof(TRecast), sizeof(T) );
return UnsafeReinterpret<TRecast>();
}
template<typename TRecast>
PANGO_HOST_DEVICE inline
Image<TRecast> UnsafeReinterpret() const
{
return Image<TRecast>((TRecast*)ptr,w,h,pitch);
}
//////////////////////////////////////////////////////
// Deprecated methods
//////////////////////////////////////////////////////
// PANGOLIN_DEPRECATED inline
Image(size_t w, size_t h, size_t pitch, T* ptr)
: pitch(pitch), ptr(ptr), w(w), h(h)
{
}
// Use RAII/move aware pangolin::ManagedImage instead
// PANGOLIN_DEPRECATED inline
void Dealloc()
{
if(ptr) {
::operator delete(ptr);
ptr = nullptr;
}
}
// Use RAII/move aware pangolin::ManagedImage instead
// PANGOLIN_DEPRECATED inline
void Alloc(size_t w, size_t h, size_t pitch)
{
Dealloc();
this->w = w;
this->h = h;
this->pitch = pitch;
this->ptr = (T*)::operator new(h*pitch);
}
//////////////////////////////////////////////////////
// Data members
//////////////////////////////////////////////////////
size_t pitch;
T* ptr;
size_t w;
size_t h;
PANGO_EXTENSION_IMAGE
};
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include <pangolin/image/managed_image.h>
#include <pangolin/utils/compontent_cast.h>
namespace pangolin
{
template <typename To, typename T>
void ImageConvert(Image<To>& dst, const Image<T>& src, To scale = 1.0)
{
for(unsigned int y = 0; y < dst.h; ++y)
{
const T* prs = src.RowPtr(y);
To* prd = dst.RowPtr(y);
for(unsigned int x = 0; x < dst.w; ++x)
{
*(prd++) = scale * ComponentCast<To, T>::cast(*(prs++));
}
}
}
template <typename To, typename T>
ManagedImage<To> ImageConvert(const Image<T>& src, To scale = 1.0)
{
ManagedImage<To> dst(src.w, src.h);
ImageConvert<To,T>(dst,src,scale);
return dst;
}
}

View File

@@ -0,0 +1,65 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/image/typed_image.h>
#include <pangolin/utils/file_extension.h>
namespace pangolin {
PANGOLIN_EXPORT
TypedImage LoadImage(std::istream& in, ImageFileType file_type);
PANGOLIN_EXPORT
TypedImage LoadImage(const std::string& filename, ImageFileType file_type);
PANGOLIN_EXPORT
TypedImage LoadImage(const std::string& filename);
PANGOLIN_EXPORT
TypedImage LoadImage(const std::string& filename, const PixelFormat& raw_fmt, size_t raw_width, size_t raw_height, size_t raw_pitch);
/// Quality \in [0..100] for lossy formats
PANGOLIN_EXPORT
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, ImageFileType file_type, bool top_line_first = true, float quality = 100.0f);
/// Quality \in [0..100] for lossy formats
PANGOLIN_EXPORT
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, ImageFileType file_type, bool top_line_first = true, float quality = 100.0f);
/// Quality \in [0..100] for lossy formats
PANGOLIN_EXPORT
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first = true, float quality = 100.0f);
/// Quality \in [0..100] for lossy formats
PANGOLIN_EXPORT
void SaveImage(const TypedImage& image, const std::string& filename, bool top_line_first = true, float quality = 100.0f);
}

View File

@@ -0,0 +1,185 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <limits>
#include <utility>
#include <pangolin/image/image.h>
#include <pangolin/plot/range.h>
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glpixformat.h>
namespace pangolin
{
namespace internal
{
template <typename T>
std::pair<float, float> GetMinMax(const Image<T>& img, size_t channels)
{
const size_t max_channels = 3;
const size_t colour_channels = std::min(channels, max_channels);
std::pair<float, float> chan_mm[max_channels];
for(size_t c = 0; c < max_channels; ++c)
{
chan_mm[c].first = +std::numeric_limits<float>::max();
chan_mm[c].second = -std::numeric_limits<float>::max();
}
for(size_t y = 0; y < img.h; ++y)
{
T* pix = (T*)((char*)img.ptr + y * img.pitch);
for(size_t x = 0; x < img.w; ++x)
{
for(size_t c = 0; c < colour_channels; ++c)
{
if(pix[c] < chan_mm[c].first)
chan_mm[c].first = (float)pix[c];
if(pix[c] > chan_mm[c].second)
chan_mm[c].second = (float)pix[c];
}
pix += channels;
}
}
// Find min / max of all channels, ignoring 4th alpha channel
std::pair<float, float> mm = chan_mm[0];
for(size_t c = 1; c < colour_channels; ++c)
{
mm.first = std::min(mm.first, chan_mm[c].first);
mm.second = std::max(mm.second, chan_mm[c].second);
}
return mm;
}
template<typename T>
pangolin::Image<T> GetImageRoi( pangolin::Image<T> img, size_t channels, const pangolin::XYRangei& roi )
{
return pangolin::Image<T>(
img.RowPtr(std::min(roi.y.min,roi.y.max)) + channels*std::min(roi.x.min,roi.x.max),
roi.x.AbsSize(), roi.y.AbsSize(),
img.pitch
);
}
template<typename T>
std::pair<float,float> GetOffsetScale(const pangolin::Image<T>& img, size_t channels, float type_max, float format_max)
{
// Find min / max of all channels, ignoring 4th alpha channel
const std::pair<float,float> mm = internal::GetMinMax<T>(img,channels);
const float type_scale = format_max / type_max;
const float offset = -type_scale* mm.first;
const float scale = type_max / (mm.second - mm.first);
return std::pair<float,float>(offset, scale);
}
template<typename T>
float GetScaleOnly(const pangolin::Image<T>& img, size_t channels, float type_max, float /*format_max*/)
{
// Find min / max of all channels, ignoring 4th alpha channel
const std::pair<float,float> mm = internal::GetMinMax<T>(img,channels);
const float scale = type_max / mm.second;
return scale;
}
} // internal
inline std::pair<float, float> GetMinMax(
const Image<unsigned char>& img,
XYRangei iroi, const GlPixFormat& glfmt
) {
using namespace internal;
iroi.Clamp(0, (int)img.w - 1, 0, (int)img.h - 1);
const size_t num_channels = pangolin::GlFormatChannels(glfmt.glformat);
if(glfmt.gltype == GL_UNSIGNED_BYTE) {
return GetMinMax(GetImageRoi(img.template UnsafeReinterpret<unsigned char>(), num_channels, iroi), num_channels);
} else if(glfmt.gltype == GL_UNSIGNED_SHORT) {
return GetMinMax(GetImageRoi(img.template UnsafeReinterpret<unsigned short>(), num_channels, iroi), num_channels);
} else if(glfmt.gltype == GL_FLOAT) {
return GetMinMax(GetImageRoi(img.template UnsafeReinterpret<float>(), num_channels, iroi), num_channels);
} else if(glfmt.gltype == GL_DOUBLE) {
return GetMinMax(GetImageRoi(img.template UnsafeReinterpret<double>(), num_channels, iroi), num_channels);
} else {
return std::pair<float, float>(std::numeric_limits<float>::max(), std::numeric_limits<float>::lowest());
}
}
inline std::pair<float,float> GetOffsetScale(
const pangolin::Image<unsigned char>& img,
pangolin::XYRangei iroi, const pangolin::GlPixFormat& glfmt
) {
using namespace internal;
iroi.Clamp(0, (int)img.w-1, 0, (int)img.h-1 );
const size_t num_channels = pangolin::GlFormatChannels(glfmt.glformat);
if(glfmt.gltype == GL_UNSIGNED_BYTE) {
return GetOffsetScale(GetImageRoi(img.template UnsafeReinterpret<unsigned char>(), num_channels, iroi), num_channels, 255.0f, 1.0f);
}else if(glfmt.gltype == GL_UNSIGNED_SHORT) {
return GetOffsetScale(GetImageRoi(img.template UnsafeReinterpret<unsigned short>(), num_channels, iroi), num_channels, 65535.0f, 1.0f);
}else if(glfmt.gltype == GL_FLOAT) {
return GetOffsetScale(GetImageRoi(img.template UnsafeReinterpret<float>(), num_channels, iroi), num_channels, 1.0f, 1.0f);
}else if(glfmt.gltype == GL_DOUBLE) {
return GetOffsetScale(GetImageRoi(img.template UnsafeReinterpret<double>(), num_channels, iroi), num_channels, 1.0f, 1.0f);
}else{
return std::pair<float,float>(0.0f, 1.0f);
}
}
inline float GetScaleOnly(
const pangolin::Image<unsigned char>& img,
pangolin::XYRangei iroi, const pangolin::GlPixFormat& glfmt
) {
using namespace internal;
iroi.Clamp(0, (int)img.w-1, 0, (int)img.h-1 );
const size_t num_channels = pangolin::GlFormatChannels(glfmt.glformat);
if(glfmt.gltype == GL_UNSIGNED_BYTE) {
return GetScaleOnly(GetImageRoi(img.template UnsafeReinterpret<unsigned char>(), num_channels, iroi), num_channels, 255.0f, 1.0f);
}else if(glfmt.gltype == GL_UNSIGNED_SHORT) {
return GetScaleOnly(GetImageRoi(img.template UnsafeReinterpret<unsigned short>(), num_channels, iroi), num_channels, 65535.0f, 1.0f);
}else if(glfmt.gltype == GL_FLOAT) {
return GetScaleOnly(GetImageRoi(img.template UnsafeReinterpret<float>(), num_channels, iroi), num_channels, 1.0f, 1.0f);
}else if(glfmt.gltype == GL_DOUBLE) {
return GetScaleOnly(GetImageRoi(img.template UnsafeReinterpret<double>(), num_channels, iroi), num_channels, 1.0f, 1.0f);
}else{
return 1.0f;
}
}
}

View File

@@ -0,0 +1,175 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/image/image.h>
#include <pangolin/image/copy.h>
namespace pangolin {
template<class T> using DefaultImageAllocator = std::allocator<T>;
// Image that manages it's own memory, storing a strong pointer to it's memory
template<typename T, class Allocator = DefaultImageAllocator<T> >
class ManagedImage : public Image<T>
{
public:
// Destructor
inline
~ManagedImage()
{
Deallocate();
}
// Null image
inline
ManagedImage()
{
}
// Row image
inline
ManagedImage(size_t w)
: Image<T>(
Allocator().allocate(w),
w, 1, w*sizeof(T)
)
{
}
inline
ManagedImage(size_t w, size_t h)
: Image<T>(
Allocator().allocate(w*h),
w, h, w*sizeof(T)
)
{
}
inline
ManagedImage(size_t w, size_t h, size_t pitch_bytes)
: Image<T>(
Allocator().allocate( (h*pitch_bytes) / sizeof(T) + 1),
w, h, pitch_bytes
)
{
}
// Not copy constructable
inline
ManagedImage( const ManagedImage<T>& other ) = delete;
// Move constructor
inline
ManagedImage(ManagedImage<T,Allocator>&& img)
{
*this = std::move(img);
}
// Move asignment
inline
void operator=(ManagedImage<T,Allocator>&& img)
{
Deallocate();
Image<T>::pitch = img.pitch;
Image<T>::ptr = img.ptr;
Image<T>::w = img.w;
Image<T>::h = img.h;
img.ptr = nullptr;
}
// Explicit copy constructor
template<typename TOther>
ManagedImage( const CopyObject<TOther>& other )
{
CopyFrom(other.obj);
}
// Explicit copy assignment
template<typename TOther>
void operator=(const CopyObject<TOther>& other)
{
CopyFrom(other.obj);
}
inline
void Swap(ManagedImage<T>& img)
{
std::swap(img.pitch, Image<T>::pitch);
std::swap(img.ptr, Image<T>::ptr);
std::swap(img.w, Image<T>::w);
std::swap(img.h, Image<T>::h);
}
inline
void CopyFrom(const Image<T>& img)
{
if(!Image<T>::IsValid() || Image<T>::w != img.w || Image<T>::h != img.h) {
Reinitialise(img.w,img.h);
}
Image<T>::CopyFrom(img);
}
inline
void Reinitialise(size_t w, size_t h)
{
if(!Image<T>::ptr || Image<T>::w != w || Image<T>::h != h) {
*this = ManagedImage<T,Allocator>(w,h);
}
}
inline
void Reinitialise(size_t w, size_t h, size_t pitch)
{
if(!Image<T>::ptr || Image<T>::w != w || Image<T>::h != h || Image<T>::pitch != pitch) {
*this = ManagedImage<T,Allocator>(w,h,pitch);
}
}
inline void Deallocate()
{
if (Image<T>::ptr) {
Allocator().deallocate(Image<T>::ptr, (Image<T>::h * Image<T>::pitch) / sizeof(T) );
Image<T>::ptr = nullptr;
}
}
// Move asignment
template<typename TOther, typename AllocOther> inline
void OwnAndReinterpret(ManagedImage<TOther,AllocOther>&& img)
{
Deallocate();
Image<T>::pitch = img.pitch;
Image<T>::ptr = (T*)img.ptr;
Image<T>::w = img.w;
Image<T>::h = img.h;
img.ptr = nullptr;
}
};
}

View File

@@ -0,0 +1,110 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <cstring>
#ifdef HAVE_CUDA
# include <cuda_runtime.h>
#endif
namespace pangolin {
template<typename T>
PANGO_HOST_DEVICE inline
bool IsDevicePtr(T* ptr)
{
#ifdef HAVE_CUDA
cudaPointerAttributes attributes;
cudaError_t res = cudaPointerGetAttributes(&attributes,ptr);
//Flushing the error flag for future CUDA error checks
if(res != cudaSuccess)
{
cudaGetLastError();
return false;
}
return attributes.memoryType == cudaMemoryTypeDevice;
#else
PANGOLIN_UNUSED(ptr);
return false;
#endif
}
PANGO_HOST_DEVICE inline
void MemCopy(void *dst, const void *src, size_t size_bytes)
{
#ifdef HAVE_CUDA
cudaMemcpy(dst,src, size_bytes, cudaMemcpyDefault);
#else
std::memcpy(dst, src, size_bytes);
#endif
}
inline
void PitchedCopy(char* dst, unsigned int dst_pitch_bytes, const char* src, unsigned int src_pitch_bytes, unsigned int width_bytes, unsigned int height)
{
#ifdef HAVE_CUDA
cudaMemcpy2D(dst, dst_pitch_bytes, src, src_pitch_bytes, width_bytes, height, cudaMemcpyDefault);
#else
if(dst_pitch_bytes == width_bytes && src_pitch_bytes == width_bytes ) {
std::memcpy(dst, src, height * width_bytes);
}else{
for(unsigned int row=0; row < height; ++row) {
std::memcpy(dst, src, width_bytes);
dst += dst_pitch_bytes;
src += src_pitch_bytes;
}
}
#endif
}
PANGO_HOST_DEVICE inline
void Memset(char* ptr, unsigned char v, size_t size_bytes)
{
#ifdef __CUDA_ARCH__
// Called in kernel
char* end = ptr + size_bytes;
for(char* p=ptr; p != end; ++p) *p = v;
#else
# ifdef HAVE_CUDA
if(IsDevicePtr(ptr))
{
cudaMemset(ptr, v, size_bytes);
}else
# endif // HAVE_CUDA
{
std::memset(ptr, v, size_bytes);
}
#endif // __CUDA_ARCH__
}
}

View File

@@ -0,0 +1,66 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011-2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <string>
namespace pangolin
{
struct PANGOLIN_EXPORT PixelFormat
{
// Previously, VideoInterface::PixFormat returned a string.
// For compatibility, make this string convertable
inline operator std::string() const { return format; }
std::string format;
unsigned int channels;
unsigned int channel_bits[4]; //Of the data type
unsigned int bpp; //Of the data type
unsigned int channel_bit_depth; //Of the data
bool planar;
};
//! Return Pixel Format properties given string specification in
//! FFMPEG notation.
PANGOLIN_EXPORT
PixelFormat PixelFormatFromString(const std::string& format);
////////////////////////////////////////////////////////////////////
/// Deprecated aliases for above
PANGOLIN_DEPRECATED
typedef PixelFormat VideoPixelFormat;
PANGOLIN_DEPRECATED
inline PixelFormat VideoFormatFromString(const std::string& format) {
return PixelFormatFromString(format);
}
}

View File

@@ -0,0 +1,91 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2013 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/image/managed_image.h>
#include <pangolin/image/pixel_format.h>
namespace pangolin {
struct TypedImage : public ManagedImage<unsigned char>
{
typedef ManagedImage<unsigned char> Base;
inline TypedImage()
: Base()
{
}
inline TypedImage(size_t w, size_t h, const PixelFormat& fmt)
: Base(w,h,w*fmt.bpp/8), fmt(fmt)
{
}
inline TypedImage(size_t w, size_t h, const PixelFormat& fmt, size_t pitch )
: Base(w,h, pitch), fmt(fmt)
{
}
inline
void Reinitialise(size_t w, size_t h, const PixelFormat& fmt)
{
Base::Reinitialise(w, h, w*fmt.bpp/8);
this->fmt = fmt;
}
inline
void Reinitialise(size_t w, size_t h, const PixelFormat& fmt, size_t pitch)
{
Base::Reinitialise(w, h, pitch);
this->fmt = fmt;
}
// Not copy constructable
inline
TypedImage( const TypedImage& other ) = delete;
// Move constructor
inline
TypedImage(TypedImage&& img)
{
*this = std::move(img);
}
// Move asignment
inline
void operator=(TypedImage&& img)
{
fmt = img.fmt;
Base::operator =( std::move(img));
}
PixelFormat fmt;
};
}

View File

@@ -0,0 +1,36 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <UIKit/UIKit.h>
#import "PangolinUIView.h"
@interface PangolinAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

View File

@@ -0,0 +1,22 @@
//
// GlTestViewController.h
// gltest
//
// Created by Steven Lovegrove on 30/01/2014.
// Copyright (c) 2014 Steven Lovegrove. All rights reserved.
//
#import <UIKit/UIKit.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
@interface PangolinUIView : UIView {
CAEAGLLayer* _eaglLayer;
EAGLContext* _context;
GLuint _colorRenderBuffer;
GLuint _depthRenderBuffer;
}
@end

View File

@@ -0,0 +1,70 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <mutex>
#include <pangolin/log/packetstream.h>
#include <pangolin/log/packetstream_source.h>
namespace pangolin {
// Encapsulate serialized reading of Packet from stream.
struct Packet
{
Packet(PacketStream& s, std::unique_lock<std::recursive_mutex>&& mutex, std::vector<PacketStreamSource>& srcs);
Packet(const Packet&) = delete;
Packet(Packet&& o);
~Packet();
size_t BytesRead() const;
int BytesRemaining() const;
PacketStream& Stream()
{
return _stream;
}
PacketStreamSourceId src;
int64_t time;
size_t size;
size_t sequence_num;
picojson::value meta;
std::streampos frame_streampos;
private:
void ParsePacketHeader(PacketStream& s, std::vector<PacketStreamSource>& srcs);
void ReadRemaining();
PacketStream& _stream;
std::unique_lock<std::recursive_mutex> lock;
std::streampos data_streampos;
size_t _data_len;
};
}

View File

@@ -0,0 +1,111 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <fstream>
#include <pangolin/platform.h>
#include <pangolin/log/packetstream_tags.h>
#include <pangolin/utils/file_utils.h>
namespace pangolin
{
class PacketStream: public std::ifstream
{
public:
PacketStream()
: _is_pipe(false)
{
cclear();
}
PacketStream(const std::string& filename)
: Base(filename.c_str(), std::ios::in | std::ios::binary),
_is_pipe(IsPipe(filename))
{
cclear();
}
bool seekable() const
{
return is_open() && !_is_pipe;
}
void open(const std::string& filename)
{
close();
_is_pipe = IsPipe(filename);
Base::open(filename.c_str(), std::ios::in | std::ios::binary);
}
void close()
{
cclear();
if (Base::is_open()) Base::close();
}
void seekg(std::streampos target);
void seekg(std::streamoff off, std::ios_base::seekdir way);
std::streampos tellg();
size_t read(char* target, size_t len);
char get();
size_t skip(size_t len);
size_t readUINT();
int64_t readTimestamp();
pangoTagType peekTag();
pangoTagType readTag();
pangoTagType readTag(pangoTagType);
pangoTagType syncToTag();
private:
using Base = std::ifstream;
bool _is_pipe;
pangoTagType _tag;
// Amount of frame data left to read. Tracks our position within a data block.
void cclear() {
_tag = 0;
}
};
}

View File

@@ -0,0 +1,120 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <fstream>
#include <mutex>
#include <thread>
#include <pangolin/log/packet.h>
#include <pangolin/log/sync_time.h>
#include <pangolin/utils/file_utils.h>
#include <pangolin/utils/timer.h>
namespace pangolin
{
class PANGOLIN_EXPORT PacketStreamReader
{
public:
PacketStreamReader();
PacketStreamReader(const std::string& filename);
~PacketStreamReader();
void Open(const std::string& filename);
void Close();
const std::vector<PacketStreamSource>&
Sources() const
{
return _sources;
}
// Grab Next available frame packetstream
Packet NextFrame();
// Grab Next available frame in packetstream from src, discarding other frames.
Packet NextFrame(PacketStreamSourceId src);
bool Good() const
{
return _stream.good();
}
// Jumps to a particular packet.
size_t Seek(PacketStreamSourceId src, size_t framenum);
// Jumps to the first packet with time >= time
size_t Seek(PacketStreamSourceId src, SyncTime::TimePoint time);
void FixFileIndex();
private:
bool GoodToRead();
bool SetupIndex();
void ParseHeader();
void ParseNewSource();
bool ParseIndex();
void RebuildIndex();
void AppendIndex();
std::streampos ParseFooter();
void SkipSync();
void ReSync() {
_stream.syncToTag();
}
std::string _filename;
std::vector<PacketStreamSource> _sources;
SyncTime::TimePoint packet_stream_start;
PacketStream _stream;
std::recursive_mutex _mutex;
bool _is_pipe;
int _pipe_fd;
};
}

View File

@@ -0,0 +1,63 @@
#pragma once
#include <iostream>
#include <pangolin/platform.h>
#include <pangolin/utils/picojson.h>
namespace pangolin {
using PacketStreamSourceId = size_t;
struct PANGOLIN_EXPORT PacketStreamSource
{
struct PacketInfo
{
std::streampos pos;
int64_t capture_time;
};
PacketStreamSource()
: id(static_cast<PacketStreamSourceId>(-1)),
version(0),
data_alignment_bytes(1),
data_size_bytes(0),
next_packet_id(0)
{
}
std::streampos FindSeekLocation(size_t packet_id)
{
if(packet_id < index.size()) {
return index[packet_id].pos;
}else{
return std::streampos(-1);
}
}
int64_t NextPacketTime() const
{
if(next_packet_id < index.size()) {
return index[next_packet_id].capture_time;
}else{
return 0;
}
}
std::string driver;
size_t id;
std::string uri;
picojson::value info;
int64_t version;
int64_t data_alignment_bytes;
std::string data_definitions;
int64_t data_size_bytes;
// Index keyed by packet_id
std::vector<PacketInfo> index;
// Based on current position in stream
size_t next_packet_id;
};
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include <string>
namespace pangolin {
using pangoTagType = uint32_t;
const static std::string PANGO_MAGIC = "PANGO";
const static std::string pss_src_driver = "driver";
const static std::string pss_src_id = "id";
const static std::string pss_src_info = "info";
const static std::string pss_src_uri = "uri";
const static std::string pss_src_packet = "packet";
const static std::string pss_src_version = "version";
const static std::string pss_pkt_alignment_bytes = "alignment_bytes";
const static std::string pss_pkt_definitions = "definitions";
const static std::string pss_pkt_size_bytes = "size_bytes";
const static std::string pss_pkt_format_written = "format_written";
const unsigned int TAG_LENGTH = 3;
#define PANGO_TAG(a,b,c) ( (c<<16) | (b<<8) | a)
const uint32_t TAG_PANGO_HDR = PANGO_TAG('L', 'I', 'N');
const uint32_t TAG_PANGO_MAGIC = PANGO_TAG('P', 'A', 'N');
const uint32_t TAG_PANGO_SYNC = PANGO_TAG('S', 'Y', 'N');
const uint32_t TAG_PANGO_STATS = PANGO_TAG('S', 'T', 'A');
const uint32_t TAG_PANGO_FOOTER = PANGO_TAG('F', 'T', 'R');
const uint32_t TAG_ADD_SOURCE = PANGO_TAG('S', 'R', 'C');
const uint32_t TAG_SRC_JSON = PANGO_TAG('J', 'S', 'N');
const uint32_t TAG_SRC_PACKET = PANGO_TAG('P', 'K', 'T');
const uint32_t TAG_END = PANGO_TAG('E', 'N', 'D');
#undef PANGO_TAG
inline std::string tagName(int v)
{
char b[4];
b[0] = v&0xff;
b[1] = (v>>8)&0xff;
b[2] = (v>>16)&0xff;
b[3] = 0x00;
return std::string(b);
}
}

View File

@@ -0,0 +1,173 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <ostream>
#include <pangolin/log/packetstream.h>
#include <pangolin/log/packetstream_source.h>
#include <pangolin/utils/file_utils.h>
#include <pangolin/utils/threadedfilebuf.h>
namespace pangolin
{
class PANGOLIN_EXPORT PacketStreamWriter
{
public:
PacketStreamWriter()
: _stream(&_buffer), _indexable(false), _open(false), _bytes_written(0)
{
_stream.exceptions(std::ostream::badbit);
}
PacketStreamWriter(const std::string& filename, size_t buffer_size = 100*1024*1024)
: _buffer(pangolin::PathExpand(filename), buffer_size), _stream(&_buffer),
_indexable(!IsPipe(filename)), _open(_stream.good()), _bytes_written(0)
{
_stream.exceptions(std::ostream::badbit);
WriteHeader();
}
~PacketStreamWriter() {
Close();
}
void Open(const std::string& filename, size_t buffer_size = 100 * 1024 * 1024)
{
Close();
_buffer.open(filename, buffer_size);
_open = _stream.good();
_bytes_written = 0;
_indexable = !IsPipe(filename);
WriteHeader();
}
void Close()
{
if (_open)
{
if (_indexable) {
WriteEnd();
}
_buffer.close();
_open = false;
}
}
// Does not write footer or index.
void ForceClose()
{
if (_open)
{
_buffer.force_close();
Close();
}
}
// Writes to the stream immediately upon add. Return source id # and writes
// source id # to argument struct
PacketStreamSourceId AddSource(PacketStreamSource& source);
// If constructor is called inline
PacketStreamSourceId AddSource(const PacketStreamSource& source);
void WriteSourcePacket(
PacketStreamSourceId src, const char* source,const int64_t receive_time_us,
size_t sourcelen, const picojson::value& meta = picojson::value()
);
// For stream read/write synchronization. Note that this is NOT the same as
// time synchronization on playback of iPacketStreams.
void WriteSync();
// Writes the end of the stream data, including the index. Does NOT close
// the underlying ostream.
void WriteEnd();
const std::vector<PacketStreamSource>& Sources() const {
return _sources;
}
bool IsOpen() const {
return _open;
}
private:
void WriteHeader();
void Write(const PacketStreamSource&);
void WriteMeta(PacketStreamSourceId src, const picojson::value& data);
threadedfilebuf _buffer;
std::ostream _stream;
bool _indexable, _open;
std::vector<PacketStreamSource> _sources;
size_t _bytes_written;
std::recursive_mutex _lock;
};
inline void writeCompressedUnsignedInt(std::ostream& writer, size_t n)
{
while (n >= 0x80)
{
writer.put(0x80 | (n & 0x7F));
n >>= 7;
}
writer.put(static_cast<unsigned char>(n));
}
inline void writeTimestamp(std::ostream& writer, int64_t time_us)
{
writer.write(reinterpret_cast<const char*>(&time_us), sizeof(decltype(time_us)));
}
inline void writeTag(std::ostream& writer, const pangoTagType tag)
{
writer.write(reinterpret_cast<const char*>(&tag), TAG_LENGTH);
}
inline picojson::value SourceStats(const std::vector<PacketStreamSource>& srcs)
{
picojson::value stat;
stat["num_sources"] = srcs.size();
stat["src_packet_index"] = picojson::array();
stat["src_packet_times"] = picojson::array();
for(auto& src : srcs) {
picojson::array pkt_index, pkt_times;
for (const PacketStreamSource::PacketInfo& frame : src.index) {
pkt_index.emplace_back(frame.pos);
pkt_times.emplace_back(frame.capture_time);
}
stat["src_packet_index"].push_back(std::move(pkt_index));
stat["src_packet_times"].push_back(std::move(pkt_times));
}
return stat;
}
}

View File

@@ -0,0 +1,48 @@
#pragma once
#include <memory>
#include <vector>
#include <pangolin/log/packetstream_reader.h>
#include <pangolin/utils/file_utils.h>
#include <pangolin/utils/registration.h>
namespace pangolin {
class Params;
class PlaybackSession
{
public:
// Singleton Instance
static std::shared_ptr<PlaybackSession> Default();
// Return thread-safe, shared instance of PacketStreamReader, providing
// serialised read for PacketStreamReader
std::shared_ptr<PacketStreamReader> Open(const std::string& filename)
{
const std::string path = SanitizePath(PathExpand(filename));
auto i = readers.find(path);
if(i == readers.end()) {
auto psr = std::make_shared<PacketStreamReader>(path);
readers[path] = psr;
return psr;
}else{
return i->second;
}
}
SyncTime& Time()
{
return time;
}
static std::shared_ptr<PlaybackSession> ChooseFromParams(const Params& params);
private:
std::map<std::string,std::shared_ptr<PacketStreamReader>> readers;
SyncTime time;
};
}

View File

@@ -0,0 +1,230 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <pangolin/utils/signal_slot.h>
#include <pangolin/utils/timer.h>
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <queue>
namespace pangolin
{
// Lightweight timestamp class to allow synchronized playback from the same (or a different) stream.
// All playback functions called with the same SyncTime will be time-synchronized, and will remain synchronized on seek() if the SyncTime is passed in when seeking.
// Playback with multiple SyncTimes (on the same or different streams) should also be synced, even in different processes or systems (underlying clock sync is not required).
// However, playback with multiple SyncTimes will break on seek().
class PANGOLIN_EXPORT SyncTime
{
public:
using Clock = baseclock;
using Duration = Clock::duration;
using TimePoint = Clock::time_point;
struct SeekInterruption: std::runtime_error
{
SeekInterruption() : std::runtime_error("Time queue invalidated by seek"){}
};
SyncTime(Duration virtual_clock_offset = std::chrono::milliseconds(0))
: seeking(false)
{
SetOffset(virtual_clock_offset);
}
// No copy constructor
SyncTime(const SyncTime&) = delete;
void SetOffset(Duration virtual_clock_offset)
{
virtual_offset = virtual_clock_offset;
}
void SetClock(TimePoint virtual_now)
{
virtual_offset = virtual_now - Clock::now();
}
TimePoint TimeNow() const
{
return Clock::now() + virtual_offset;
}
TimePoint ToVirtual(TimePoint real) const
{
return real + virtual_offset;
}
TimePoint ToReal(TimePoint virt) const
{
return virt - virtual_offset;
}
void WaitUntil(TimePoint virtual_time) const
{
std::this_thread::sleep_until( ToReal(virtual_time) );
}
int64_t QueueEvent(int64_t new_event_time_us)
{
return WaitDequeueAndQueueEvent(0, new_event_time_us);
}
void DequeueEvent(int64_t event_time_us)
{
std::unique_lock<std::mutex> l(time_mutex);
auto i = std::find(time_queue_us.begin(), time_queue_us.end(), event_time_us);
PANGO_ENSURE(i != time_queue_us.end());
time_queue_us.erase(i);
queue_changed.notify_all();
}
int64_t WaitDequeueAndQueueEvent(int64_t event_time_us, int64_t new_event_time_us =0 )
{
std::unique_lock<std::mutex> l(time_mutex);
if(event_time_us) {
PANGO_ENSURE(time_queue_us.size());
// Wait until we're top the priority-queue
queue_changed.wait(l, [&](){
if(seeking) {
// Time queue will be invalidated on seek.
// Unblock without action
throw SeekInterruption();
}
return time_queue_us.back() == event_time_us;
});
// Dequeue
time_queue_us.pop_back();
}
if(new_event_time_us) {
// Add the new event whilst we still hold the lock, so that our
// event can't be missed
insert_sorted(time_queue_us, new_event_time_us, std::greater<int64_t>());
if(time_queue_us.back() == new_event_time_us) {
// Return to avoid yielding when we're next.
return new_event_time_us;
}
}
// Only yield if another device is next
queue_changed.notify_all();
return new_event_time_us;
}
void NotifyAll()
{
queue_changed.notify_all();
}
std::mutex& TimeMutex()
{
return time_mutex;
}
void Stop()
{
seeking = true;
OnTimeStop();
queue_changed.notify_all();
}
void Start()
{
OnTimeStart();
seeking=false;
}
void Seek(TimePoint t)
{
Stop();
OnSeek(t);
Start();
}
Signal<> OnTimeStart;
Signal<> OnTimeStop;
Signal<TimePoint> OnSeek;
private:
template< typename T, typename Pred >
static typename std::vector<T>::iterator
insert_sorted( std::vector<T> & vec, T const& item, Pred pred )
{
return vec.insert (
std::upper_bound( vec.begin(), vec.end(), item, pred ), item
);
}
std::vector<int64_t> time_queue_us;
Duration virtual_offset;
std::mutex time_mutex;
std::condition_variable queue_changed;
bool seeking;
};
struct SyncTimeEventPromise
{
SyncTimeEventPromise(SyncTime& sync, int64_t time_us = 0)
: sync(sync), time_us(time_us)
{
sync.QueueEvent(time_us);
}
~SyncTimeEventPromise()
{
Cancel();
}
void Cancel()
{
if(time_us) {
sync.DequeueEvent(time_us);
time_us = 0;
}
}
void WaitAndRenew(int64_t new_time_us)
{
time_us = sync.WaitDequeueAndQueueEvent(time_us, new_time_us);
}
private:
SyncTime& sync;
int64_t time_us;
};
}

View File

@@ -0,0 +1,64 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#ifdef BUILD_PANGOLIN_GUI
#include <pangolin/gl/gl.h>
#include <pangolin/gl/gldraw.h>
#include <pangolin/gl/glvbo.h>
#include <pangolin/gl/glstate.h>
#include <pangolin/gl/colour.h>
#include <pangolin/display/display.h>
#include <pangolin/display/view.h>
#ifdef _ANDROID_
#include <pangolin/display/device/display_android.h>
#endif
#if !defined(HAVE_GLES) || defined(HAVE_GLES_2)
#include <pangolin/plot/plotter.h>
#endif
#endif // BUILD_PANGOLIN_GUI
#ifdef BUILD_PANGOLIN_VARS
#include <pangolin/var/varextra.h>
#ifdef BUILD_PANGOLIN_GUI
#include <pangolin/display/widgets/widgets.h>
#endif // BUILD_PANGOLIN_GUI
#endif // BUILD_PANGOLIN_VARS
#ifdef BUILD_PANGOLIN_VIDEO
#include <pangolin/video/video.h>
#include <pangolin/video/video_input.h>
#include <pangolin/video/video_output.h>
#endif // BUILD_PANGOLIN_VIDEO
#include <pangolin/image/image_io.h>
// Let other libraries headers know about Pangolin
#define HAVE_PANGOLIN

View File

@@ -0,0 +1,81 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/config.h>
// Include portable printf-style format macros
#define __STDC_FORMAT_MACROS
#ifdef _GCC_
# define PANGOLIN_DEPRECATED __attribute__((deprecated))
#elif defined _MSVC_
# define PANGOLIN_DEPRECATED __declspec(deprecated)
#else
# define PANGOLIN_DEPRECATED
#endif
#ifdef _MSVC_
# define __thread __declspec(thread)
# include <pangolin/pangolin_export.h>
#else
# define PANGOLIN_EXPORT
#endif //_MSVC_
#define PANGOLIN_UNUSED(x) (void)(x)
#ifdef _APPLE_IOS_
// Not supported on this platform.
#define __thread
#endif // _APPLE_IOS_
// HOST / DEVICE Annotations
#ifdef __CUDACC__
# include <cuda_runtime.h>
# define PANGO_HOST_DEVICE __host__ __device__
#else
# define PANGO_HOST_DEVICE
#endif
// Non-standard check that header exists (Clang, GCC 5.X)
// Useful for
#if defined(__has_include)
# define PANGO_HEADER_EXISTS(x) __has_include(x)
#else
# define PANGO_HEADER_EXISTS(x) 0
#endif
// Workaround for Apple-Clangs lack of thread_local support
#if defined(_CLANG_) && defined(_OSX_)
# if !__has_feature(cxx_thread_local)
# define PANGO_NO_THREADLOCAL
# endif
#endif
#include <pangolin/utils/assert.h>
#include <pangolin/utils/log.h>

View File

@@ -0,0 +1,243 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <algorithm> // std::min, std::max
#include <limits>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <string>
#include <vector>
#if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
#define USE_EIGEN
#endif
#ifdef USE_EIGEN
#include <Eigen/Core>
#endif
namespace pangolin
{
/// Simple statistics recorded for a logged input dimension.
struct DimensionStats
{
DimensionStats()
{
Reset();
}
void Reset()
{
isMonotonic = true;
sum = 0.0f;
sum_sq = 0.0f;
min = std::numeric_limits<float>::max();
max = std::numeric_limits<float>::lowest();
}
void Add(const float v)
{
isMonotonic = isMonotonic && (v >= max);
sum += v;
sum_sq += v*v;
min = std::min(min, v);
max = std::max(max, v);
}
bool isMonotonic;
float sum;
float sum_sq;
float min;
float max;
};
class DataLogBlock
{
public:
/// @param dim: dimension of sample
/// @param max_samples: maximum number of samples this block can hold
/// @param start_id: index of first sample (from entire dataset) in this buffer
DataLogBlock(size_t dim, size_t max_samples, size_t start_id)
: dim(dim), max_samples(max_samples), samples(0),
start_id(start_id)
{
sample_buffer = std::unique_ptr<float[]>(new float[dim*max_samples]);
// stats = std::unique_ptr<DimensionStats[]>(new DimensionStats[dim]);
}
~DataLogBlock()
{
}
size_t Samples() const
{
return samples;
}
size_t MaxSamples() const
{
return max_samples;
}
/// Return how many more samples can fit in this block
size_t SampleSpaceLeft() const
{
return MaxSamples()- Samples();
}
bool IsFull() const
{
return Samples() >= MaxSamples();
}
/// Add data to block
void AddSamples(size_t num_samples, size_t dimensions, const float* data_dim_major );
/// Delete all samples
void ClearLinked()
{
samples = 0;
nextBlock.reset();
}
DataLogBlock* NextBlock() const
{
return nextBlock.get();
}
size_t StartId() const
{
return start_id;
}
float* DimData(size_t d) const
{
return sample_buffer.get() + d;
}
size_t Dimensions() const
{
return dim;
}
const float* Sample(size_t n) const
{
const int id = (int)n - (int)start_id;
if( 0 <= id && id < (int)samples ) {
return sample_buffer.get() + dim*id;
}else{
if(nextBlock) {
return nextBlock->Sample(n);
}else{
throw std::out_of_range("Index out of range.");
}
}
}
protected:
size_t dim;
size_t max_samples;
size_t samples;
size_t start_id;
std::unique_ptr<float[]> sample_buffer;
// std::unique_ptr<DimensionStats[]> stats;
std::unique_ptr<DataLogBlock> nextBlock;
};
/// A DataLog can efficiently record floating point sample data of any size.
/// Memory is allocated in blocks is transparent to the user.
class PANGOLIN_EXPORT DataLog
{
public:
/// @param block_samples_alloc number of samples each memory block can hold.
DataLog(unsigned int block_samples_alloc = 10000 );
~DataLog();
/// Provide textual labels corresponding to each dimension logged.
/// This information may be used by graphical interfaces to DataLog.
void SetLabels(const std::vector<std::string> & labels);
const std::vector<std::string>& Labels() const;
void Log(size_t dimension, const float * vals, unsigned int samples = 1);
void Log(float v);
void Log(float v1, float v2);
void Log(float v1, float v2, float v3);
void Log(float v1, float v2, float v3, float v4);
void Log(float v1, float v2, float v3, float v4, float v5);
void Log(float v1, float v2, float v3, float v4, float v5, float v6);
void Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7);
void Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8);
void Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8, float v9);
void Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8, float v9, float v10);
void Log(const std::vector<float> & vals);
#ifdef USE_EIGEN
template<typename Derived>
void Log(const Eigen::MatrixBase<Derived>& M)
{
Log( M.rows() * M.cols(), M.template cast<float>().eval().data() );
}
#endif
void Clear();
void Save(std::string filename);
// Return first block of stored data
const DataLogBlock* FirstBlock() const;
// Return last block of stored data
const DataLogBlock* LastBlock() const;
// Return number of samples stored in this DataLog
size_t Samples() const;
// Return pointer to stored sample n
const float* Sample(int n) const;
// Return stats computed for each dimension if enabled.
const DimensionStats& Stats(size_t dim) const;
std::mutex access_mutex;
protected:
unsigned int block_samples_alloc;
std::vector<std::string> labels;
std::unique_ptr<DataLogBlock> block0;
DataLogBlock* blockn;
std::vector<DimensionStats> stats;
bool record_stats;
};
}

View File

@@ -0,0 +1,282 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef PLOTTER_H
#define PLOTTER_H
#include <limits>
#include <pangolin/display/view.h>
#include <pangolin/gl/colour.h>
#include <pangolin/gl/gl.h>
#include <pangolin/gl/glfont.h>
#include <pangolin/gl/glsl.h>
#include <pangolin/handler/handler.h>
#include <pangolin/plot/datalog.h>
#include <pangolin/plot/range.h>
#include <set>
namespace pangolin
{
enum DrawingMode
{
DrawingModePoints = GL_POINTS,
DrawingModeDashed = GL_LINES,
DrawingModeLine = GL_LINE_STRIP,
DrawingModeNone,
};
struct Marker
{
enum Direction
{
Horizontal,
Vertical
};
enum Equality
{
LessThan = -1,
Equal = 0,
GreaterThan = 1
};
Marker(Direction d, float value, Equality leg = Equal, Colour c = Colour() )
: colour(c)
{
if(d == Horizontal) {
range.x = Rangef::Open();
range.y = Rangef::Containing(value);
if(leg == LessThan) {
range.y.Insert(std::numeric_limits<float>::lowest() );
}else if(leg == GreaterThan) {
range.y.Insert(std::numeric_limits<float>::max() );
}
}else if(d == Vertical) {
range.x = Rangef::Containing(value);
range.y = Rangef::Open();
if(leg == LessThan) {
range.x.Insert(std::numeric_limits<float>::lowest() );
}else if(leg == GreaterThan) {
range.x.Insert(std::numeric_limits<float>::max() );
}
}
}
Marker(const XYRangef& range, const Colour& c = Colour() )
: range(range), colour(c)
{
}
XYRangef range;
Colour colour;
};
class PANGOLIN_EXPORT Plotter : public View, Handler
{
public:
Plotter(
DataLog* default_log,
float left=0, float right=600, float bottom=-1, float top=1,
float tickx=30, float ticky=0.5,
Plotter* linked_plotter_x = 0,
Plotter* linked_plotter_y = 0
);
virtual ~Plotter();
void Render();
XYRangef& GetSelection();
XYRangef& GetDefaultView();
void SetDefaultView(const XYRangef& range);
XYRangef& GetView();
void SetView(const XYRangef& range);
void SetViewSmooth(const XYRangef& range);
void ScrollView(float x, float y);
void ScrollViewSmooth(float x, float y);
void ScaleView(float x, float y, float cx, float cy);
void ScaleViewSmooth(float x, float y, float cx, float cy);
void ResetView();
void SetTicks(float tickx, float ticky);
void Track(const std::string& x="$i", const std::string& y = "");
void ToggleTracking();
void Trigger(const std::string& x="$0", int edge = -1, float value = 0.0f);
void ToggleTrigger();
void SetBackgroundColour(const Colour& col);
void SetAxisColour(const Colour& col);
void SetTickColour(const Colour& col);
void ScreenToPlot(int xpix, int ypix, float &xplot, float &yplot);
void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
void MouseMotion(View&, int x, int y, int mouse_state);
void PassiveMouseMotion(View&, int x, int y, int button_state);
void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
/// Remove all current series plots
void ClearSeries();
/// Add series X,Y plot from glsl compatible expressions x_expr, y_expr
/// $i refers to integral index of datum in log.
/// $0, $1, $2, ... refers to nth series in log.
/// e.g. x_expr = "$i", y_expr = "$0" // index - data[0] plot
/// e.g. x_expr = "$0", y_expr = "$1" // data[0], data[1] X-Y plot
/// e.g. x_exptr ="$i", y_expr = "sqrt($1)} // index - sqrt(data[0]) plot
void AddSeries(const std::string& x_expr, const std::string& y_expr,
DrawingMode drawing_mode = DrawingModeLine, Colour colour = Colour::Unspecified(),
const std::string &title = "$y", DataLog* log = nullptr
);
std::string PlotTitleFromExpr(const std::string& expr) const;
/// Remove all current markers
void ClearMarkers();
/// Add horizontal or vertical inequality marker; equal-to, less-than, or greater than.
/// This is useful for annotating a critical point or valid region.
Marker& AddMarker(
Marker::Direction d, float value,
Marker::Equality leg = Marker::Equal, Colour c = Colour()
);
Marker& AddMarker( const Marker& marker );
void ClearImplicitPlots();
void AddImplicitPlot();
/// Reset colour wheel to initial state. May be useful together with ClearSeries() / ClearMarkers()
void ResetColourWheel();
protected:
struct PANGOLIN_EXPORT Tick
{
float val;
float factor;
std::string symbol;
};
struct PANGOLIN_EXPORT PlotAttrib
{
PlotAttrib(std::string name, int plot_id, int location = -1)
: name(name), plot_id(plot_id), location(location) { }
std::string name;
int plot_id;
int location;
};
struct PANGOLIN_EXPORT PlotSeries
{
PlotSeries();
void CreatePlot(const std::string& x, const std::string& y, Colour c, std::string title);
GlSlProgram prog;
GlText title;
bool contains_id;
std::vector<PlotAttrib> attribs;
DataLog* log;
GLenum drawing_mode;
Colour colour;
bool used;
};
struct PANGOLIN_EXPORT PlotImplicit
{
// Assign to gl_FragColor
void CreatePlot(const std::string& code);
// Expression uses x,y and assignes colours [0,1] to r,g,b,a
void CreateColouredPlot(const std::string& code);
// Expression uses x,y and evaluates to true/false;
void CreateInequality(const std::string& ie, Colour c);
// Expression uses x,y and evaluates to a number
void CreateDistancePlot(const std::string& dist);
GlSlProgram prog;
};
void FixSelection();
void UpdateView();
Tick FindTickFactor(float tick);
DataLog* default_log;
ColourWheel colour_wheel;
Colour colour_bg;
Colour colour_tk;
Colour colour_ax;
GlSlProgram prog_lines;
GlSlProgram prog_text;
std::vector<PlotSeries> plotseries;
std::vector<Marker> plotmarkers;
std::vector<PlotImplicit> plotimplicits;
Tick tick[2];
XYRangef rview_default;
XYRangef rview;
XYRangef target;
XYRangef selection;
void ComputeTrackValue( float track_val[2] );
XYRangef ComputeAutoSelection();
bool track;
std::string track_x;
std::string track_y;
float last_track_val[2];
// -1: falling, -0:disable, 1: rising
int trigger_edge;
float trigger_value;
std::string trigger;
float hover[2];
int last_mouse_pos[2];
Plotter* linked_plotter_x;
Plotter* linked_plotter_y;
};
} // namespace pangolin
#endif // PLOTTER_H

View File

@@ -0,0 +1,372 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2014 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/platform.h>
#include <limits>
#include <algorithm>
#include <cmath>
//prevent including Eigen in cuda files
#if defined(HAVE_EIGEN) && !defined(__CUDACC__)
# define USE_EIGEN
#endif
#ifdef USE_EIGEN
# include <Eigen/Core>
# include <Eigen/src/Geometry/AlignedBox.h>
#endif // USE_EIGEN
namespace pangolin
{
template<typename T>
struct Range
{
static Range<T> Open()
{
return Range<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
}
static Range<T> Empty()
{
return Range<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest());
}
static Range<T> Containing(T val)
{
return Range<T>(val, val);
}
Range()
: min(+std::numeric_limits<T>::max()),
max(-std::numeric_limits<T>::max())
{
}
Range(T rmin, T rmax)
: min(rmin), max(rmax)
{
}
Range operator+(T v)
{
return Range(min+v, max+v);
}
Range operator-(T v)
{
return Range(min-v, max-v);
}
Range& operator+=(T v)
{
min += v;
max += v;
return *this;
}
Range& operator-=(T v)
{
min -= v;
max -= v;
return *this;
}
Range& operator*=(T v)
{
min *= v;
max *= v;
return *this;
}
Range& operator/=(T v)
{
min /= v;
max /= v;
return *this;
}
Range& operator+=(const Range& o)
{
min += o.min;
max += o.max;
return *this;
}
Range& operator-=(const Range& o)
{
min -= o.min;
max -= o.max;
return *this;
}
Range operator+(const Range& o) const
{
return Range(min + o.min, max + o.max);
}
Range operator-(const Range& o) const
{
return Range(min - o.min, max - o.max);
}
Range operator*(float s) const
{
return Range(T(s*min), T(s*max));
}
T Size() const
{
return max - min;
}
T AbsSize() const
{
return std::abs(Size());
}
T Mid() const
{
return (min + max) / (T)2.0f;
}
void Scale(float s, float center = 0.0f)
{
min = T(s*(min-center) + center);
max = T(s*(max-center) + center);
}
void Insert(T v)
{
min = std::min(min,v);
max = std::max(max,v);
}
void Insert(const Range<T>& r)
{
Insert(r.min);
Insert(r.max);
}
void Clamp(T vmin, T vmax)
{
min = std::min(std::max(vmin, min), vmax);
max = std::min(std::max(vmin, max), vmax);
}
void Clamp(const Range& o)
{
Clamp(o.min, o.max);
}
void Clear()
{
min = std::numeric_limits<T>::max();
max = std::numeric_limits<T>::lowest();
}
bool Contains(T v) const
{
return min <= v && v <= max;
}
bool ContainsWeak(T v) const
{
return (min <= v && v <= max)
|| (max <= v && v <= min);
}
template<typename To>
Range<To> Cast() const
{
return Range<To>(To(min), To(max));
}
T min;
T max;
};
template<typename T>
struct XYRange
{
static XYRange<T> Open()
{
return XYRange<T>(
Range<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max()),
Range<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max())
);
}
static XYRange<T> Empty()
{
return XYRange<T>(
Range<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest()),
Range<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest())
);
}
static XYRange<T> Containing(T x, T y)
{
return XYRange<T>(
Range<T>(x, x),
Range<T>(y, y)
);
}
XYRange()
{
}
XYRange(const Range<T>& xrange, const Range<T>& yrange)
: x(xrange), y(yrange)
{
}
XYRange(T xmin, T xmax, T ymin, T ymax)
: x(xmin,xmax), y(ymin,ymax)
{
}
XYRange operator-(const XYRange& o) const
{
return XYRange(x - o.x, y - o.y);
}
XYRange operator*(float s) const
{
return XYRange(x*s, y*s);
}
XYRange& operator+=(const XYRange& o)
{
x += o.x;
y += o.y;
return *this;
}
void Scale(float sx, float sy, float centerx, float centery)
{
x.Scale(sx, centerx);
y.Scale(sy, centery);
}
void Clear()
{
x.Clear();
y.Clear();
}
void Clamp(T xmin, T xmax, T ymin, T ymax)
{
x.Clamp(xmin,xmax);
y.Clamp(ymin,ymax);
}
void Clamp(const XYRange& o)
{
x.Clamp(o.x);
y.Clamp(o.y);
}
void Insert(T xval, T yval)
{
x.Insert(xval);
y.Insert(yval);
}
void Insert(XYRange<T> r)
{
x.Insert(r.x);
y.Insert(r.y);
}
float Area() const
{
return x.Size() * y.Size();
}
bool Contains(float px, float py) const
{
return x.Contains(px) && y.Contains(py);
}
bool ContainsWeak(float px, float py) const
{
return x.ContainsWeak(px) && y.ContainsWeak(py);
}
template<typename To>
XYRange<To> Cast() const
{
return XYRange<To>(
x.template Cast<To>(),
y.template Cast<To>()
);
}
#ifdef USE_EIGEN
operator Eigen::AlignedBox<T,2>() const {
return Eigen::AlignedBox<T,2>(
Eigen::Matrix<T,2,1>(x.min, y.min),
Eigen::Matrix<T,2,1>(x.max, y.max)
);
}
Eigen::Matrix<T,2,1> Center() const {
return Eigen::Matrix<T,2,1>(x.Mid(), y.Mid());
}
#endif
Range<T> x;
Range<T> y;
};
typedef Range<int> Rangei;
typedef Range<float> Rangef;
typedef Range<double> Ranged;
typedef XYRange<int> XYRangei;
typedef XYRange<float> XYRangef;
typedef XYRange<double> XYRanged;
template<typename T> inline
Rangei Round(const Range<T>& r)
{
return Rangei( int(r.min+0.5), int(r.max+0.5) );
}
template<typename T> inline
XYRangei Round(const XYRange<T>& r)
{
return XYRangei( Round(r.x), Round(r.y) );
}
}

View File

@@ -0,0 +1,70 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <Python.h>
#include <pangolin/var/varextra.h>
#include <pangolin/python/pyuniqueobj.h>
#include <pangolin/console/ConsoleInterpreter.h>
#include <queue>
#include <set>
#include <thread>
namespace pangolin
{
class PyInterpreter : public ConsoleInterpreter
{
public:
PyInterpreter();
~PyInterpreter() override;
void PushCommand(const std::string &cmd) override;
bool PullLine(ConsoleLine& line) override;
std::vector<std::string> Complete(
const std::string& cmd, int max_options
) override;
static void AttachPrefix(void* data, const std::string& name, VarValueGeneric& var, bool brand_new );
private:
PyObject* pycompleter;
PyObject* pycomplete;
std::string ToString(PyObject* py);
void CheckPrintClearError();
PyUniqueObj EvalExec(const std::string& cmd);
std::queue<ConsoleLine> line_queue;
std::set<std::string> base_prefixes;
};
}

View File

@@ -0,0 +1,178 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <Python.h>
#include <iomanip>
#include <queue>
#include <structmember.h>
#include <pangolin/var/var.h>
#include <pangolin/console/ConsoleInterpreter.h>
namespace pangolin
{
struct PyPangoIO {
PyObject_HEAD
static PyTypeObject Py_type;
static PyMethodDef Py_methods[];
PyPangoIO(PyTypeObject *type, std::queue<ConsoleLine>& line_queue, ConsoleLineType line_type)
: line_queue(line_queue), line_type(line_type)
{
#if PY_MAJOR_VERSION >= 3
ob_base.ob_refcnt = 1;
ob_base.ob_type = type;
#else
ob_refcnt = 1;
ob_type = type;
#endif
}
static void Py_dealloc(PyPangoIO* self)
{
delete self;
}
static PyObject * Py_new(PyTypeObject */*type*/, PyObject */*args*/, PyObject */*kwds*/)
{
// Failure. Can only new in c++
return 0;
}
static int Py_init(PyPangoIO* /*self*/, PyObject* /*args*/, PyObject* /*kwds*/)
{
return 0;
}
static PyObject* Py_getattr(PyPangoIO *self, char* name)
{
#if PY_MAJOR_VERSION >= 3
PyObject* pystr = PyUnicode_FromString(name);
#else
PyObject* pystr = PyString_FromString(name);
#endif
return PyObject_GenericGetAttr((PyObject*)self, pystr );
}
static int Py_setattr(PyPangoIO *self, char* name, PyObject* val)
{
#if PY_MAJOR_VERSION >= 3
PyObject* pystr = PyUnicode_FromString(name);
#else
PyObject* pystr = PyString_FromString(name);
#endif
return PyObject_GenericSetAttr((PyObject*)self, pystr, val);
}
static PyObject* Py_write(PyPangoIO* self, PyObject *args)
{
const char *text = 0;
if (PyArg_ParseTuple(args, "s", &text)) {
self->buffer += std::string(text);
size_t nl = self->buffer.find_first_of('\n');
while(nl != std::string::npos) {
const std::string line = self->buffer.substr(0,nl);
self->line_queue.push(ConsoleLine(line,self->line_type));
self->buffer = self->buffer.substr(nl+1);
nl = self->buffer.find_first_of('\n');
}
}
Py_RETURN_NONE;
}
std::string buffer;
std::queue<ConsoleLine>& line_queue;
ConsoleLineType line_type;
};
PyMethodDef PyPangoIO::Py_methods[] = {
{"write", (PyCFunction)PyPangoIO::Py_write, METH_VARARGS, "Write to console" },
{NULL, NULL, 0, NULL}
};
#pragma GCC diagnostic push // Ignore python missing initializer warning.
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
PyTypeObject PyPangoIO::Py_type = {
PyVarObject_HEAD_INIT(NULL,0)
"pangolin.PangoIO", /* tp_name*/
sizeof(PyPangoIO), /* tp_basicsize*/
0, /* tp_itemsize*/
(destructor)PyPangoIO::Py_dealloc, /* tp_dealloc*/
0, /* tp_print*/
(getattrfunc)PyPangoIO::Py_getattr, /* tp_getattr*/
(setattrfunc)PyPangoIO::Py_setattr, /* tp_setattr*/
0, /* tp_compare*/
0, /* tp_repr*/
0, /* tp_as_number*/
0, /* tp_as_sequence*/
0, /* tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call*/
0, /* tp_str*/
0, /* tp_getattro*/
0, /* tp_setattro*/
0, /* tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags*/
"PyPangoIO object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
PyPangoIO::Py_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)PyPangoIO::Py_init, /* tp_init */
0, /* tp_alloc */
(newfunc)PyPangoIO::Py_new, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
0, /* tp_del */
0 /* tp_version_tag */
};
#pragma GCC diagnostic pop // Return to normal
}

View File

@@ -0,0 +1,40 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <Python.h>
#include <pangolin/platform.h>
namespace pangolin
{
PANGOLIN_EXPORT
PyMODINIT_FUNC InitPyPangolinModule();
}

View File

@@ -0,0 +1,111 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <Python.h>
#include <pangolin/platform.h>
namespace pangolin
{
/// Class represents a reference counted PythonObject.
/// PythonObject is appropriately Py_INCREF'd and Py_DECREF'd
class PyUniqueObj
{
public:
inline
PyUniqueObj()
: obj(0)
{
}
/// Assumption: PythonObject has already been appropriately INCREF'd.
inline
PyUniqueObj(PyObject* obj)
: obj(obj)
{
}
inline
PyUniqueObj(const PyUniqueObj& other)
:obj(other.obj)
{
if(obj) Py_INCREF(obj);
}
inline
~PyUniqueObj()
{
if(obj) Py_DECREF(obj);
}
inline
PyUniqueObj(PyUniqueObj&& other)
: obj(other.obj)
{
other.obj = 0;
}
inline
void operator=(PyUniqueObj&& other)
{
Release();
obj = other.obj;
other.obj = 0;
}
inline
void operator=(PyObject* obj)
{
Release();
this->obj = obj;
}
inline
void Release() {
if(obj) {
Py_DECREF(obj);
obj = 0;
}
}
inline
PyObject* operator*() {
return obj;
}
inline
operator PyObject*() {
return obj;
}
private:
PyObject* obj;
};
}

View File

@@ -0,0 +1,271 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <Python.h>
#include <structmember.h>
#include <iomanip>
#include <pangolin/var/var.h>
#include <pangolin/python/pyuniqueobj.h>
namespace pangolin
{
PyObject* GetPangoVarAsPython(const std::string& name)
{
VarState::VarStoreContainer::iterator i = VarState::I().vars.find(name);
if(i != VarState::I().vars.end()) {
VarValueGeneric* var = i->second;
try{
if( !strcmp(var->TypeId(), typeid(bool).name() ) ) {
const bool val = Var<bool>(*var).Get();
return PyBool_FromLong( val );
}else if( !strcmp(var->TypeId(), typeid(short).name() ) ||
!strcmp(var->TypeId(), typeid(int).name() ) ||
!strcmp(var->TypeId(), typeid(long).name() ) ) {
const long val = Var<long>(*var).Get();
return PyLong_FromLong( val );
}else if( !strcmp(var->TypeId(), typeid(double).name() ) ||
!strcmp(var->TypeId(), typeid(float).name() ) ) {
const double val = Var<double>(*var).Get();
return PyFloat_FromDouble(val);
}else{
const std::string val = var->str->Get();
#if PY_MAJOR_VERSION >= 3
return PyUnicode_FromString(val.c_str());
#else
return PyString_FromString(val.c_str());
#endif
}
}catch(const std::exception&) {
}
}
Py_RETURN_NONE;
}
void SetPangoVarFromPython(const std::string& name, PyObject* val)
{
try{
if (PyFloat_Check(val)) {
pangolin::Var<double> pango_var(name);
pango_var = PyFloat_AsDouble(val);
pango_var.Meta().gui_changed = true;
}else if (PyLong_Check(val)) {
pangolin::Var<long> pango_var(name);
pango_var = PyLong_AsLong(val);
pango_var.Meta().gui_changed = true;
}else if (PyBool_Check(val)) {
pangolin::Var<bool> pango_var(name);
pango_var = (val == Py_True) ? true : false;
pango_var.Meta().gui_changed = true;
}
#if PY_MAJOR_VERSION >= 3
else if (PyUnicode_Check(val)) {
pangolin::Var<std::string> pango_var(name);
pango_var = PyUnicode_AsUTF8(val);
pango_var.Meta().gui_changed = true;
}
#else
else if (PyString_Check(val)) {
pangolin::Var<std::string> pango_var(name);
pango_var = PyString_AsString(val);
pango_var.Meta().gui_changed = true;
} else if (PyInt_Check(val)) {
pangolin::Var<int> pango_var(name);
pango_var = PyInt_AsLong(val);
pango_var.Meta().gui_changed = true;
}
#endif
else {
PyUniqueObj pystr = PyObject_Repr(val);
#if PY_MAJOR_VERSION >= 3
const std::string str = PyUnicode_AsUTF8(pystr);
#else
const std::string str = PyString_AsString(pystr);
#endif
pangolin::Var<std::string> pango_var(name);
pango_var = str;
pango_var.Meta().gui_changed = true;
}
FlagVarChanged();
}catch(const std::exception& e) {
pango_print_error("%s\n", e.what());
}
}
struct PyVar {
static PyTypeObject Py_type;
PyObject_HEAD
PyVar(PyTypeObject *type)
{
#if PY_MAJOR_VERSION >= 3
ob_base.ob_refcnt = 1;
ob_base.ob_type = type;
#else
ob_refcnt = 1;
ob_type = type;
#endif
}
static void Py_dealloc(PyVar* self)
{
delete self;
}
static PyObject * Py_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
{
PyVar* self = new PyVar(type);
return (PyObject *)self;
}
static int Py_init(PyVar *self, PyObject *args, PyObject * /*kwds*/)
{
char* cNamespace = 0;
if (!PyArg_ParseTuple(args, "s", &cNamespace))
return -1;
self->ns = std::string(cNamespace);
return 0;
}
static PyObject* Py_getattr(PyVar *self, char* name)
{
const std::string prefix = self->ns + ".";
const std::string full_name = self->ns.empty() ? name : prefix + std::string(name);
if( !strcmp(name, "__call__") ||
!strcmp(name, "__dict__") ||
!strcmp(name, "__methods__") ||
!strcmp(name, "__class__") )
{
// Default behaviour
#if PY_MAJOR_VERSION >= 3
return PyObject_GenericGetAttr((PyObject*)self, PyUnicode_FromString(name));
#else
return PyObject_GenericGetAttr((PyObject*)self, PyString_FromString(name));
#endif
} else if( !strcmp(name, "__members__") ) {
const int nss = prefix.size();
PyObject* l = PyList_New(0);
for(const std::string& s : VarState::I().var_adds) {
if(!s.compare(0, nss, prefix)) {
size_t dot = s.find_first_of('.', nss);
std::string val = (dot != std::string::npos) ? s.substr(nss, dot - nss) : s.substr(nss);
#if PY_MAJOR_VERSION >= 3
PyList_Append(l, PyUnicode_FromString(val.c_str()));
#else
PyList_Append(l, PyString_FromString(val.c_str()));
#endif
}
}
return l;
}else if( pangolin::VarState::I().Exists(full_name) ) {
return GetPangoVarAsPython(full_name);
}else{
PyVar* obj = (PyVar*)PyVar::Py_new(&PyVar::Py_type,NULL,NULL);
if(obj) {
obj->ns = full_name;
return PyObject_Init((PyObject *)obj,&PyVar::Py_type);
}
return (PyObject *)obj;
}
Py_RETURN_NONE;
}
static int Py_setattr(PyVar *self, char* name, PyObject* val)
{
const std::string full_name = self->ns.empty() ? name : self->ns + "." + std::string(name);
SetPangoVarFromPython(full_name, val);
return 0;
}
std::string ns;
};
// The uninitialized variable can be ignored.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
PyTypeObject PyVar::Py_type = {
PyVarObject_HEAD_INIT(NULL,0)
"pypangolin.Var", /* tp_name*/
sizeof(PyVar), /* tp_basicsize*/
0, /* tp_itemsize*/
(destructor)PyVar::Py_dealloc, /* tp_dealloc*/
0, /* tp_print*/
(getattrfunc)PyVar::Py_getattr, /* tp_getattr*/
(setattrfunc)PyVar::Py_setattr, /* tp_setattr*/
0, /* tp_compare*/
0, /* tp_repr*/
0, /* tp_as_number*/
0, /* tp_as_sequence*/
0, /* tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call*/
0, /* tp_str*/
0, /* tp_getattro*/
0, /* tp_setattro*/
0, /* tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags*/
"PyVar object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)PyVar::Py_init, /* tp_init */
0, /* tp_alloc */
(newfunc)PyVar::Py_new, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
0, /* tp_del */
0 /* tp_version_tag */
};
#pragma GCC diagnostic pop
}

View File

@@ -0,0 +1,117 @@
#pragma once
#include <pangolin/display/opengl_render_state.h>
#include <pangolin/display/viewport.h>
#include <pangolin/gl/gldraw.h>
#include <pangolin/scene/renderable.h>
#include <pangolin/scene/interactive_index.h>
#ifdef HAVE_EIGEN
# include <Eigen/Geometry>
#endif
namespace pangolin {
struct Axis : public Renderable, public Interactive
{
Axis()
: axis_length(1.0),
label_x(InteractiveIndex::I().Store(this)),
label_y(InteractiveIndex::I().Store(this)),
label_z(InteractiveIndex::I().Store(this))
{
}
void Render(const RenderParams&) override {
glColor4f(1,0,0,1);
glPushName(label_x.Id());
glDrawLine(0,0,0, axis_length,0,0);
glPopName();
glColor4f(0,1,0,1);
glPushName(label_y.Id());
glDrawLine(0,0,0, 0,axis_length,0);
glPopName();
glColor4f(0,0,1,1);
glPushName(label_z.Id());
glDrawLine(0,0,0, 0,0,axis_length);
glPopName();
}
bool Mouse(
int button,
const GLprecision /*win*/[3], const GLprecision /*obj*/[3], const GLprecision /*normal*/[3],
bool /*pressed*/, int button_state, int pickId
) override
{
PANGOLIN_UNUSED(button);
PANGOLIN_UNUSED(button_state);
PANGOLIN_UNUSED(pickId);
#ifdef HAVE_EIGEN
if((button == MouseWheelUp || button == MouseWheelDown) ) {
float scale = (button == MouseWheelUp) ? 0.01f : -0.01f;
if(button_state & KeyModifierShift) scale /= 10;
Eigen::Vector3d rot = Eigen::Vector3d::Zero();
Eigen::Vector3d xyz = Eigen::Vector3d::Zero();
if(button_state & KeyModifierCtrl) {
// rotate
if(pickId == label_x.Id()) {
rot << 1,0,0;
}else if(pickId == label_y.Id()) {
rot << 0,1,0;
}else if(pickId == label_z.Id()) {
rot << 0,0,1;
}else{
return false;
}
}else if(button_state & KeyModifierShift){
// translate
if(pickId == label_x.Id()) {
xyz << 1,0,0;
}else if(pickId == label_y.Id()) {
xyz << 0,1,0;
}else if(pickId == label_z.Id()) {
xyz << 0,0,1;
}else{
return false;
}
}else{
return false;
}
// old from new
Eigen::Matrix<double,4,4> T_on = Eigen::Matrix<double,4,4>::Identity();
T_on.block<3,3>(0,0) = Eigen::AngleAxis<double>(scale,rot).toRotationMatrix();
T_on.block<3,1>(0,3) = scale*xyz;
// Update
T_pc = (ToEigen<double>(T_pc) * T_on.inverse()).eval();
return true;
}
#endif // HAVE_EIGEN
return false;
}
virtual bool MouseMotion(
const GLprecision /*win*/[3], const GLprecision /*obj*/[3], const GLprecision /*normal*/[3],
int /*button_state*/, int /*pickId*/
) override
{
return false;
}
float axis_length;
const InteractiveIndex::Token label_x;
const InteractiveIndex::Token label_y;
const InteractiveIndex::Token label_z;
};
}

View File

@@ -0,0 +1,69 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <pangolin/gl/glplatform.h>
#include <pangolin/display/opengl_render_state.h>
namespace pangolin {
struct Interactive
{
static __thread GLuint current_id;
virtual ~Interactive() {}
virtual bool Mouse(
int button,
const GLprecision win[3], const GLprecision obj[3], const GLprecision normal[3],
bool pressed, int button_state, int pickId
) = 0;
virtual bool MouseMotion(
const GLprecision win[3], const GLprecision obj[3], const GLprecision normal[3],
int button_state, int pickId
) = 0;
};
struct RenderParams
{
RenderParams()
: render_mode(GL_RENDER)
{
}
GLint render_mode;
};
struct Manipulator : public Interactive
{
virtual void Render(const RenderParams& params) = 0;
};
}

View File

@@ -0,0 +1,115 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <map>
#include <pangolin/scene/interactive.h>
namespace pangolin {
class InteractiveIndex
{
public:
class Token
{
public:
friend class InteractiveIndex;
Token()
: id(0)
{
}
Token(Token&& o)
: id(o.id)
{
o.id = 0;
}
GLint Id() const
{
return id;
}
~Token()
{
if(id) {
InteractiveIndex::I().Unstore(*this);
}
}
private:
Token(GLint id)
: id(id)
{
}
GLint id;
};
static InteractiveIndex& I()
{
static InteractiveIndex instance;
return instance;
}
Interactive* Find(GLuint id)
{
auto kv = index.find(id);
if(kv != index.end()) {
return kv->second;
}
return nullptr;
}
Token Store(Interactive* r)
{
index[next_id] = r;
return Token(next_id++);
}
void Unstore(Token& t)
{
index.erase(t.id);
t.id = 0;
}
private:
// Private constructor.
InteractiveIndex()
: next_id(1)
{
}
GLint next_id;
std::map<GLint, Interactive*> index;
};
}

View File

@@ -0,0 +1,117 @@
/* This file is part of the Pangolin Project.
* http://github.com/stevenlovegrove/Pangolin
*
* Copyright (c) 2011 Steven Lovegrove
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <memory>
#include <map>
#include <random>
#include <pangolin/display/opengl_render_state.h>
#include <pangolin/scene/interactive.h>
namespace pangolin {
class Renderable
{
public:
using guid_t = GLuint;
static guid_t UniqueGuid()
{
static std::random_device rd;
static std::mt19937 gen(rd());
return (guid_t)gen();
}
Renderable(const std::weak_ptr<Renderable>& parent = std::weak_ptr<Renderable>())
: guid(UniqueGuid()), parent(parent), T_pc(IdentityMatrix()), should_show(true)
{
}
virtual ~Renderable()
{
}
// Default implementation simply renders children.
virtual void Render(const RenderParams& params = RenderParams()) {
RenderChildren(params);
}
void RenderChildren(const RenderParams& params)
{
for(auto& p : children) {
Renderable& r = *p.second;
if(r.should_show) {
glPushMatrix();
r.T_pc.Multiply();
r.Render(params);
if(r.manipulator) {
r.manipulator->Render(params);
}
glPopMatrix();
}
}
}
std::shared_ptr<Renderable> FindChild(guid_t guid)
{
auto o = children.find(guid);
if(o != children.end()) {
return o->second;
}
for(auto& kv : children ) {
std::shared_ptr<Renderable> c = kv.second->FindChild(guid);
if(c) return c;
}
return std::shared_ptr<Renderable>();
}
Renderable& Add(const std::shared_ptr<Renderable>& child)
{
if(child) {
children[child->guid] = child;
};
return *this;
}
// Renderable properties
const guid_t guid;
std::weak_ptr<Renderable> parent;
pangolin::OpenGlMatrix T_pc;
bool should_show;
// Children
std::map<guid_t, std::shared_ptr<Renderable>> children;
// Manipulator (handler, thing)
std::shared_ptr<Manipulator> manipulator;
};
}

View File

@@ -0,0 +1,182 @@
#pragma once
#include <pangolin/handler/handler.h>
#include <pangolin/scene/renderable.h>
#include <pangolin/scene/interactive_index.h>
namespace pangolin {
inline void gluPickMatrix(
GLdouble x, GLdouble y,
GLdouble width, GLdouble height,
GLint viewport[4]
) {
GLfloat m[16];
GLfloat sx, sy;
GLfloat tx, ty;
sx = viewport[2] / (GLfloat)width;
sy = viewport[3] / (GLfloat)height;
tx = (viewport[2] + 2.0f * (viewport[0] - (GLfloat)x)) / (GLfloat)width;
ty = (viewport[3] + 2.0f * (viewport[1] - (GLfloat)y)) / (GLfloat)height;
#define M(row, col) m[col*4+row]
M(0, 0) = sx;
M(0, 1) = 0.0f;
M(0, 2) = 0.0f;
M(0, 3) = tx;
M(1, 0) = 0.0f;
M(1, 1) = sy;
M(1, 2) = 0.0f;
M(1, 3) = ty;
M(2, 0) = 0.0f;
M(2, 1) = 0.0f;
M(2, 2) = 1.0f;
M(2, 3) = 0.0f;
M(3, 0) = 0.0f;
M(3, 1) = 0.0f;
M(3, 2) = 0.0f;
M(3, 3) = 1.0f;
#undef M
glMultMatrixf(m);
}
struct SceneHandler : public Handler3D
{
SceneHandler(
Renderable& scene,
OpenGlRenderState& cam_state
) : Handler3D(cam_state), scene(scene)
{
}
void ProcessHitBuffer(GLint hits, GLuint* buf, std::map<GLuint, Interactive*>& hit_map )
{
GLuint* closestNames = 0;
GLuint closestNumNames = 0;
GLuint closestZ = std::numeric_limits<GLuint>::max();
for (int i = 0; i < hits; i++) {
if (buf[1] < closestZ) {
closestNames = buf + 3;
closestNumNames = buf[0];
closestZ = buf[1];
}
buf += buf[0] + 3;
}
for (unsigned int i = 0; i < closestNumNames; i++) {
const int pickId = closestNames[i];
hit_map[pickId] = InteractiveIndex::I().Find(pickId);
}
}
void ComputeHits(pangolin::View& view,
const pangolin::OpenGlRenderState& cam_state,
int x, int y, int grab_width,
std::map<GLuint, Interactive*>& hit_objects )
{
// Get views viewport / modelview /projection
GLint viewport[4] = {view.v.l, view.v.b, view.v.w, view.v.h};
pangolin::OpenGlMatrix mv = cam_state.GetModelViewMatrix();
pangolin::OpenGlMatrix proj = cam_state.GetProjectionMatrix();
// Prepare hit buffer object
const unsigned int MAX_SEL_SIZE = 64;
GLuint vSelectBuf[MAX_SEL_SIZE];
glSelectBuffer(MAX_SEL_SIZE, vSelectBuf);
// Load and adjust modelview projection matrices
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPickMatrix(x, y, grab_width, grab_width, viewport);
proj.Multiply();
glMatrixMode(GL_MODELVIEW);
mv.Load();
// Render scenegraph in 'select' mode
glRenderMode(GL_SELECT);
glInitNames();
RenderParams select;
select.render_mode = GL_SELECT;
scene.Render(select);
glFlush();
GLint nHits = glRenderMode(GL_RENDER);
// std::cout << " -- Number of Hits are: " << nHits << std::endl;
// std::cout << " -- size of hitobjects: " << hit_objects.size() << std::endl;
if (nHits > 0) {
ProcessHitBuffer(nHits, vSelectBuf, hit_objects);
}
}
void Mouse(pangolin::View& view, pangolin::MouseButton button,
int x, int y, bool pressed, int button_state)
{
GetPosNormal(view, x, y, p, Pw, Pc, n);
bool handled = false;
if (pressed) {
m_selected_objects.clear();
ComputeHits(view, *cam_state, x, y, 2*hwin+1, m_selected_objects);
}
for (auto kv : m_selected_objects)
{
Interactive* ir = dynamic_cast<Interactive*>(kv.second);
handled |= ir && ir->Mouse( button, p, Pw, n, pressed, button_state, kv.first);
}
if (!handled) {
Handler3D::Mouse(view, button, x, y, pressed, button_state);
}
}
void MouseMotion(pangolin::View& view, int x, int y, int button_state)
{
GetPosNormal(view, x, y, p, Pw, Pc, n);
bool handled = false;
for (auto kv : m_selected_objects)
{
Interactive* ir = dynamic_cast<Interactive*>(kv.second);
handled |= ir && ir->MouseMotion( p, Pw, n, button_state, kv.first);
}
if (!handled) {
pangolin::Handler3D::MouseMotion(view, x, y, button_state);
}
}
void Special(pangolin::View& view, pangolin::InputSpecial inType,
float x, float y, float p1, float p2, float p3, float p4,
int button_state)
{
GetPosNormal(view, (int)x, (int)y, p, Pw, Pc, n);
bool handled = false;
if (inType == pangolin::InputSpecialScroll)
{
m_selected_objects.clear();
ComputeHits(view, *cam_state, (int)x, (int)y, 2*hwin+1, m_selected_objects);
const MouseButton button = p2 > 0 ? MouseWheelUp : MouseWheelDown;
for (auto kv : m_selected_objects)
{
Interactive* ir = dynamic_cast<Interactive*>(kv.second);
handled |= ir && ir->Mouse( button, p, Pw, n, true, button_state, kv.first);
}
}
if (!handled) {
pangolin::Handler3D::Special(view, inType, x, y,
p1, p2, p3, p4, button_state);
}
}
std::map<GLuint, Interactive*> m_selected_objects;
Renderable& scene;
unsigned int grab_width;
};
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include <map>
#include <pangolin/display/opengl_render_state.h>
namespace pangolin {
template<typename T, typename TEdge>
struct TreeNode
{
struct Edge
{
TEdge parent_child;
TreeNode node;
};
T item;
std::vector<Edge> edges;
};
template<typename T, typename TEdge>
using NodeFunction = std::function<void(TreeNode<T,TEdge>&,const TEdge&)>;
//template<typename T, typename TEdge>
//void VisitDepthFirst(TreeNode<T,TEdge>& node, const NodeFunction<T,TEdge>& func, const TEdge& T_root_node = TEdge())
//{
// func(node, T_root_node);
// for(auto& e : node.edges) {
// const TEdge T_root_child = T_root_node * e.parent_child;
// VisitDepthFirst(e.node, func, T_root_child);
// }
//}
//void Eg()
//{
// using RenderNode = TreeNode<std::shared_ptr<Renderable>,OpenGlMatrix>;
// RenderNode root;
// VisitDepthFirst<std::shared_ptr<Renderable>,OpenGlMatrix>(
// root, [](RenderNode& node, const OpenGlMatrix& T_root_node) {
// if(node.item) {
// node.item->DoRender();
// }
// }, IdentityMatrix());
//}
}

View File

@@ -0,0 +1,106 @@
#pragma once
#include <pangolin/display/window.h>
#include <pangolin/platform.h>
#include <pangolin/video/video_input.h>
#include <functional>
#include <mutex>
#include <string>
#include <thread>
namespace pangolin
{
PANGOLIN_EXPORT
class VideoViewer
{
public:
typedef std::function<void(const unsigned char* data,
const std::vector<Image<unsigned char> >& images,
const picojson::value& properties)> FrameChangedCallbackFn;
static constexpr int FRAME_SKIP = 30;
VideoViewer(const std::string& window_name, const std::string& input_uri, const std::string& output_uri = "video.pango" );
VideoViewer(const VideoViewer&) = delete;
virtual ~VideoViewer();
void Run();
void RunAsync();
void Quit();
void QuitAndWait();
inline int TotalFrames() const
{
return video_playback ? video_playback->GetTotalFrames() : std::numeric_limits<int>::max();
}
// Control playback
void OpenInput(const std::string& input_uri);
void CloseInput();
// Control recording
void Record();
void RecordOneFrame();
void StopRecording();
// Useful for user-control
void TogglePlay();
void ToggleRecord();
void ToggleDiscardBufferedFrames();
void ToggleWaitForFrames();
void SetDiscardBufferedFrames(bool new_state);
void SetWaitForFrames(bool new_state);
void Skip(int frames);
bool ChangeExposure(int delta_us);
bool ChangeGain(float delta);
void SetActiveCamera(int delta);
void DrawEveryNFrames(int n);
// Register to be notified of new image data
void SetFrameChangedCallback(FrameChangedCallbackFn cb);
void WaitUntilExit();
VideoInput& Video() {return video;}
const VideoInput& Video() const {return video;}
void SetRecordNthFrame(int record_nth_frame_) {
record_nth_frame = record_nth_frame_;
}
protected:
void RegisterDefaultKeyShortcutsAndPangoVariables();
std::mutex control_mutex;
std::string window_name;
std::thread vv_thread;
VideoInput video;
VideoPlaybackInterface* video_playback;
VideoInterface* video_interface;
std::string output_uri;
int current_frame;
int grab_until;
int record_nth_frame;
int draw_nth_frame;
bool video_grab_wait;
bool video_grab_newest;
bool should_run;
uint16_t active_cam;
FrameChangedCallbackFn frame_changed_callback;
};
void PANGOLIN_EXPORT RunVideoViewerUI(const std::string& input_uri, const std::string& output_uri);
}

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