v01
This commit is contained in:
776
thirdparty/Pangolin/src/CMakeLists.txt
vendored
Normal file
776
thirdparty/Pangolin/src/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,776 @@
|
||||
#######################################################
|
||||
## Library sources
|
||||
|
||||
macro( append_glob list glob )
|
||||
file(GLOB files ${glob})
|
||||
set(${list} "${${list}};${files}")
|
||||
endmacro()
|
||||
|
||||
## Header only includes / core headers
|
||||
set( INCDIR "../include/pangolin" )
|
||||
set( HEADERS
|
||||
${INCDIR}/pangolin.h
|
||||
${INCDIR}/platform.h
|
||||
)
|
||||
append_glob(HEADERS ${INCDIR}/utils/*.h*)
|
||||
append_glob(HEADERS ${INCDIR}/image/*.h*)
|
||||
append_glob(HEADERS ${INCDIR}/log/*.h*)
|
||||
append_glob(HEADERS ${INCDIR}/geometry/*.h*)
|
||||
|
||||
### Store list of source files
|
||||
append_glob(SOURCES utils/*.cpp)
|
||||
append_glob(SOURCES image/*.cpp)
|
||||
append_glob(SOURCES log/*.cpp)
|
||||
append_glob(SOURCES geometry/*.cpp)
|
||||
|
||||
### Store list of Video factory registery methods to call for init.
|
||||
include(CreateMethodCallFile)
|
||||
set( VIDEO_FACTORY_REG "" )
|
||||
set( WINDOW_FACTORY_REG "" )
|
||||
|
||||
#######################################################
|
||||
## User build options
|
||||
|
||||
option(BUILD_PANGOLIN_GUI "Build support for Pangolin GUI" ON)
|
||||
if(BUILD_PANGOLIN_GUI)
|
||||
append_glob(HEADERS ${INCDIR}/gl/*.h*)
|
||||
append_glob(HEADERS ${INCDIR}/display/*.h*)
|
||||
append_glob(HEADERS ${INCDIR}/handler/*.h*)
|
||||
|
||||
append_glob(SOURCES gl/*.cpp)
|
||||
append_glob(SOURCES display/*.cpp)
|
||||
append_glob(SOURCES handler/*.cpp)
|
||||
|
||||
if(NOT HAVE_GLES OR HAVE_GLES_2)
|
||||
append_glob(HEADERS ${INCDIR}/plot/*.h*)
|
||||
append_glob(SOURCES plot/*.cpp)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_VARS "Build support for Pangolin Vars" ON)
|
||||
if(BUILD_PANGOLIN_VARS)
|
||||
append_glob(HEADERS ${INCDIR}/var/*.h*)
|
||||
append_glob(SOURCES var/*.cpp)
|
||||
|
||||
if(BUILD_PANGOLIN_GUI)
|
||||
list(APPEND HEADERS ${INCDIR}/display/widgets/widgets.h )
|
||||
list(APPEND SOURCES display/widgets/widgets.cpp )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_VIDEO "Build support for Pangolin Video Utilities" ON)
|
||||
if(BUILD_PANGOLIN_VIDEO)
|
||||
# Generic video includes
|
||||
append_glob(HEADERS ${INCDIR}/video/*.h*)
|
||||
append_glob(SOURCES video/*.cpp)
|
||||
|
||||
# Generic video drivers
|
||||
list(APPEND HEADERS
|
||||
${INCDIR}/video/drivers/test.h
|
||||
${INCDIR}/video/drivers/images.h
|
||||
${INCDIR}/video/drivers/images_out.h
|
||||
${INCDIR}/video/drivers/split.h
|
||||
${INCDIR}/video/drivers/truncate.h
|
||||
${INCDIR}/video/drivers/pvn.h
|
||||
${INCDIR}/video/drivers/pango.h
|
||||
${INCDIR}/video/drivers/pango_video_output.h
|
||||
${INCDIR}/video/drivers/debayer.h
|
||||
${INCDIR}/video/drivers/shift.h
|
||||
${INCDIR}/video/drivers/mirror.h
|
||||
${INCDIR}/video/drivers/unpack.h
|
||||
${INCDIR}/video/drivers/pack.h
|
||||
${INCDIR}/video/drivers/join.h
|
||||
${INCDIR}/video/drivers/merge.h
|
||||
${INCDIR}/video/drivers/thread.h
|
||||
)
|
||||
list(APPEND SOURCES
|
||||
video/drivers/test.cpp
|
||||
video/drivers/images.cpp
|
||||
video/drivers/images_out.cpp
|
||||
video/drivers/split.cpp
|
||||
video/drivers/truncate.cpp
|
||||
video/drivers/pvn.cpp
|
||||
video/drivers/pango.cpp
|
||||
video/drivers/pango_video_output.cpp
|
||||
video/drivers/debayer.cpp
|
||||
video/drivers/shift.cpp
|
||||
video/drivers/mirror.cpp
|
||||
video/drivers/unpack.cpp
|
||||
video/drivers/pack.cpp
|
||||
video/drivers/join.cpp
|
||||
video/drivers/merge.cpp
|
||||
video/drivers/json.cpp
|
||||
video/drivers/thread.cpp
|
||||
)
|
||||
|
||||
list(APPEND VIDEO_FACTORY_REG
|
||||
RegisterTestVideoFactory
|
||||
RegisterImagesVideoFactory
|
||||
RegisterImagesVideoOutputFactory
|
||||
RegisterSplitVideoFactory
|
||||
RegisterTruncateVideoFactory
|
||||
RegisterPvnVideoFactory
|
||||
RegisterPangoVideoFactory
|
||||
RegisterPangoVideoOutputFactory
|
||||
RegisterDebayerVideoFactory
|
||||
RegisterShiftVideoFactory
|
||||
RegisterMirrorVideoFactory
|
||||
RegisterUnpackVideoFactory
|
||||
RegisterPackVideoFactory
|
||||
RegisterJoinVideoFactory
|
||||
RegisterMergeVideoFactory
|
||||
RegisterJsonVideoFactory
|
||||
RegisterThreadVideoFactory
|
||||
)
|
||||
|
||||
if(_LINUX_)
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/shared_memory.h)
|
||||
list(APPEND SOURCES video/drivers/shared_memory.cpp)
|
||||
# Required for shared memory API using some versions of glibc
|
||||
list(APPEND LINK_LIBS rt pthread)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if(BUILD_PANGOLIN_GUI AND BUILD_PANGOLIN_VARS AND BUILD_PANGOLIN_VIDEO )
|
||||
list(APPEND HEADERS ${INCDIR}/tools/video_viewer.h)
|
||||
list(APPEND SOURCES tools/video_viewer.cpp)
|
||||
endif()
|
||||
|
||||
if(_LINUX_)
|
||||
set(OpenGL_GL_PREFERENCE "GLVND")
|
||||
endif()
|
||||
|
||||
#######################################################
|
||||
## Setup required includes / link info
|
||||
|
||||
option(DISPLAY_X11 "X11 Window Interface" ON)
|
||||
option(DISPLAY_WAYLAND "Wayland Window Interface" OFF)
|
||||
|
||||
if(BUILD_PANGOLIN_GUI)
|
||||
if( ANDROID )
|
||||
# Android specific display code
|
||||
list(APPEND HEADERS ${INCDIR}/display/device/display_android.h )
|
||||
list(APPEND SOURCES display/device/display_android.cpp )
|
||||
list(APPEND WINDOW_FACTORY_REG RegisterAndroidWindowFactory)
|
||||
|
||||
if(HAVE_GLES_2)
|
||||
list(APPEND LINK_LIBS "-lEGL;-lGLESv2" )
|
||||
else()
|
||||
list(APPEND LINK_LIBS "-lEGL;-lGLESv1_CM" )
|
||||
endif()
|
||||
elseif( IOS )
|
||||
list(APPEND LINK_LIBS "-framework OpenGLES" )
|
||||
list(APPEND HEADERS "${INCDIR}/ios/PangolinAppDelegate.h" "${INCDIR}/ios/PangolinViewController.h" )
|
||||
list(APPEND SOURCES "ios/PangolinAppDelegate.mm" "ios/PangolinViewController.mm" )
|
||||
list(APPEND WINDOW_FACTORY_REG RegisterIosWindowFactory)
|
||||
else()
|
||||
find_package(OpenGL REQUIRED)
|
||||
list(APPEND USER_INC ${OPENGL_INCLUDE_DIR})
|
||||
list(APPEND LINK_LIBS ${OPENGL_LIBRARIES})
|
||||
|
||||
if(NOT BUILD_EXTERN_GLEW)
|
||||
find_package(GLEW REQUIRED)
|
||||
endif()
|
||||
list(APPEND USER_INC ${GLEW_INCLUDE_DIR})
|
||||
list(APPEND LINK_LIBS ${GLEW_LIBRARY})
|
||||
endif()
|
||||
|
||||
if( HAVE_GLES_2 )
|
||||
# Add Pangolins backwards compat layer.
|
||||
list(APPEND HEADERS ${INCDIR}/gl2engine.h )
|
||||
list(APPEND SOURCES gl2engine.cpp)
|
||||
endif()
|
||||
|
||||
# headless offscreen rendering via EGL
|
||||
find_package(OpenGL QUIET COMPONENTS EGL)
|
||||
if(OpenGL_EGL_FOUND)
|
||||
list(APPEND WINDOW_FACTORY_REG RegisterNoneWindowFactory)
|
||||
list(APPEND SOURCES display/device/display_headless.cpp)
|
||||
list(APPEND LINK_LIBS ${OPENGL_egl_LIBRARY} )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#######################################################
|
||||
## Find optional dependencies
|
||||
|
||||
if(ANDROID)
|
||||
# Fix issue with thread local storage on android.
|
||||
add_definitions(-fno-data-sections)
|
||||
list(APPEND LINK_LIBS android log)
|
||||
elseif(IOS)
|
||||
# Nothing specific in here yet.
|
||||
else()
|
||||
if(BUILD_PANGOLIN_GUI)
|
||||
if(_WIN_)
|
||||
list(APPEND WINDOW_FACTORY_REG RegisterWinWindowFactory)
|
||||
list(APPEND SOURCES display/device/display_win.cpp )
|
||||
elseif(_OSX_)
|
||||
list(APPEND WINDOW_FACTORY_REG RegisterOsxWindowFactory)
|
||||
list(APPEND SOURCES display/device/display_osx.mm display/device/PangolinNSApplication.mm display/device/PangolinNSGLView.mm )
|
||||
list(APPEND LINK_LIBS "-framework Cocoa" )
|
||||
elseif(_LINUX_)
|
||||
# Wayland
|
||||
if(DISPLAY_WAYLAND)
|
||||
find_package(Wayland QUIET)
|
||||
if(WAYLAND_CLIENT_FOUND)
|
||||
find_package(Wayland REQUIRED)
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(xkbcommon REQUIRED xkbcommon)
|
||||
pkg_check_modules(egl QUIET egl)
|
||||
|
||||
# find Wayland protocols
|
||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
||||
|
||||
# generate header for protocol 'xdg_shell'
|
||||
set(XDG_PROT_DEF "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml")
|
||||
if(EXISTS ${XDG_PROT_DEF})
|
||||
# use the 'xdg_shell' protocol
|
||||
add_definitions(-DUSE_WL_XDG=1)
|
||||
|
||||
# find 'wayland-scanner' executable
|
||||
pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
|
||||
|
||||
# generate protocol implementation
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xdg-shell-client-protocol.h
|
||||
COMMAND ${WAYLAND_SCANNER} client-header ${XDG_PROT_DEF} xdg-shell-client-protocol.h)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xdg-shell-protocol.c
|
||||
COMMAND ${WAYLAND_SCANNER} private-code ${XDG_PROT_DEF} xdg-shell-protocol.c
|
||||
DEPENDS xdg-shell-client-protocol.h)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
list(APPEND SOURCES xdg-shell-protocol.c)
|
||||
|
||||
else()
|
||||
# use deprecated 'wl_shell' interface
|
||||
add_definitions(-DUSE_WL_XDG=0)
|
||||
endif()
|
||||
|
||||
list(APPEND WINDOW_FACTORY_REG RegisterWaylandWindowFactory)
|
||||
list(APPEND SOURCES display/device/display_wayland.cpp)
|
||||
list(APPEND LINK_LIBS
|
||||
${WAYLAND_CLIENT_LIBRARIES}
|
||||
${WAYLAND_EGL_LIBRARIES}
|
||||
${WAYLAND_CURSOR_LIBRARIES}
|
||||
${egl_LIBRARIES}
|
||||
${xkbcommon_LIBRARIES}
|
||||
)
|
||||
list(APPEND INTERNAL_INC
|
||||
${WAYLAND_CLIENT_INCLUDE_DIR}
|
||||
${WAYLAND_EGL_INCLUDE_DIR}
|
||||
${WAYLAND_CURSOR_INCLUDE_DIR}
|
||||
${egl_INCLUDE_DIRS}
|
||||
${xkbcommon_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# X11
|
||||
find_package(X11 QUIET)
|
||||
if(DISPLAY_X11 AND X11_FOUND)
|
||||
list(APPEND WINDOW_FACTORY_REG RegisterX11WindowFactory)
|
||||
list(APPEND USER_INC ${X11_INCLUDE_DIR})
|
||||
list(APPEND SOURCES display/device/display_x11.cpp )
|
||||
list(APPEND LINK_LIBS ${X11_LIBRARIES} )
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
append_glob(HEADERS ${INCDIR}/utils/posix/*.h*)
|
||||
append_glob(SOURCES utils/posix/*.cpp)
|
||||
if(_LINUX_)
|
||||
# Required for shared memory API using some versions of glibc
|
||||
list(APPEND LINK_LIBS rt pthread)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_PYTHON "Build support for Pangolin Interactive Console" ON)
|
||||
if(BUILD_PANGOLIN_PYTHON AND BUILD_PANGOLIN_GUI AND BUILD_PANGOLIN_VARS AND NOT _WIN_)
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../external/pybind11/CMakeLists.txt")
|
||||
add_subdirectory("../external/pybind11" "${CMAKE_CURRENT_BINARY_DIR}/external/pybind11")
|
||||
set( pybind11_FOUND true)
|
||||
else()
|
||||
find_package(pybind11 QUIET)
|
||||
endif()
|
||||
|
||||
if(pybind11_FOUND)
|
||||
set(HAVE_PYTHON 1)
|
||||
|
||||
file(GLOB pypangolin_SRC "python/pypangolin/*.cpp" )
|
||||
file(GLOB pypangolin_HDR "python/pypangolin/*.hpp" )
|
||||
list(APPEND HEADERS
|
||||
${INCDIR}/console/ConsoleInterpreter.h
|
||||
${INCDIR}/console/ConsoleView.h
|
||||
${INCDIR}/python/pyinterpreter.h
|
||||
${INCDIR}/python/pypangolin_init.h
|
||||
${INCDIR}/python/pyuniqueobj.h
|
||||
${INCDIR}/python/pyvar.h
|
||||
${INCDIR}/python/pypangoio.h
|
||||
${pypangolin_HDR}
|
||||
)
|
||||
list(APPEND SOURCES
|
||||
console/ConsoleView.cpp
|
||||
python/pyinterpreter.cpp
|
||||
python/pypangolin_init.cpp
|
||||
${pypangolin_SRC}
|
||||
)
|
||||
|
||||
# pybind11 stuff
|
||||
list(APPEND INTERNAL_INC ${PYBIND11_INCLUDE_DIR})
|
||||
list(APPEND LINK_LIBS PRIVATE ${pybind11_LIBRARIES})
|
||||
|
||||
if(_GCC_)
|
||||
set_source_files_properties(python/PyInterpreter.cpp PROPERTIES COMPILE_FLAGS "-Wno-missing-field-initializers")
|
||||
set_source_files_properties(python/PyModulePangolin.cpp PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -Wno-missing-field-initializers")
|
||||
endif()
|
||||
list(APPEND INTERNAL_INC ${PYTHON_INCLUDE_DIRS})
|
||||
list(APPEND LINK_LIBS ${PYTHON_LIBRARIES})
|
||||
message(STATUS "Python Found and Enabled (with pybind11)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_EIGEN "Build support for Eigen matrix types" ON)
|
||||
if(BUILD_PANGOLIN_EIGEN)
|
||||
find_package(Eigen QUIET)
|
||||
if(EIGEN_FOUND)
|
||||
set(HAVE_EIGEN 1)
|
||||
list(APPEND USER_INC ${EIGEN_INCLUDE_DIR} )
|
||||
if(_CLANG_)
|
||||
# Eigen causes many of these errors. Suppress.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-register")
|
||||
endif()
|
||||
message(STATUS "Eigen Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_TOON "Build support for TooN matrix types" ON)
|
||||
if(BUILD_PANGOLIN_TOON)
|
||||
find_package(TooN QUIET)
|
||||
if(TooN_FOUND)
|
||||
set(HAVE_TOON 1)
|
||||
list(APPEND USER_INC ${TooN_INCLUDE_DIR} )
|
||||
message(STATUS "TooN Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_LIBDC1394 "Build support for libdc1394 video input" ON)
|
||||
if(BUILD_PANGOLIN_LIBDC1394 AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(DC1394 QUIET)
|
||||
if(DC1394_FOUND)
|
||||
set(HAVE_DC1394 1)
|
||||
list(APPEND INTERNAL_INC ${DC1394_INCLUDE_DIR} )
|
||||
list(APPEND LINK_LIBS ${DC1394_LIBRARY} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/firewire.h ${INCDIR}/video/drivers/deinterlace.h )
|
||||
list(APPEND SOURCES video/drivers/firewire.cpp video/drivers/deinterlace.cpp)
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterFirewireVideoFactory )
|
||||
message(STATUS "libdc1394 Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_V4L "Build support for V4L video input" ON)
|
||||
if(BUILD_PANGOLIN_V4L AND BUILD_PANGOLIN_VIDEO AND _LINUX_)
|
||||
set(HAVE_V4L 1)
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/v4l.h)
|
||||
list(APPEND SOURCES video/drivers/v4l.cpp)
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterV4lVideoFactory )
|
||||
message(STATUS "V4L Found and Enabled")
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_FFMPEG "Build support for ffmpeg video input" ON)
|
||||
if(BUILD_PANGOLIN_FFMPEG AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(FFMPEG QUIET)
|
||||
if(FFMPEG_FOUND)
|
||||
set(HAVE_FFMPEG 1)
|
||||
list(APPEND INTERNAL_INC ${FFMPEG_INCLUDE_DIRS} )
|
||||
list(APPEND LINK_LIBS ${FFMPEG_LIBRARIES} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/ffmpeg.h)
|
||||
list(APPEND SOURCES video/drivers/ffmpeg.cpp)
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterFfmpegVideoFactory )
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterFfmpegVideoOutputFactory )
|
||||
|
||||
if(_GCC_)
|
||||
# FFMPEG is a real pain for deprecating the API.
|
||||
set_source_files_properties(video/drivers/ffmpeg.cpp PROPERTIES COMPILE_FLAGS "-Wno-deprecated-declarations")
|
||||
endif()
|
||||
message(STATUS "ffmpeg Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_LIBREALSENSE "Build support for LibRealSense video input" ON)
|
||||
if(BUILD_PANGOLIN_LIBREALSENSE AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(LibRealSense QUIET)
|
||||
if(LIBREALSENSE_FOUND)
|
||||
set(HAVE_LIBREALSENSE 1)
|
||||
list(APPEND INTERNAL_INC ${LIBREALSENSE_INCLUDE_DIRS} )
|
||||
list(APPEND LINK_LIBS ${LIBREALSENSE_LIBRARIES} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/realsense.h )
|
||||
list(APPEND SOURCES video/drivers/realsense.cpp)
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterRealSenseVideoFactory )
|
||||
message(STATUS "LibRealSense Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_LIBREALSENSE2 "Build support for LibRealSense2 video input" ON)
|
||||
if(BUILD_PANGOLIN_LIBREALSENSE2 AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(LibRealSense2 QUIET)
|
||||
if(LIBREALSENSE2_FOUND)
|
||||
set(HAVE_LIBREALSENSE2 1)
|
||||
list(APPEND INTERNAL_INC ${LIBREALSENSE2_INCLUDE_DIRS} )
|
||||
list(APPEND LINK_LIBS ${LIBREALSENSE2_LIBRARIES} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/realsense2.h )
|
||||
list(APPEND SOURCES video/drivers/realsense2.cpp)
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterRealSense2VideoFactory )
|
||||
message(STATUS "LibRealSense2 Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_OPENNI "Build support for OpenNI video input" ON)
|
||||
if(BUILD_PANGOLIN_OPENNI AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(OpenNI QUIET)
|
||||
if(OPENNI_FOUND)
|
||||
set(HAVE_OPENNI 1)
|
||||
if(_LINUX_)
|
||||
add_definitions(-Dlinux=1)
|
||||
endif()
|
||||
list(APPEND INTERNAL_INC ${OPENNI_INCLUDE_DIRS} )
|
||||
list(APPEND LINK_LIBS ${OPENNI_LIBRARIES} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/openni.h )
|
||||
list(APPEND SOURCES video/drivers/openni.cpp)
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterOpenNiVideoFactory )
|
||||
message(STATUS "OpenNI Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_OPENNI2 "Build support for OpenNI2 video input" ON)
|
||||
if(BUILD_PANGOLIN_OPENNI2 AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(OpenNI2 QUIET)
|
||||
if(OPENNI2_FOUND)
|
||||
set(HAVE_OPENNI2 1)
|
||||
if(_LINUX_)
|
||||
add_definitions(-Dlinux=1)
|
||||
endif()
|
||||
list(APPEND INTERNAL_INC ${OPENNI2_INCLUDE_DIRS} )
|
||||
list(APPEND LINK_LIBS ${OPENNI2_LIBRARIES} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/openni2.h )
|
||||
list(APPEND SOURCES video/drivers/openni2.cpp)
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterOpenNi2VideoFactory )
|
||||
message(STATUS "OpenNI2 Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_LIBUVC "Build support for libuvc video input" ON)
|
||||
if(BUILD_PANGOLIN_LIBUVC AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(uvc QUIET)
|
||||
if(uvc_FOUND)
|
||||
set(HAVE_UVC 1)
|
||||
list(APPEND INTERNAL_INC ${uvc_INCLUDE_DIRS} )
|
||||
list(APPEND LINK_LIBS ${uvc_LIBRARIES} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/uvc.h )
|
||||
list(APPEND SOURCES video/drivers/uvc.cpp)
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterUvcVideoFactory )
|
||||
if(_WIN_)
|
||||
find_package(pthread REQUIRED QUIET)
|
||||
list(APPEND LINK_LIBS ${pthread_LIBRARIES} )
|
||||
|
||||
find_package(libusb1 REQUIRED QUIET)
|
||||
list(APPEND LINK_LIBS ${libusb1_LIBRARIES} )
|
||||
endif()
|
||||
message(STATUS "libuvc Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_UVC_MEDIAFOUNDATION "Build support for MediaFoundation UVC input" ON)
|
||||
if (BUILD_PANGOLIN_UVC_MEDIAFOUNDATION AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(MediaFoundation QUIET)
|
||||
if (MediaFoundation_FOUND)
|
||||
list(APPEND LINK_LIBS ${MediaFoundation_LIBRARIES} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/uvc_mediafoundation.h )
|
||||
list(APPEND SOURCES video/drivers/uvc_mediafoundation.cpp )
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterUvcMediaFoundationVideoFactory )
|
||||
message(STATUS "MediaFoundation Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_DEPTHSENSE "Build support for DepthSense video input" ON)
|
||||
if(BUILD_PANGOLIN_DEPTHSENSE AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(DepthSense QUIET)
|
||||
if(DepthSense_FOUND)
|
||||
set(HAVE_DEPTHSENSE 1)
|
||||
list(APPEND INTERNAL_INC ${DepthSense_INCLUDE_DIRS} )
|
||||
list(APPEND LINK_LIBS ${DepthSense_LIBRARIES} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/depthsense.h )
|
||||
list(APPEND SOURCES video/drivers/depthsense.cpp)
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterDepthSenseVideoFactory )
|
||||
message(STATUS "DepthSense Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_TELICAM "Build support for TeliCam video input" ON)
|
||||
if(BUILD_PANGOLIN_TELICAM AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(TeliCam QUIET)
|
||||
if(TeliCam_FOUND)
|
||||
set(HAVE_TELICAM 1)
|
||||
list(APPEND INTERNAL_INC ${TeliCam_INCLUDE_DIRS} )
|
||||
list(APPEND LINK_LIBS ${TeliCam_LIBRARIES} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/teli.h )
|
||||
list(APPEND SOURCES video/drivers/teli.cpp )
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterTeliVideoFactory )
|
||||
|
||||
message(STATUS "TeliCam Found and Enabled" )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_PLEORA "Build support for Pleora video input" ON)
|
||||
if(BUILD_PANGOLIN_PLEORA AND BUILD_PANGOLIN_VIDEO)
|
||||
find_package(Pleora QUIET)
|
||||
if(Pleora_FOUND)
|
||||
set(HAVE_PLEORA 1)
|
||||
list(APPEND INTERNAL_INC ${Pleora_INCLUDE_DIRS} )
|
||||
list(APPEND LINK_LIBS ${Pleora_LIBRARIES} )
|
||||
list(APPEND HEADERS ${INCDIR}/video/drivers/pleora.h )
|
||||
list(APPEND SOURCES video/drivers/pleora.cpp )
|
||||
list(APPEND VIDEO_FACTORY_REG RegisterPleoraVideoFactory )
|
||||
|
||||
if(_GCC_)
|
||||
# Suppress warnings generated from Pleora SDK.
|
||||
set_source_files_properties(video/drivers/pleora.cpp PROPERTIES COMPILE_FLAGS -Wno-unknown-pragmas)
|
||||
set_source_files_properties(video/video.cpp PROPERTIES COMPILE_FLAGS -Wno-unknown-pragmas)
|
||||
endif()
|
||||
message(STATUS "Pleora Found and Enabled" )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_LIBPNG "Build support for libpng image input" ON)
|
||||
if(BUILD_PANGOLIN_LIBPNG)
|
||||
if(NOT BUILD_EXTERN_LIBPNG)
|
||||
find_package(PNG QUIET)
|
||||
endif()
|
||||
if(PNG_FOUND)
|
||||
# (ZLIB is also found by FindPNG.cmake as its dependency)
|
||||
set(HAVE_PNG 1)
|
||||
list(APPEND INTERNAL_INC ${PNG_INCLUDE_DIR} )
|
||||
list(APPEND LINK_LIBS ${PNG_LIBRARY} ${ZLIB_LIBRARY} )
|
||||
message(STATUS "libpng Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_LIBJPEG "Build support for libjpeg image input" ON)
|
||||
if(BUILD_PANGOLIN_LIBJPEG)
|
||||
if(NOT BUILD_EXTERN_LIBJPEG)
|
||||
find_package(JPEG QUIET)
|
||||
endif()
|
||||
if(JPEG_FOUND)
|
||||
set(HAVE_JPEG 1)
|
||||
list(APPEND INTERNAL_INC ${JPEG_INCLUDE_DIR} )
|
||||
list(APPEND LINK_LIBS ${JPEG_LIBRARY} )
|
||||
message(STATUS "libjpeg Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_LIBTIFF "Build support for libtiff image input" ON)
|
||||
if(BUILD_PANGOLIN_LIBTIFF)
|
||||
find_package(TIFF QUIET)
|
||||
if(TIFF_FOUND)
|
||||
set(HAVE_TIFF 1)
|
||||
list(APPEND INTERNAL_INC ${TIFF_INCLUDE_DIR} )
|
||||
list(APPEND LINK_LIBS ${TIFF_LIBRARY} )
|
||||
message(STATUS "libtiff Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_LIBOPENEXR "Build support for libopenexr image input" ON)
|
||||
if(BUILD_PANGOLIN_LIBOPENEXR)
|
||||
find_package(OpenEXR QUIET)
|
||||
if(OpenEXR_FOUND)
|
||||
set(HAVE_OPENEXR 1)
|
||||
list(APPEND INTERNAL_INC ${OpenEXR_INCLUDE_DIR} )
|
||||
list(APPEND LINK_LIBS ${OpenEXR_LIBRARY} )
|
||||
message(STATUS "libopenexr Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_ZSTD "Build support for libzstd compression" ON)
|
||||
if(BUILD_PANGOLIN_ZSTD)
|
||||
find_package(zstd QUIET)
|
||||
if(zstd_FOUND)
|
||||
set(HAVE_ZSTD 1)
|
||||
list(APPEND INTERNAL_INC ${zstd_INCLUDE_DIR} )
|
||||
list(APPEND LINK_LIBS ${zstd_LIBRARY} )
|
||||
message(STATUS "libzstd Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(BUILD_PANGOLIN_LZ4 "Build support for liblz4 compression" ON)
|
||||
if(BUILD_PANGOLIN_LZ4)
|
||||
find_package(Lz4 QUIET)
|
||||
if(Lz4_FOUND)
|
||||
set(HAVE_LZ4 1)
|
||||
list(APPEND INTERNAL_INC ${Lz4_INCLUDE_DIRS} )
|
||||
list(APPEND LINK_LIBS ${Lz4_LIBRARIES} )
|
||||
message(STATUS "liblz4 Found and Enabled")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#######################################################
|
||||
## Embed resource binary files
|
||||
|
||||
include(EmbedBinaryFiles)
|
||||
|
||||
if(BUILD_PANGOLIN_GUI)
|
||||
embed_binary_files( "_embed_/fonts/*.ttf" "${CMAKE_CURRENT_BINARY_DIR}/fonts.cpp" )
|
||||
list(APPEND SOURCES "${CMAKE_CURRENT_BINARY_DIR}/fonts.cpp" )
|
||||
endif()
|
||||
|
||||
#######################################################
|
||||
## Add Libraries / Include Directories / Link directories
|
||||
|
||||
set(INSTALL_INCLUDE_DIR "include")
|
||||
|
||||
add_library(${LIBRARY_NAME} ${SOURCES} ${HEADERS})
|
||||
# 'System' includes shield us from warnings in those includes.
|
||||
target_include_directories(${LIBRARY_NAME} SYSTEM PUBLIC ${USER_INC} PRIVATE ${INTERNAL_INC})
|
||||
target_include_directories(${LIBRARY_NAME} PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR}>)
|
||||
target_link_libraries(${LIBRARY_NAME} PUBLIC ${LINK_LIBS})
|
||||
|
||||
## Generate symbol export helper header on MSVC
|
||||
IF(MSVC)
|
||||
string(TOUPPER ${LIBRARY_NAME} LIBRARY_NAME_CAPS)
|
||||
include(GenerateExportHeader)
|
||||
GENERATE_EXPORT_HEADER( ${LIBRARY_NAME}
|
||||
BASE_NAME ${LIBRARY_NAME_CAPS}
|
||||
EXPORT_MACRO_NAME ${LIBRARY_NAME_CAPS}_EXPORT
|
||||
EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/${LIBRARY_NAME}/${LIBRARY_NAME}_export.h"
|
||||
STATIC_DEFINE ${LIBRARY_NAME_CAPS}_BUILT_AS_STATIC
|
||||
)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/${LIBRARY_NAME}/${LIBRARY_NAME}_export.h"
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}/${LIBRARY_NAME}
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
## Set Special Compiler flags
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "/EHs ${CMAKE_CXX_FLAGS}")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wno-error=deprecated-declarations ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
#######################################################
|
||||
## Create config.h file for inclusion in library
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/config.h.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/${LIBRARY_NAME}/config.h"
|
||||
)
|
||||
|
||||
#######################################################
|
||||
## Create video_drivers.h file for inclusion in library
|
||||
## This loads video driver factories based on cmake configuration
|
||||
|
||||
CreateMethodCallFile(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/${LIBRARY_NAME}/video_drivers.h"
|
||||
"pangolin" "LoadBuiltInVideoDrivers" "${VIDEO_FACTORY_REG}"
|
||||
)
|
||||
|
||||
#######################################################
|
||||
## Create window_frameworks.h file for inclusion in library
|
||||
## This loads windowing framwork factories based on cmake configuration
|
||||
|
||||
CreateMethodCallFile(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/include/${LIBRARY_NAME}/window_frameworks.h"
|
||||
"pangolin" "LoadBuiltInWindowFrameworks" "${WINDOW_FACTORY_REG}"
|
||||
)
|
||||
|
||||
#######################################################
|
||||
## Python wrapper
|
||||
|
||||
option(BUILD_PYPANGOLIN_MODULE "Python wrapper for Pangolin" ON)
|
||||
if(BUILD_PYPANGOLIN_MODULE AND HAVE_PYTHON )
|
||||
file(GLOB pypangolin_SRC "python/pypangolin/*.hpp" "python/pypangolin/*.cpp" "python/pypangolin_module.cpp")
|
||||
pybind11_add_module(pypangolin ${pypangolin_SRC})
|
||||
target_link_libraries(pypangolin PRIVATE ${LIBRARY_NAME})
|
||||
target_include_directories(pypangolin PRIVATE "${USER_INC}")
|
||||
endif()
|
||||
|
||||
#######################################################
|
||||
## Generate Doxygen documentation target (make pangolin_doc)
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../doc )
|
||||
add_custom_target(pangolin_doc
|
||||
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../doc
|
||||
COMMENT "Generating API documentation with Doxygen" VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
#######################################################
|
||||
|
||||
# This relative path allows installed files to be relocatable.
|
||||
set( CMAKECONFIG_INSTALL_DIR lib/cmake/${PROJECT_NAME} )
|
||||
file( RELATIVE_PATH REL_INCLUDE_DIR
|
||||
"${CMAKE_INSTALL_PREFIX}/${CMAKECONFIG_INSTALL_DIR}"
|
||||
"${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}"
|
||||
)
|
||||
|
||||
# Export library for easy inclusion from other cmake projects. APPEND allows
|
||||
# call to function even as subdirectory of larger project.
|
||||
FILE(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake")
|
||||
export( TARGETS ${LIBRARY_NAME}
|
||||
APPEND FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake" )
|
||||
|
||||
# Version information
|
||||
configure_file(${PROJECT_NAME}ConfigVersion.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" @ONLY)
|
||||
|
||||
# Build tree config
|
||||
set( EXPORT_LIB_INC_DIR "${PROJECT_SOURCE_DIR}/include;${CMAKE_CURRENT_BINARY_DIR}/include" )
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake @ONLY IMMEDIATE )
|
||||
|
||||
# Install tree config
|
||||
set( EXPORT_LIB_INC_DIR "\${PROJECT_CMAKE_DIR}/${REL_INCLUDE_DIR}" )
|
||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake @ONLY )
|
||||
|
||||
# Add package to CMake package registery for use from the build tree
|
||||
option( EXPORT_${PROJECT_NAME}
|
||||
"Should the ${PROJECT_NAME} package be exported for use by other software" ON )
|
||||
|
||||
if( EXPORT_${PROJECT_NAME} )
|
||||
export( PACKAGE ${PROJECT_NAME} )
|
||||
endif()
|
||||
|
||||
#######################################################
|
||||
## Install headers / targets
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/${LIBRARY_NAME}/config.h"
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}/${LIBRARY_NAME}
|
||||
)
|
||||
install(DIRECTORY ${INCDIR}
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}
|
||||
)
|
||||
install(TARGETS ${LIBRARY_NAME}
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib
|
||||
)
|
||||
|
||||
#######################################################
|
||||
## Install CMake config
|
||||
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
DESTINATION ${CMAKECONFIG_INSTALL_DIR}
|
||||
)
|
||||
install(
|
||||
EXPORT ${PROJECT_NAME}Targets DESTINATION ${CMAKECONFIG_INSTALL_DIR}
|
||||
)
|
||||
2281
thirdparty/Pangolin/src/Doxyfile.in
vendored
Normal file
2281
thirdparty/Pangolin/src/Doxyfile.in
vendored
Normal file
File diff suppressed because it is too large
Load Diff
14
thirdparty/Pangolin/src/PangolinConfig.cmake.in
vendored
Normal file
14
thirdparty/Pangolin/src/PangolinConfig.cmake.in
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Compute paths
|
||||
get_filename_component( PROJECT_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH )
|
||||
SET( Pangolin_INCLUDE_DIRS "@EXPORT_LIB_INC_DIR@;@USER_INC@" )
|
||||
SET( Pangolin_INCLUDE_DIR "@EXPORT_LIB_INC_DIR@;@USER_INC@" )
|
||||
|
||||
# Library dependencies (contains definitions for IMPORTED targets)
|
||||
if( NOT TARGET @LIBRARY_NAME@ AND NOT @PROJECT_NAME@_BINARY_DIR )
|
||||
include( "${PROJECT_CMAKE_DIR}/@PROJECT_NAME@Targets.cmake" )
|
||||
@ExternConfig@
|
||||
endif()
|
||||
|
||||
SET( Pangolin_LIBRARIES @LIBRARY_NAME@ )
|
||||
SET( Pangolin_LIBRARY @LIBRARY_NAME@ )
|
||||
SET( Pangolin_CMAKEMODULES @CMAKE_CURRENT_SOURCE_DIR@/../CMakeModules )
|
||||
17
thirdparty/Pangolin/src/PangolinConfigVersion.cmake.in
vendored
Normal file
17
thirdparty/Pangolin/src/PangolinConfigVersion.cmake.in
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
set(PACKAGE_VERSION "@PANGOLIN_VERSION@")
|
||||
|
||||
# Check build type is valid
|
||||
if( "System:${CMAKE_SYSTEM_NAME},Win64:${CMAKE_CL_64},Android:${ANDROID},iOS:${IOS}" STREQUAL
|
||||
"System:@CMAKE_SYSTEM_NAME@,Win64:@CMAKE_CL_64@,Android:@ANDROID@,iOS:@IOS@" )
|
||||
# Check whether the requested PACKAGE_FIND_VERSION is compatible
|
||||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
endif()
|
||||
BIN
thirdparty/Pangolin/src/_embed_/fonts/AnonymousPro.ttf
vendored
Normal file
BIN
thirdparty/Pangolin/src/_embed_/fonts/AnonymousPro.ttf
vendored
Normal file
Binary file not shown.
94
thirdparty/Pangolin/src/_embed_/fonts/AnonymousPro.txt
vendored
Normal file
94
thirdparty/Pangolin/src/_embed_/fonts/AnonymousPro.txt
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
Copyright (c) 2009, Mark Simonson (http://www.ms-studio.com, mark@marksimonson.com),
|
||||
with Reserved Font Name Anonymous Pro.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
72
thirdparty/Pangolin/src/config.h.in
vendored
Normal file
72
thirdparty/Pangolin/src/config.h.in
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef PANGOLIN_CONFIG_H
|
||||
#define PANGOLIN_CONFIG_H
|
||||
|
||||
/*
|
||||
* Configuration Header for Pangolin
|
||||
*/
|
||||
|
||||
/// Version
|
||||
#define PANGOLIN_VERSION_MAJOR @PANGOLIN_VERSION_MAJOR@
|
||||
#define PANGOLIN_VERSION_MINOR @PANGOLIN_VERSION_MINOR@
|
||||
#define PANGOLIN_VERSION_STRING "@PANGOLIN_VERSION@"
|
||||
|
||||
/// Pangolin options
|
||||
#cmakedefine BUILD_PANGOLIN_GUI
|
||||
#cmakedefine BUILD_PANGOLIN_VARS
|
||||
#cmakedefine BUILD_PANGOLIN_VIDEO
|
||||
|
||||
/// Configured libraries
|
||||
#cmakedefine HAVE_CUDA
|
||||
#cmakedefine HAVE_PYTHON
|
||||
|
||||
#cmakedefine HAVE_EIGEN
|
||||
#cmakedefine HAVE_TOON
|
||||
|
||||
#cmakedefine HAVE_DC1394
|
||||
#cmakedefine HAVE_V4L
|
||||
#cmakedefine HAVE_OPENNI
|
||||
#cmakedefine HAVE_LIBREALSENSE
|
||||
#cmakedefine HAVE_OPENNI2
|
||||
#cmakedefine HAVE_UVC
|
||||
#cmakedefine HAVE_DEPTHSENSE
|
||||
#cmakedefine HAVE_TELICAM
|
||||
#cmakedefine HAVE_PLEORA
|
||||
|
||||
#cmakedefine HAVE_FFMPEG
|
||||
#cmakedefine HAVE_FFMPEG_MAX_ANALYZE_DURATION2
|
||||
#cmakedefine HAVE_FFMPEG_AVFORMAT_ALLOC_OUTPUT_CONTEXT2
|
||||
#cmakedefine HAVE_FFMPEG_AVPIXELFORMAT
|
||||
|
||||
#cmakedefine HAVE_GLEW
|
||||
#cmakedefine GLEW_STATIC
|
||||
|
||||
#cmakedefine HAVE_APPLE_OPENGL_FRAMEWORK
|
||||
#cmakedefine HAVE_GLES
|
||||
#cmakedefine HAVE_GLES_2
|
||||
#cmakedefine HAVE_OCULUS
|
||||
|
||||
#cmakedefine HAVE_PNG
|
||||
#cmakedefine HAVE_JPEG
|
||||
#cmakedefine HAVE_TIFF
|
||||
#cmakedefine HAVE_OPENEXR
|
||||
#cmakedefine HAVE_ZSTD
|
||||
#cmakedefine HAVE_LZ4
|
||||
|
||||
/// Platform
|
||||
#cmakedefine _UNIX_
|
||||
#cmakedefine _WIN_
|
||||
#cmakedefine _OSX_
|
||||
#cmakedefine _LINUX_
|
||||
#cmakedefine _ANDROID_
|
||||
#cmakedefine _IOS_
|
||||
|
||||
/// Compiler
|
||||
#cmakedefine _GCC_
|
||||
#cmakedefine _CLANG_
|
||||
#cmakedefine _MSVC_
|
||||
|
||||
#if (__cplusplus > 199711L) || (_MSC_VER >= 1800)
|
||||
#define CALLEE_HAS_VARIADIC_TEMPLATES
|
||||
#endif
|
||||
|
||||
#endif //PANGOLIN_CONFIG_H
|
||||
327
thirdparty/Pangolin/src/console/ConsoleView.cpp
vendored
Normal file
327
thirdparty/Pangolin/src/console/ConsoleView.cpp
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
#include <iterator>
|
||||
#include <pangolin/console/ConsoleView.h>
|
||||
#include <pangolin/utils/picojson.h>
|
||||
#include <pangolin/gl/gldraw.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
inline Colour ParseJson(const picojson::value& val)
|
||||
{
|
||||
return Colour(
|
||||
val.contains("r") ? val["r"].get<double>() : 0.0,
|
||||
val.contains("g") ? val["g"].get<double>() : 0.0,
|
||||
val.contains("b") ? val["b"].get<double>() : 0.0,
|
||||
val.contains("a") ? val["a"].get<double>() : 1.0
|
||||
);
|
||||
}
|
||||
|
||||
inline picojson::value toJson(const Colour& colour)
|
||||
{
|
||||
picojson::value ret(picojson::object_type,true);
|
||||
ret["r"] = colour.r;
|
||||
ret["g"] = colour.g;
|
||||
ret["b"] = colour.b;
|
||||
ret["a"] = colour.a;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Colour& colour)
|
||||
{
|
||||
os << toJson(colour).serialize();
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::istream& operator>>(std::istream& is, Colour& colour)
|
||||
{
|
||||
picojson::value val;
|
||||
picojson::parse(val,is);
|
||||
colour = ParseJson(val);
|
||||
return is;
|
||||
}
|
||||
|
||||
inline void glColour(const Colour& c)
|
||||
{
|
||||
glColor4f(c.r,c.g,c.b,c.a);
|
||||
}
|
||||
|
||||
ConsoleView::ConsoleView(ConsoleInterpreter* interpreter)
|
||||
: interpreter(interpreter),
|
||||
font(GlFont::I()),
|
||||
carat(0),
|
||||
hiding(false),
|
||||
bottom(1.0f),
|
||||
background_colour(0.2f, 0.0f, 0.0f, 0.6f),
|
||||
animation_speed(0.2)
|
||||
{
|
||||
SetHandler(this);
|
||||
|
||||
line_colours[ConsoleLineTypeCmd] = Colour(1.0f,1.0f,1.0f,1.0f);
|
||||
line_colours[ConsoleLineTypeCmdOptions] = Colour(0.9f,0.9f,0.9f,1.0f);
|
||||
line_colours[ConsoleLineTypeOutput] = Colour(0.0f,1.0f,1.0f,1.0f);
|
||||
line_colours[ConsoleLineTypeHelp] = Colour(1.0f,0.8f,1.0f,1.0f);
|
||||
line_colours[ConsoleLineTypeStdout] = Colour(0.0f,0.0f,1.0f,1.0f);
|
||||
line_colours[ConsoleLineTypeStderr] = Colour(1.0f,0.8f,0.8f,1.0f);
|
||||
|
||||
Var<Colour>::Attach("pangolin.console.colours.Background", background_colour);
|
||||
Var<Colour>::Attach("pangolin.console.colours.Cmd", line_colours[ConsoleLineTypeCmd]);
|
||||
Var<Colour>::Attach("pangolin.console.colours.CmdOptions", line_colours[ConsoleLineTypeCmdOptions]);
|
||||
Var<Colour>::Attach("pangolin.console.colours.Stdout", line_colours[ConsoleLineTypeStdout]);
|
||||
Var<Colour>::Attach("pangolin.console.colours.Stderr", line_colours[ConsoleLineTypeStderr]);
|
||||
Var<Colour>::Attach("pangolin.console.colours.Output", line_colours[ConsoleLineTypeOutput]);
|
||||
Var<Colour>::Attach("pangolin.console.colours.Help", line_colours[ConsoleLineTypeHelp]);
|
||||
|
||||
Var<float>::Attach("pango.console.animation_speed", animation_speed);
|
||||
|
||||
AddLine("Pangolin Python Command Prompt:", ConsoleLineTypeHelp);
|
||||
AddLine("===============================", ConsoleLineTypeHelp);
|
||||
}
|
||||
|
||||
ConsoleView::~ConsoleView() {
|
||||
delete interpreter;
|
||||
}
|
||||
|
||||
void ConsoleView::ProcessOutputLines()
|
||||
{
|
||||
// empty output queue
|
||||
ConsoleLine line_in;
|
||||
while(interpreter->PullLine(line_in))
|
||||
{
|
||||
AddLine(line_in.text, line_in.linetype);
|
||||
}
|
||||
}
|
||||
|
||||
View& ConsoleView::ShowWithoutAnimation(bool should_show){
|
||||
Show(should_show);
|
||||
bottom = show ? 1.0 : 0.0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
View& ConsoleView::Show(bool should_show)
|
||||
{
|
||||
if(should_show) {
|
||||
hiding = false;
|
||||
show = true;
|
||||
}else{
|
||||
hiding = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ConsoleView::ToggleShow()
|
||||
{
|
||||
Show(!IsShown());
|
||||
}
|
||||
|
||||
bool ConsoleView::IsShown() const
|
||||
{
|
||||
return show && !hiding;
|
||||
}
|
||||
|
||||
void ConsoleView::DrawLine(const ConsoleView::Line& l, int carat=-1)
|
||||
{
|
||||
glColour(line_colours[l.linetype]);
|
||||
l.text.Draw();
|
||||
if(carat >= 0) {
|
||||
const double w = font.Text(l.text.str.substr(0,carat)).Width();
|
||||
glDrawLine(w,-2,w,font.Height()-4);
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleView::Render()
|
||||
{
|
||||
if(hiding) {
|
||||
bottom += (1.0f - bottom) * animation_speed;
|
||||
if(1.0 - bottom < 0.01) {
|
||||
bottom = 1.0;
|
||||
show = false;
|
||||
hiding = false;
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
if(bottom > 0.01f) {
|
||||
bottom -= bottom*animation_speed;
|
||||
}else{
|
||||
bottom = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessOutputLines();
|
||||
|
||||
#ifndef HAVE_GLES
|
||||
glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT | GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
||||
#endif
|
||||
|
||||
this->ActivatePixelOrthographic();
|
||||
glDisable(GL_DEPTH_TEST );
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
glLineWidth(1.0);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc( GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
glColour(background_colour);
|
||||
|
||||
GLfloat verts[] = { 0.0f, (GLfloat)v.h,
|
||||
(GLfloat)v.w, (GLfloat)v.h,
|
||||
(GLfloat)v.w, bottom*v.h,
|
||||
0.0f, bottom*v.h };
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, verts);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
|
||||
const double line_space = font.Height();
|
||||
glTranslated(10.0, 10.0 + bottom*v.h, 0.0 );
|
||||
DrawLine(current_line, carat);
|
||||
glTranslated(0.0, line_space, 0.0);
|
||||
for(size_t l=0; l < line_buffer.size(); ++l) {
|
||||
DrawLine(line_buffer[l]);
|
||||
glTranslated(0.0, line_space, 0.0);
|
||||
}
|
||||
|
||||
#ifndef HAVE_GLES
|
||||
glPopAttrib();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline std::string CommonPrefix(const std::vector<std::string>& vec)
|
||||
{
|
||||
if(!vec.size()) return "";
|
||||
|
||||
size_t cmn = vec[0].size();
|
||||
for(size_t i=1; i<vec.size(); ++i) {
|
||||
cmn = std::min(vec[i].size(), cmn);
|
||||
for(size_t p=0; p < cmn; ++p) {
|
||||
if(vec[i][p] != vec[0][p]) {
|
||||
cmn = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vec[0].substr(0,cmn);
|
||||
}
|
||||
|
||||
void ConsoleView::Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed)
|
||||
{
|
||||
static int hist_id = -1;
|
||||
static std::string prefix;
|
||||
static bool edited = true;
|
||||
|
||||
if(pressed) {
|
||||
if(key=='\r') key = '\n';
|
||||
|
||||
GlText& txt = current_line.text;
|
||||
const std::string cmd = txt.Text();
|
||||
|
||||
if(key=='`') {
|
||||
ToggleShow();
|
||||
} else if(key=='\n') {
|
||||
interpreter->PushCommand(cmd);
|
||||
line_buffer.push_front(current_line);
|
||||
hist_id = -1;
|
||||
prefix = "";
|
||||
edited = true;
|
||||
carat = 0;
|
||||
txt.Clear();
|
||||
}else if(key=='\t') {
|
||||
std::vector<std::string> options = interpreter->Complete(cmd,100);
|
||||
if(options.size()) {
|
||||
const std::string common = CommonPrefix(options);
|
||||
if(common.size() > cmd.size()) {
|
||||
current_line = font.Text("%s", common.c_str());
|
||||
carat = common.size();
|
||||
}else{
|
||||
std::stringstream s;
|
||||
std::copy(options.begin(), options.end(), std::ostream_iterator<std::string>(s,", "));
|
||||
AddLine(s.str(), ConsoleLineTypeCmdOptions);
|
||||
}
|
||||
}
|
||||
}else if(key==PANGO_SPECIAL + PANGO_KEY_UP) {
|
||||
if(edited) {
|
||||
prefix = cmd;
|
||||
edited = false;
|
||||
}
|
||||
Line* hist_line = GetLine(hist_id+1, ConsoleLineTypeCmd, prefix);
|
||||
if(hist_line) {
|
||||
current_line = *hist_line;
|
||||
hist_id++;
|
||||
}
|
||||
}else if(key==PANGO_SPECIAL + PANGO_KEY_DOWN) {
|
||||
if(edited) {
|
||||
prefix = cmd;
|
||||
edited = false;
|
||||
}
|
||||
Line* hist_line = GetLine(hist_id-1, ConsoleLineTypeCmd, prefix);
|
||||
if(hist_line) {
|
||||
current_line = *hist_line;
|
||||
hist_id--;
|
||||
}
|
||||
}else if(key==PANGO_SPECIAL + PANGO_KEY_LEFT) {
|
||||
if(carat > 0) carat--;
|
||||
}else if(key==PANGO_SPECIAL + PANGO_KEY_RIGHT) {
|
||||
if(carat < (int)txt.str.size()) carat++;
|
||||
}else if(key==PANGO_SPECIAL + PANGO_KEY_HOME) {
|
||||
carat = 0;
|
||||
}else if(key==PANGO_SPECIAL + PANGO_KEY_END) {
|
||||
carat = txt.Text().size();
|
||||
}else if(key=='\b') {
|
||||
if(carat > 0) {
|
||||
std::string newstr = txt.Text();
|
||||
newstr.erase(newstr.begin()+carat-1);
|
||||
txt = font.Text("%s", newstr.c_str() );
|
||||
carat--;
|
||||
edited = true;
|
||||
}
|
||||
}else if(key==127) { // delete
|
||||
if(carat < (int)txt.Text().size() ) {
|
||||
std::string newstr = txt.Text();
|
||||
newstr.erase(newstr.begin()+carat);
|
||||
txt = font.Text("%s", newstr.c_str() );
|
||||
edited = true;
|
||||
}
|
||||
}else if(key==PANGO_CTRL + 'c') {
|
||||
txt = font.Text("");
|
||||
carat = 0;
|
||||
edited = true;
|
||||
}else if(key < PANGO_SPECIAL){
|
||||
std::string newstr = txt.Text();
|
||||
newstr.insert(carat, 1, key);
|
||||
txt = font.Text("%s", newstr.c_str());
|
||||
++carat;
|
||||
edited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleView::AddLine(const std::string& text, ConsoleLineType linetype )
|
||||
{
|
||||
line_buffer.push_front( Line( font.Text("%s",text.c_str()), linetype) );
|
||||
}
|
||||
|
||||
ConsoleView::Line* ConsoleView::GetLine(int id, ConsoleLineType line_type, const std::string& prefix )
|
||||
{
|
||||
int match = 0;
|
||||
for(Line& l : line_buffer)
|
||||
{
|
||||
if(l.linetype == line_type) {
|
||||
const std::string substr = l.text.Text().substr(0,prefix.size());
|
||||
if(substr == prefix ) {
|
||||
if(id == match) {
|
||||
return &l;
|
||||
}else{
|
||||
++match;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
95
thirdparty/Pangolin/src/display/device/PangolinNSApplication.mm
vendored
Normal file
95
thirdparty/Pangolin/src/display/device/PangolinNSApplication.mm
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
/* 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/platform.h>
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/device/PangolinNSApplication.h>
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
||||
# define NSAnyEventMask NSEventMaskAny
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// PangolinNSApplication
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation PangolinNSApplication
|
||||
|
||||
+ (void)run_pre
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:NSApplicationWillFinishLaunchingNotification
|
||||
object:NSApp];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:NSApplicationDidFinishLaunchingNotification
|
||||
object:NSApp];
|
||||
}
|
||||
|
||||
+ (void)run_step
|
||||
{
|
||||
NSEvent *event;
|
||||
do{
|
||||
event = [NSApp
|
||||
nextEventMatchingMask:NSAnyEventMask
|
||||
untilDate:nil
|
||||
// untilDate: [NSDate distantFuture]
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
[NSApp sendEvent:event];
|
||||
[NSApp updateWindows];
|
||||
}while(event != nil);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// PangolinWindowDelegate
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation PangolinWindowDelegate
|
||||
|
||||
- (BOOL)windowShouldClose:(id)sender {
|
||||
PANGOLIN_UNUSED(sender);
|
||||
|
||||
pangolin::Quit();
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// PangolinAppDelegate
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation PangolinAppDelegate
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
325
thirdparty/Pangolin/src/display/device/PangolinNSGLView.mm
vendored
Normal file
325
thirdparty/Pangolin/src/display/device/PangolinNSGLView.mm
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
#include <pangolin/platform.h>
|
||||
#include <pangolin/gl/glinclude.h>
|
||||
#include <pangolin/display/device/PangolinNSGLView.h>
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/display_internal.h>
|
||||
#include <pangolin/handler/handler_enums.h>
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
||||
# define NSDeviceIndependentModifierFlagsMask NSEventModifierFlagDeviceIndependentFlagsMask
|
||||
# define NSShiftKeyMask NSEventModifierFlagShift
|
||||
# define NSControlKeyMask NSEventModifierFlagControl
|
||||
# define NSAlternateKeyMask NSEventModifierFlagOption
|
||||
# define NSCommandKeyMask NSEventModifierFlagCommand
|
||||
# define NSFunctionKeyMask NSEventModifierFlagFunction
|
||||
#endif
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
extern __thread PangolinGl* context;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Input maps
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline
|
||||
int mapMouseButton(int osx_button )
|
||||
{
|
||||
const int map[] = {0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||
return map[osx_button];
|
||||
}
|
||||
|
||||
inline
|
||||
int mapKeymap(int osx_key)
|
||||
{
|
||||
if(osx_key == NSUpArrowFunctionKey)
|
||||
return pangolin::PANGO_SPECIAL + pangolin::PANGO_KEY_UP;
|
||||
else if(osx_key == NSDownArrowFunctionKey)
|
||||
return pangolin::PANGO_SPECIAL + pangolin::PANGO_KEY_DOWN;
|
||||
else if(osx_key == NSLeftArrowFunctionKey)
|
||||
return pangolin::PANGO_SPECIAL + pangolin::PANGO_KEY_LEFT;
|
||||
else if(osx_key == NSRightArrowFunctionKey)
|
||||
return pangolin::PANGO_SPECIAL + pangolin::PANGO_KEY_RIGHT;
|
||||
else if(osx_key == NSPageUpFunctionKey)
|
||||
return pangolin::PANGO_SPECIAL + pangolin::PANGO_KEY_PAGE_UP;
|
||||
else if(osx_key == NSPageDownFunctionKey)
|
||||
return pangolin::PANGO_SPECIAL + pangolin::PANGO_KEY_PAGE_DOWN;
|
||||
else if(osx_key == NSHomeFunctionKey)
|
||||
return pangolin::PANGO_SPECIAL + pangolin::PANGO_KEY_HOME;
|
||||
else if(osx_key == NSEndFunctionKey)
|
||||
return pangolin::PANGO_SPECIAL + pangolin::PANGO_KEY_END;
|
||||
else if(osx_key == NSInsertFunctionKey)
|
||||
return pangolin::PANGO_SPECIAL + pangolin::PANGO_KEY_INSERT;
|
||||
else if(osx_key == NSDeleteCharacter )
|
||||
return NSBackspaceCharacter;
|
||||
else if(osx_key == NSDeleteFunctionKey)
|
||||
return NSDeleteCharacter;
|
||||
else {
|
||||
return osx_key;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// PangolinNSGLView
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
@implementation PangolinNSGLView
|
||||
|
||||
-(id)initWithFrame:(NSRect)frameRect pixelFormat:(NSOpenGLPixelFormat *)format
|
||||
{
|
||||
self = [super initWithFrame:frameRect pixelFormat:format];
|
||||
context = pangolin::context;
|
||||
return(self);
|
||||
}
|
||||
|
||||
- (void)prepareOpenGL
|
||||
{
|
||||
[super prepareOpenGL];
|
||||
}
|
||||
|
||||
-(void)reshape
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||
if ( [self wantsBestResolutionOpenGLSurface] && [ self.window respondsToSelector:@selector(backingScaleFactor) ] )
|
||||
backing_scale = [self.window backingScaleFactor];
|
||||
else
|
||||
#endif
|
||||
backing_scale = 1.0;
|
||||
|
||||
pangolin::process::Resize(self.bounds.size.width * backing_scale, self.bounds.size.height * backing_scale);
|
||||
|
||||
[[self openGLContext] update];
|
||||
}
|
||||
|
||||
-(BOOL)acceptsFirstResponder
|
||||
{
|
||||
return(YES);
|
||||
}
|
||||
|
||||
-(BOOL)becomeFirstResponder
|
||||
{
|
||||
return(YES);
|
||||
}
|
||||
|
||||
-(BOOL)resignFirstResponder
|
||||
{
|
||||
return(YES);
|
||||
}
|
||||
|
||||
-(BOOL)isFlipped
|
||||
{
|
||||
return(YES);
|
||||
}
|
||||
|
||||
-(NSPoint)_Location:(NSEvent *)theEvent
|
||||
{
|
||||
NSPoint location = [self convertPoint: [theEvent locationInWindow] fromView: nil];
|
||||
location.x *= backing_scale;
|
||||
location.y *= backing_scale;
|
||||
return location;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Keyboard
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
-(void)keyDown:(NSEvent *)theEvent
|
||||
{
|
||||
const NSPoint location = [self _Location: theEvent];
|
||||
NSString *str = [theEvent characters];
|
||||
int len = (int)[str length];
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
const int osx_key = [str characterAtIndex:i];
|
||||
pangolin::process::Keyboard(mapKeymap(osx_key), location.x, location.y);
|
||||
}
|
||||
}
|
||||
|
||||
-(void)keyUp:(NSEvent *)theEvent
|
||||
{
|
||||
const NSPoint location = [self _Location: theEvent];
|
||||
NSString *str = [theEvent characters];
|
||||
int len = (int)[str length];
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
const int osx_key = [str characterAtIndex:i];
|
||||
pangolin::process::KeyboardUp(mapKeymap(osx_key), location.x, location.y);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)flagsChanged:(NSEvent *)event
|
||||
{
|
||||
unsigned int flags = [event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
|
||||
|
||||
if(flags&NSShiftKeyMask) {
|
||||
context->mouse_state |= pangolin::KeyModifierShift;
|
||||
}else{
|
||||
context->mouse_state &= ~pangolin::KeyModifierShift;
|
||||
}
|
||||
|
||||
if(flags&NSControlKeyMask) {
|
||||
context->mouse_state |= pangolin::KeyModifierCtrl;
|
||||
}else{
|
||||
context->mouse_state &= ~pangolin::KeyModifierCtrl;
|
||||
}
|
||||
|
||||
if(flags&NSAlternateKeyMask) {
|
||||
context->mouse_state |= pangolin::KeyModifierAlt;
|
||||
}else{
|
||||
context->mouse_state &= ~pangolin::KeyModifierAlt;
|
||||
}
|
||||
|
||||
if(flags&NSCommandKeyMask) {
|
||||
context->mouse_state |= pangolin::KeyModifierCmd;
|
||||
}else{
|
||||
context->mouse_state &= ~pangolin::KeyModifierCmd;
|
||||
}
|
||||
|
||||
if(flags&NSFunctionKeyMask) {
|
||||
context->mouse_state |= pangolin::KeyModifierFnc;
|
||||
}else{
|
||||
context->mouse_state &= ~pangolin::KeyModifierFnc;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Mouse Input
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
-(void)mouseDownCommon:(NSEvent *)theEvent
|
||||
{
|
||||
const int button = (int)[theEvent buttonNumber];
|
||||
const NSPoint location = [self _Location: theEvent];
|
||||
pangolin::process::Mouse(mapMouseButton(button), 0, location.x, location.y);
|
||||
}
|
||||
|
||||
-(void)mouseUpCommon:(NSEvent *)theEvent
|
||||
{
|
||||
const int button = (int)[theEvent buttonNumber];
|
||||
const NSPoint location = [self _Location: theEvent];
|
||||
pangolin::process::Mouse(mapMouseButton(button), 1, location.x, location.y);
|
||||
}
|
||||
|
||||
- (void)mouseDraggedCommon: (NSEvent *)theEvent
|
||||
{
|
||||
const NSPoint location = [self _Location: theEvent];
|
||||
pangolin::process::MouseMotion(location.x, location.y);
|
||||
// pangolin::process::SubpixMotion(location.x, location.y, 1.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
-(void)mouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseDownCommon:theEvent];
|
||||
}
|
||||
|
||||
-(void)mouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseUpCommon:theEvent];
|
||||
}
|
||||
|
||||
- (void)mouseDragged: (NSEvent *)theEvent
|
||||
{
|
||||
[self mouseDraggedCommon:theEvent];
|
||||
}
|
||||
|
||||
-(void)rightMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseDownCommon:theEvent];
|
||||
}
|
||||
|
||||
-(void)rightMouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseUpCommon:theEvent];
|
||||
}
|
||||
|
||||
- (void)rightMouseDragged: (NSEvent *)theEvent
|
||||
{
|
||||
[self mouseDraggedCommon:theEvent];
|
||||
}
|
||||
|
||||
-(void)otherMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseDownCommon:theEvent];
|
||||
}
|
||||
|
||||
-(void)otherMouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
[self mouseUpCommon:theEvent];
|
||||
}
|
||||
|
||||
- (void)otherMouseDragged: (NSEvent *)theEvent
|
||||
{
|
||||
[self mouseDraggedCommon:theEvent];
|
||||
}
|
||||
|
||||
- (void)mouseMoved: (NSEvent *)theEvent
|
||||
{
|
||||
const NSPoint location = [self _Location: theEvent];
|
||||
// pangolin::process::PassiveMouseMotion(location.x, location.y);
|
||||
pangolin::process::SubpixMotion(location.x, location.y, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
- (void)scrollWheel:(NSEvent *)theEvent
|
||||
{
|
||||
const NSPoint location = [self _Location: theEvent];
|
||||
|
||||
float dx, dy;
|
||||
if([theEvent respondsToSelector:@selector(scrollingDeltaX)]) {
|
||||
dx = theEvent.scrollingDeltaX; dy = theEvent.scrollingDeltaY;
|
||||
} else {
|
||||
dx = theEvent.deltaX; dy = theEvent.deltaY;
|
||||
}
|
||||
|
||||
if(dx != 0.0f || dy != 0.0f) {
|
||||
pangolin::process::SpecialInput(
|
||||
pangolin::InputSpecialScroll,
|
||||
location.x, context->base.v.h - location.y,
|
||||
dx, dy,
|
||||
0, 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)magnifyWithEvent: (NSEvent *)theEvent
|
||||
{
|
||||
const NSPoint location = [self _Location: theEvent];
|
||||
const float dm = theEvent.magnification;
|
||||
if(dm != 0.0f) {
|
||||
pangolin::process::SpecialInput(
|
||||
pangolin::InputSpecialZoom,
|
||||
location.x, context->base.v.h - location.y,
|
||||
dm, 0.0f, 0.0f, 0.0f
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)rotateWithEvent: (NSEvent *)theEvent
|
||||
{
|
||||
const NSPoint location = [self _Location: theEvent];
|
||||
const float dr = theEvent.rotation;
|
||||
if(dr != 0.0f) {
|
||||
pangolin::process::SpecialInput(
|
||||
pangolin::InputSpecialRotate,
|
||||
location.x, context->base.v.h - location.y,
|
||||
dr, 0.0f, 0.0f, 0.0f
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mouseEntered: (NSEvent *)theEvent
|
||||
{
|
||||
PANGOLIN_UNUSED(theEvent);
|
||||
}
|
||||
|
||||
- (void)mouseExited: (NSEvent *)theEvent
|
||||
{
|
||||
PANGOLIN_UNUSED(theEvent);
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
1026
thirdparty/Pangolin/src/display/device/display_android.cpp
vendored
Normal file
1026
thirdparty/Pangolin/src/display/device/display_android.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
166
thirdparty/Pangolin/src/display/device/display_headless.cpp
vendored
Executable file
166
thirdparty/Pangolin/src/display/device/display_headless.cpp
vendored
Executable file
@@ -0,0 +1,166 @@
|
||||
#include <pangolin/display/display_internal.h>
|
||||
#include <pangolin/factory/factory_registry.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
extern __thread PangolinGl* context;
|
||||
|
||||
namespace headless {
|
||||
|
||||
class EGLDisplayHL {
|
||||
public:
|
||||
EGLDisplayHL(const int width, const int height);
|
||||
|
||||
~EGLDisplayHL();
|
||||
|
||||
void swap();
|
||||
|
||||
void makeCurrent();
|
||||
|
||||
void removeCurrent();
|
||||
|
||||
private:
|
||||
EGLSurface egl_surface;
|
||||
EGLContext egl_context;
|
||||
EGLDisplay egl_display;
|
||||
|
||||
static constexpr EGLint attribs[] = {
|
||||
EGL_SURFACE_TYPE , EGL_PBUFFER_BIT,
|
||||
EGL_RENDERABLE_TYPE , EGL_OPENGL_BIT,
|
||||
EGL_RED_SIZE , 8,
|
||||
EGL_GREEN_SIZE , 8,
|
||||
EGL_BLUE_SIZE , 8,
|
||||
EGL_ALPHA_SIZE , 8,
|
||||
EGL_DEPTH_SIZE , 24,
|
||||
EGL_STENCIL_SIZE , 8,
|
||||
EGL_NONE
|
||||
};
|
||||
};
|
||||
|
||||
constexpr EGLint EGLDisplayHL::attribs[];
|
||||
|
||||
struct HeadlessWindow : public PangolinGl {
|
||||
HeadlessWindow(const int width, const int height);
|
||||
|
||||
~HeadlessWindow() override;
|
||||
|
||||
void ToggleFullscreen() override;
|
||||
|
||||
void Move(const int x, const int y) override;
|
||||
|
||||
void Resize(const unsigned int w, const unsigned int h) override;
|
||||
|
||||
void MakeCurrent() override;
|
||||
|
||||
void RemoveCurrent() override;
|
||||
|
||||
void SwapBuffers() override;
|
||||
|
||||
void ProcessEvents() override;
|
||||
|
||||
EGLDisplayHL display;
|
||||
};
|
||||
|
||||
EGLDisplayHL::EGLDisplayHL(const int width, const int height) {
|
||||
egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if(!egl_display) {
|
||||
std::cerr << "Failed to open EGL display" << std::endl;
|
||||
}
|
||||
|
||||
EGLint major, minor;
|
||||
if(eglInitialize(egl_display, &major, &minor)==EGL_FALSE) {
|
||||
std::cerr << "EGL init failed" << std::endl;
|
||||
}
|
||||
|
||||
if(eglBindAPI(EGL_OPENGL_API)==EGL_FALSE) {
|
||||
std::cerr << "EGL bind failed" << std::endl;
|
||||
}
|
||||
|
||||
EGLint count;
|
||||
eglGetConfigs(egl_display, nullptr, 0, &count);
|
||||
|
||||
std::vector<EGLConfig> egl_configs(count);
|
||||
|
||||
EGLint numConfigs;
|
||||
eglChooseConfig(egl_display, attribs, egl_configs.data(), count, &numConfigs);
|
||||
|
||||
egl_context = eglCreateContext(egl_display, egl_configs[0], EGL_NO_CONTEXT, nullptr);
|
||||
|
||||
const EGLint pbufferAttribs[] = {
|
||||
EGL_WIDTH, width,
|
||||
EGL_HEIGHT, height,
|
||||
EGL_NONE,
|
||||
};
|
||||
egl_surface = eglCreatePbufferSurface(egl_display, egl_configs[0], pbufferAttribs);
|
||||
if (egl_surface == EGL_NO_SURFACE) {
|
||||
std::cerr << "Cannot create EGL surface" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
EGLDisplayHL::~EGLDisplayHL() {
|
||||
if(egl_context) eglDestroyContext(egl_display, egl_context);
|
||||
if(egl_surface) eglDestroySurface(egl_display, egl_surface);
|
||||
if(egl_display) eglTerminate(egl_display);
|
||||
}
|
||||
|
||||
void EGLDisplayHL::swap() {
|
||||
eglSwapBuffers(egl_display, egl_surface);
|
||||
}
|
||||
|
||||
void EGLDisplayHL::makeCurrent() {
|
||||
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
|
||||
}
|
||||
|
||||
void EGLDisplayHL::removeCurrent() {
|
||||
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
HeadlessWindow::HeadlessWindow(const int w, const int h) : display(w, h) {
|
||||
windowed_size[0] = w;
|
||||
windowed_size[1] = h;
|
||||
}
|
||||
|
||||
HeadlessWindow::~HeadlessWindow() { }
|
||||
|
||||
void HeadlessWindow::MakeCurrent() {
|
||||
display.makeCurrent();
|
||||
context = this;
|
||||
}
|
||||
|
||||
void HeadlessWindow::RemoveCurrent() {
|
||||
display.removeCurrent();
|
||||
}
|
||||
|
||||
void HeadlessWindow::ToggleFullscreen() { }
|
||||
|
||||
void HeadlessWindow::Move(const int /*x*/, const int /*y*/) { }
|
||||
|
||||
void HeadlessWindow::Resize(const unsigned int /*w*/, const unsigned int /*h*/) { }
|
||||
|
||||
void HeadlessWindow::ProcessEvents() { }
|
||||
|
||||
void HeadlessWindow::SwapBuffers() {
|
||||
display.swap();
|
||||
MakeCurrent();
|
||||
}
|
||||
|
||||
} // namespace headless
|
||||
|
||||
PANGOLIN_REGISTER_FACTORY(NoneWindow) {
|
||||
struct HeadlessWindowFactory : public FactoryInterface<WindowInterface> {
|
||||
std::unique_ptr<WindowInterface> Open(const Uri& uri) override {
|
||||
return std::unique_ptr<WindowInterface>(new headless::HeadlessWindow(uri.Get<int>("w", 640), uri.Get<int>("h", 480)));
|
||||
}
|
||||
|
||||
virtual ~HeadlessWindowFactory() { }
|
||||
};
|
||||
|
||||
auto factory = std::make_shared<HeadlessWindowFactory>();
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 1, "none");
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 1, "nogui");
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 1, "headless");
|
||||
}
|
||||
|
||||
} // namespace pangolin
|
||||
|
||||
249
thirdparty/Pangolin/src/display/device/display_osx.mm
vendored
Normal file
249
thirdparty/Pangolin/src/display/device/display_osx.mm
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) 2011-2018 Steven Lovegrove, Andrey Mnatsakanov
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Silence all the OSX GL deprecation messages.
|
||||
#define GL_SILENCE_DEPRECATION
|
||||
|
||||
#include <pangolin/factory/factory_registry.h>
|
||||
#include <pangolin/platform.h>
|
||||
#include <pangolin/gl/glinclude.h>
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/display_internal.h>
|
||||
#include <pangolin/display/device/OsxWindow.h>
|
||||
#include <pangolin/display/device/PangolinNSGLView.h>
|
||||
#include <pangolin/display/device/PangolinNSApplication.h>
|
||||
#include <memory>
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
||||
# define NSFullScreenWindowMask NSWindowStyleMaskFullScreen
|
||||
# define NSTitledWindowMask NSWindowStyleMaskTitled
|
||||
# define NSMiniaturizableWindowMask NSWindowStyleMaskMiniaturizable
|
||||
# define NSResizableWindowMask NSWindowStyleMaskResizable
|
||||
# define NSClosableWindowMask NSWindowStyleMaskClosable
|
||||
#endif
|
||||
|
||||
// Hack to fix window focus issue
|
||||
// http://www.miscdebris.net/blog/2010/03/30/solution-for-my-mac-os-x-gui-program-doesnt-get-focus-if-its-outside-an-application-bundle/
|
||||
extern "C" { void CPSEnableForegroundOperation(ProcessSerialNumber* psn); }
|
||||
inline void FixOsxFocus()
|
||||
{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
ProcessSerialNumber psn;
|
||||
GetCurrentProcess( &psn );
|
||||
CPSEnableForegroundOperation( &psn );
|
||||
SetFrontProcess( &psn );
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
extern __thread PangolinGl* context;
|
||||
|
||||
std::unique_ptr<WindowInterface> CreateOsxWindowAndBind(std::string window_title, int w, int h, const bool is_highres)
|
||||
{
|
||||
|
||||
OsxWindow* win = new OsxWindow(window_title, w, h, is_highres);
|
||||
|
||||
return std::unique_ptr<WindowInterface>(win);
|
||||
}
|
||||
|
||||
OsxWindow::OsxWindow(
|
||||
const std::string& title, int width, int height, bool USE_RETINA
|
||||
) {
|
||||
context = this;
|
||||
|
||||
PangolinGl::is_double_buffered = true;
|
||||
PangolinGl::windowed_size[0] = width;
|
||||
PangolinGl::windowed_size[1] = height;
|
||||
|
||||
// // These are important I think!
|
||||
// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
// [pool release];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Make sure Application is initialised correctly.
|
||||
// This can be run repeatedly.
|
||||
|
||||
[NSApplication sharedApplication];
|
||||
PangolinAppDelegate *delegate = [[PangolinAppDelegate alloc] init];
|
||||
|
||||
[NSApp setDelegate:delegate];
|
||||
[NSApp setPresentationOptions:NSFullScreenWindowMask];
|
||||
|
||||
[PangolinNSApplication run_pre];
|
||||
[PangolinNSApplication run_step];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Create Window
|
||||
|
||||
NSRect viewRect = NSMakeRect( 0.0, 0.0, width, height );
|
||||
|
||||
_window = [[NSWindow alloc] initWithContentRect:viewRect styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask|NSClosableWindowMask backing:NSBackingStoreBuffered defer:YES];
|
||||
[_window setTitle:[NSString stringWithUTF8String:title.c_str()]];
|
||||
[_window setOpaque:YES];
|
||||
[_window makeKeyAndOrderFront:NSApp];
|
||||
[_window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
|
||||
|
||||
PangolinWindowDelegate *windelegate = [[PangolinWindowDelegate alloc] init];
|
||||
[_window setDelegate:windelegate];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Setup Menu
|
||||
|
||||
// NSMenu *mainMenuBar;
|
||||
// NSMenu *appMenu;
|
||||
// NSMenuItem *menuItem;
|
||||
|
||||
// mainMenuBar = [[NSMenu alloc] init];
|
||||
|
||||
// appMenu = [[NSMenu alloc] initWithTitle:@"Pangolin Application"];
|
||||
// menuItem = [appMenu addItemWithTitle:@"Quit Pangolin Application" action:@selector(terminate:) keyEquivalent:@"q"];
|
||||
// [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
|
||||
|
||||
// menuItem = [[NSMenuItem alloc] init];
|
||||
// [menuItem setSubmenu:appMenu];
|
||||
|
||||
// [mainMenuBar addItem:menuItem];
|
||||
|
||||
// //[NSApp performSelector:@selector(setAppleMenu:) withObject:appMenu];
|
||||
// [appMenu release];
|
||||
// [NSApp setMainMenu:mainMenuBar];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Create OpenGL View for Window
|
||||
|
||||
NSOpenGLPixelFormatAttribute attrs[] =
|
||||
{
|
||||
NSOpenGLPFADoubleBuffer,
|
||||
NSOpenGLPFADepthSize, 32,
|
||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
|
||||
0
|
||||
};
|
||||
|
||||
NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
|
||||
view = [[PangolinNSGLView alloc] initWithFrame:_window.frame pixelFormat:format];
|
||||
[format release];
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
||||
if( USE_RETINA && floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
|
||||
[view setWantsBestResolutionOpenGLSurface:YES];
|
||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||
|
||||
[_window setContentView:view];
|
||||
|
||||
[PangolinNSApplication run_step];
|
||||
|
||||
glewInit();
|
||||
|
||||
FixOsxFocus();
|
||||
}
|
||||
|
||||
OsxWindow::~OsxWindow()
|
||||
{
|
||||
// Not sure how to deallocate...
|
||||
}
|
||||
|
||||
void OsxWindow::StartFullScreen()
|
||||
{
|
||||
if(!is_fullscreen) {
|
||||
[_window toggleFullScreen:nil];
|
||||
is_fullscreen = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OsxWindow::StopFullScreen()
|
||||
{
|
||||
if(is_fullscreen) {
|
||||
[_window toggleFullScreen:nil];
|
||||
is_fullscreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
void OsxWindow::ToggleFullscreen()
|
||||
{
|
||||
[_window toggleFullScreen:nil];
|
||||
PangolinGl::is_fullscreen = !PangolinGl::is_fullscreen;
|
||||
}
|
||||
|
||||
void OsxWindow::Move(int x, int y)
|
||||
{
|
||||
[_window setFrame:CGRectMake(x, y, [_window frame].size.width,
|
||||
[_window frame].size.height) display:NO];
|
||||
}
|
||||
|
||||
void OsxWindow::Resize(unsigned int w, unsigned int h)
|
||||
{
|
||||
[_window setFrame:CGRectMake([_window frame].origin.x,
|
||||
[_window frame].origin.y, w, h) display:NO];
|
||||
}
|
||||
|
||||
void OsxWindow::MakeCurrent()
|
||||
{
|
||||
[[view openGLContext] makeCurrentContext];
|
||||
context = this;
|
||||
}
|
||||
|
||||
void OsxWindow::RemoveCurrent()
|
||||
{
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
|
||||
void OsxWindow::SwapBuffers()
|
||||
{
|
||||
[[view openGLContext] flushBuffer];
|
||||
// [[view openGLContext] update];
|
||||
// [view setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
void OsxWindow::ProcessEvents()
|
||||
{
|
||||
[PangolinNSApplication run_step];
|
||||
}
|
||||
|
||||
PANGOLIN_REGISTER_FACTORY(OsxWindow)
|
||||
{
|
||||
struct OsxWindowFactory : public FactoryInterface<WindowInterface> {
|
||||
std::unique_ptr<WindowInterface> Open(const Uri& uri) override {
|
||||
|
||||
const std::string window_title = uri.Get<std::string>("window_title", "window");
|
||||
const int w = uri.Get<int>("w", 640);
|
||||
const int h = uri.Get<int>("h", 480);
|
||||
const bool is_highres = uri.Get<bool>(PARAM_HIGHRES, false);
|
||||
return std::unique_ptr<WindowInterface>(CreateOsxWindowAndBind(window_title, w, h, is_highres));
|
||||
}
|
||||
};
|
||||
|
||||
auto factory = std::make_shared<OsxWindowFactory>();
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 10, "cocoa");
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 100, "default");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
1048
thirdparty/Pangolin/src/display/device/display_wayland.cpp
vendored
Executable file
1048
thirdparty/Pangolin/src/display/device/display_wayland.cpp
vendored
Executable file
File diff suppressed because it is too large
Load Diff
599
thirdparty/Pangolin/src/display/device/display_win.cpp
vendored
Normal file
599
thirdparty/Pangolin/src/display/device/display_win.cpp
vendored
Normal file
@@ -0,0 +1,599 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) 2011-2018 Steven Lovegrove, Andrey Mnatsakanov
|
||||
*
|
||||
* 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/factory/factory_registry.h>
|
||||
#include <pangolin/platform.h>
|
||||
#include <pangolin/gl/glinclude.h>
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/display_internal.h>
|
||||
|
||||
#include <pangolin/display/device/WinWindow.h>
|
||||
#include <memory>
|
||||
|
||||
#define CheckWGLDieOnError() pangolin::_CheckWLDieOnError( __FILE__, __LINE__ );
|
||||
namespace pangolin {
|
||||
inline void _CheckWLDieOnError( const char *sFile, const int nLine )
|
||||
{
|
||||
DWORD errorCode = GetLastError();
|
||||
if(errorCode!=0) {
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf, 0, NULL);
|
||||
// MessageBox( NULL, (LPCTSTR)lpMsgBuf, ("Error "+std::to_string(errorCode)).c_str(), MB_OK | MB_ICONINFORMATION );
|
||||
pango_print_error("Error %i: %s", errorCode, (char *)lpMsgBuf);
|
||||
pango_print_error("In: %s, line %d\n", sFile, nLine);
|
||||
// exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
const char *className = "Pangolin";
|
||||
|
||||
extern __thread PangolinGl* context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
unsigned char GetPangoKey(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (wParam)
|
||||
{
|
||||
case VK_F1: return PANGO_SPECIAL + PANGO_KEY_F1;
|
||||
case VK_F2: return PANGO_SPECIAL + PANGO_KEY_F2;
|
||||
case VK_F3: return PANGO_SPECIAL + PANGO_KEY_F3;
|
||||
case VK_F4: return PANGO_SPECIAL + PANGO_KEY_F4;
|
||||
case VK_F5: return PANGO_SPECIAL + PANGO_KEY_F5;
|
||||
case VK_F6: return PANGO_SPECIAL + PANGO_KEY_F6;
|
||||
case VK_F7: return PANGO_SPECIAL + PANGO_KEY_F7;
|
||||
case VK_F8: return PANGO_SPECIAL + PANGO_KEY_F8;
|
||||
case VK_F9: return PANGO_SPECIAL + PANGO_KEY_F9;
|
||||
case VK_F10: return PANGO_SPECIAL + PANGO_KEY_F10;
|
||||
case VK_F11: return PANGO_SPECIAL + PANGO_KEY_F11;
|
||||
case VK_F12: return PANGO_SPECIAL + PANGO_KEY_F12;
|
||||
case VK_LEFT: return PANGO_SPECIAL + PANGO_KEY_LEFT;
|
||||
case VK_UP: return PANGO_SPECIAL + PANGO_KEY_UP;
|
||||
case VK_RIGHT: return PANGO_SPECIAL + PANGO_KEY_RIGHT;
|
||||
case VK_DOWN: return PANGO_SPECIAL + PANGO_KEY_DOWN;
|
||||
case VK_HOME: return PANGO_SPECIAL + PANGO_KEY_HOME;
|
||||
case VK_END: return PANGO_SPECIAL + PANGO_KEY_END;
|
||||
case VK_INSERT: return PANGO_SPECIAL + PANGO_KEY_INSERT;
|
||||
case VK_DELETE: return 127;
|
||||
default:
|
||||
const int lBufferSize = 2;
|
||||
WCHAR lBuffer[lBufferSize];
|
||||
|
||||
BYTE State[256];
|
||||
GetKeyboardState(State);
|
||||
|
||||
const UINT scanCode = (lParam >> 8) & 0xFFFFFF00;
|
||||
if( ToUnicode((UINT)wParam, scanCode, State, lBuffer, lBufferSize, 0) >=1 ) {
|
||||
return (unsigned char)lBuffer[0];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetMouseModifierKey(WPARAM wParam)
|
||||
{
|
||||
//maps windows key modifier to glutGetModifiers values
|
||||
int gluKeyModVal = 0;
|
||||
if (wParam & MK_SHIFT) gluKeyModVal += 1;
|
||||
if (wParam & MK_CONTROL) gluKeyModVal += 2;
|
||||
if (HIBYTE(GetKeyState(VK_MENU))) gluKeyModVal += 4;
|
||||
return gluKeyModVal << 4;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// WinWindow Implementation
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void WinWindow::SetupPixelFormat(HDC hDC)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd = {
|
||||
sizeof(PIXELFORMATDESCRIPTOR), /* size */
|
||||
1, /* version */
|
||||
PFD_SUPPORT_OPENGL |
|
||||
PFD_DRAW_TO_WINDOW |
|
||||
PFD_DOUBLEBUFFER, /* support double-buffering */
|
||||
PFD_TYPE_RGBA, /* color type */
|
||||
24, /* prefered color depth */
|
||||
0, 0, 0, 0, 0, 0, /* color bits (ignored) */
|
||||
8, /* alpha bits */
|
||||
0, /* alpha shift (ignored) */
|
||||
0, /* no accumulation buffer */
|
||||
0, 0, 0, 0, /* accum bits (ignored) */
|
||||
32, /* depth buffer */
|
||||
0, /* no stencil buffer */
|
||||
0, /* no auxiliary buffers */
|
||||
PFD_MAIN_PLANE, /* main layer */
|
||||
0, /* reserved */
|
||||
0, 0, 0, /* no layer, visible, damage masks */
|
||||
};
|
||||
int pixelFormat;
|
||||
|
||||
pixelFormat = ChoosePixelFormat(hDC, &pfd);
|
||||
if (pixelFormat == 0) {
|
||||
MessageBoxA(WindowFromDC(hDC), "ChoosePixelFormat failed.", "Error", MB_ICONERROR | MB_OK);
|
||||
CheckWGLDieOnError();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) {
|
||||
MessageBoxA(WindowFromDC(hDC), "SetPixelFormat failed.", "Error", MB_ICONERROR | MB_OK);
|
||||
CheckWGLDieOnError();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void WinWindow::SetupPalette(HDC hDC)
|
||||
{
|
||||
int pixelFormat = GetPixelFormat(hDC);
|
||||
if(!pixelFormat) {
|
||||
std::cerr << "GetPixelFormat() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
LOGPALETTE* pPal;
|
||||
int paletteSize;
|
||||
|
||||
if(!DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) {
|
||||
std::cerr << "DescribePixelFormat() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
|
||||
if (pfd.dwFlags & PFD_NEED_PALETTE) {
|
||||
paletteSize = 1 << pfd.cColorBits;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
pPal = (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
|
||||
pPal->palVersion = 0x300;
|
||||
pPal->palNumEntries = paletteSize;
|
||||
|
||||
/* build a simple RGB color palette */
|
||||
{
|
||||
int redMask = (1 << pfd.cRedBits) - 1;
|
||||
int greenMask = (1 << pfd.cGreenBits) - 1;
|
||||
int blueMask = (1 << pfd.cBlueBits) - 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i<paletteSize; ++i) {
|
||||
pPal->palPalEntry[i].peRed =
|
||||
(((i >> pfd.cRedShift) & redMask) * 255) / redMask;
|
||||
pPal->palPalEntry[i].peGreen =
|
||||
(((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask;
|
||||
pPal->palPalEntry[i].peBlue =
|
||||
(((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask;
|
||||
pPal->palPalEntry[i].peFlags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
hPalette = CreatePalette(pPal);
|
||||
free(pPal);
|
||||
|
||||
if (hPalette) {
|
||||
SelectPalette(hDC, hPalette, FALSE);
|
||||
RealizePalette(hDC);
|
||||
}
|
||||
else {
|
||||
std::cerr << "CreatePalette() failed" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
WinWindow::WinWindow(
|
||||
const std::string& window_title, int width, int height
|
||||
) : hWnd(0)
|
||||
{
|
||||
const HMODULE hCurrentInst = GetModuleHandleA(nullptr);
|
||||
if(hCurrentInst==NULL) {
|
||||
std::cerr << "GetModuleHandle() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
RegisterThisClass(hCurrentInst);
|
||||
|
||||
HWND thishwnd = CreateWindowA(
|
||||
className, window_title.c_str(),
|
||||
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
||||
0, 0, width, height,
|
||||
NULL, NULL, hCurrentInst, this);
|
||||
if(thishwnd==NULL) {
|
||||
std::cerr << "CreateWindow() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
|
||||
if( thishwnd != hWnd ) {
|
||||
throw std::runtime_error("Pangolin Window Creation Failed.");
|
||||
}
|
||||
|
||||
// Gets the size of the window, excluding the top bar
|
||||
RECT cRect;
|
||||
GetClientRect(thishwnd, &cRect);
|
||||
|
||||
PangolinGl::windowed_size[0] = cRect.right;
|
||||
PangolinGl::windowed_size[1] = cRect.bottom;
|
||||
|
||||
// Display Window
|
||||
ShowWindow(hWnd, SW_SHOW);
|
||||
PangolinGl::is_double_buffered = true;
|
||||
}
|
||||
|
||||
WinWindow::~WinWindow()
|
||||
{
|
||||
if(!DestroyWindow(hWnd)) {
|
||||
std::cerr << "DestroyWindow() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
}
|
||||
|
||||
void WinWindow::RegisterThisClass(HMODULE hCurrentInst)
|
||||
{
|
||||
WNDCLASSA wndClass;
|
||||
wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
|
||||
wndClass.lpfnWndProc = WinWindow::WndProc;
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = 0;
|
||||
wndClass.hInstance = hCurrentInst;
|
||||
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
wndClass.lpszMenuName = NULL;
|
||||
wndClass.lpszClassName = className;
|
||||
if(!RegisterClassA(&wndClass)) {
|
||||
std::cerr << "RegisterClass() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT APIENTRY
|
||||
WinWindow::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
WinWindow* self = 0;
|
||||
|
||||
if (uMsg == WM_NCCREATE) {
|
||||
auto lpcs = reinterpret_cast<LPCREATESTRUCTA>(lParam);
|
||||
self = reinterpret_cast<WinWindow*>(lpcs->lpCreateParams);
|
||||
if(self) {
|
||||
self->hWnd = hwnd;
|
||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(self));
|
||||
}
|
||||
} else {
|
||||
self = reinterpret_cast<WinWindow*>(GetWindowLongPtrA(hwnd, GWLP_USERDATA));
|
||||
}
|
||||
|
||||
if (self) {
|
||||
return self->HandleWinMessages(uMsg, wParam, lParam);
|
||||
} else {
|
||||
return DefWindowProcA(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT WinWindow::HandleWinMessages(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message) {
|
||||
case WM_CREATE:
|
||||
/* initialize OpenGL rendering */
|
||||
hDC = GetDC(hWnd);
|
||||
if(hDC==NULL) {
|
||||
std::cerr << "WM_CREATE GetDC() failed" << std::endl;
|
||||
}
|
||||
SetupPixelFormat(hDC);
|
||||
SetupPalette(hDC);
|
||||
hGLRC = wglCreateContext(hDC);
|
||||
if(!hGLRC) {
|
||||
std::cerr << "WM_CREATE wglCreateContext() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
if(!wglMakeCurrent(hDC, hGLRC)) {
|
||||
std::cerr << "WM_CREATE wglMakeCurrent() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
return 0;
|
||||
case WM_DESTROY:
|
||||
/* finish OpenGL rendering */
|
||||
if (hGLRC) {
|
||||
if(!wglMakeCurrent(NULL, NULL)) {
|
||||
std::cerr << "WM_DESTROY wglMakeCurrent() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
if(!wglDeleteContext(hGLRC)) {
|
||||
std::cerr << "WM_DESTROY wglDeleteContext() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
}
|
||||
if (hPalette) {
|
||||
DeleteObject(hPalette);
|
||||
}
|
||||
ReleaseDC(hWnd, hDC);
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
case WM_SIZE:
|
||||
/* track window size changes */
|
||||
if (context == this) {
|
||||
process::Resize((int)LOWORD(lParam), (int)HIWORD(lParam));
|
||||
}
|
||||
return 0;
|
||||
case WM_PALETTECHANGED:
|
||||
/* realize palette if this is *not* the current window */
|
||||
if (hGLRC && hPalette && (HWND)wParam != hWnd) {
|
||||
if(!UnrealizeObject(hPalette)) {
|
||||
std::cerr << "WM_PALETTECHANGED UnrealizeObject() failed" << std::endl;
|
||||
}
|
||||
if(!SelectPalette(hDC, hPalette, FALSE)) {
|
||||
std::cerr << "WM_PALETTECHANGED SelectPalette() failed" << std::endl;
|
||||
}
|
||||
if(RealizePalette(hDC)==GDI_ERROR) {
|
||||
std::cerr << "WM_PALETTECHANGED RealizePalette() failed" << std::endl;
|
||||
}
|
||||
//redraw();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_QUERYNEWPALETTE:
|
||||
/* realize palette if this is the current window */
|
||||
if (hGLRC && hPalette) {
|
||||
if(!UnrealizeObject(hPalette)) {
|
||||
std::cerr << "WM_QUERYNEWPALETTE UnrealizeObject() failed" << std::endl;
|
||||
}
|
||||
if(!SelectPalette(hDC, hPalette, FALSE)) {
|
||||
std::cerr << "WM_QUERYNEWPALETTE SelectPalette() failed" << std::endl;
|
||||
}
|
||||
if(RealizePalette(hDC)==GDI_ERROR) {
|
||||
std::cerr << "WM_QUERYNEWPALETTE RealizePalette() failed" << std::endl;
|
||||
}
|
||||
//redraw();
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case WM_PAINT:
|
||||
{
|
||||
//PAINTSTRUCT ps;
|
||||
//BeginPaint(hWnd, &ps);
|
||||
//if (hGLRC) {
|
||||
// redraw();
|
||||
//}
|
||||
//EndPaint(hWnd, &ps);
|
||||
//return 0;
|
||||
}
|
||||
break;
|
||||
case WM_KEYDOWN:
|
||||
{
|
||||
unsigned char key = GetPangoKey(wParam, lParam);
|
||||
if(key>0) process::Keyboard(key, 1, 1);
|
||||
return 0;
|
||||
}
|
||||
case WM_KEYUP:
|
||||
{
|
||||
unsigned char key = GetPangoKey(wParam, lParam);
|
||||
if (key>0) process::KeyboardUp(key, 1, 1);
|
||||
return 0;
|
||||
}
|
||||
case WM_LBUTTONDOWN:
|
||||
process::Mouse(0 | GetMouseModifierKey(wParam), 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
return 0;
|
||||
case WM_MBUTTONDOWN:
|
||||
process::Mouse(1 | GetMouseModifierKey(wParam), 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
return 0;
|
||||
case WM_RBUTTONDOWN:
|
||||
process::Mouse(2 | GetMouseModifierKey(wParam), 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
return 0;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
process::Mouse(0 | GetMouseModifierKey(wParam), 1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
return 0;
|
||||
case WM_MBUTTONUP:
|
||||
process::Mouse(1 | GetMouseModifierKey(wParam), 1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
return 0;
|
||||
case WM_RBUTTONUP:
|
||||
process::Mouse(2 | GetMouseModifierKey(wParam), 1, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
return 0;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
if (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) ) {
|
||||
process::MouseMotion(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
} else{
|
||||
process::PassiveMouseMotion(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
||||
}
|
||||
return 0;
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
process::Scroll(0.0f, GET_WHEEL_DELTA_WPARAM(wParam) / 5.0f );
|
||||
return 0;
|
||||
case WM_MOUSEHWHEEL:
|
||||
process::Scroll(GET_WHEEL_DELTA_WPARAM(wParam) / 5.0f, 0.0f);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return DefWindowProcA(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
void WinWindow::StartFullScreen() {
|
||||
LONG dwExStyle = GetWindowLongA(hWnd, GWL_EXSTYLE)
|
||||
& ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE);
|
||||
if(dwExStyle==0) {
|
||||
std::cerr << "GetWindowLongA() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
LONG dwStyle = GetWindowLongA(hWnd, GWL_STYLE)
|
||||
& ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU);
|
||||
if(dwStyle==0) {
|
||||
std::cerr << "GetWindowLongA() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
|
||||
if(!SetWindowLongA(hWnd, GWL_EXSTYLE, dwExStyle)) {
|
||||
std::cerr << "SetWindowLongA() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
if(!SetWindowLongA(hWnd, GWL_STYLE, dwStyle)) {
|
||||
std::cerr << "SetWindowLongA() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
|
||||
GLint prev[2];
|
||||
std::memcpy(prev, context->windowed_size, sizeof(prev));
|
||||
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
|
||||
std::memcpy(context->windowed_size, prev, sizeof(prev));
|
||||
}
|
||||
|
||||
void WinWindow::StopFullScreen() {
|
||||
ChangeDisplaySettings(NULL, 0);
|
||||
ShowCursor(TRUE);
|
||||
|
||||
LONG dwExStyle = GetWindowLongA(hWnd, GWL_EXSTYLE) | WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||
LONG dwStyle = GetWindowLongA(hWnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW;
|
||||
|
||||
if(dwExStyle==0) {
|
||||
std::cerr << "GetWindowLongA() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
if(dwStyle==0) {
|
||||
std::cerr << "GetWindowLongA() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
|
||||
if(!SetWindowLongA(hWnd, GWL_EXSTYLE, dwExStyle)) {
|
||||
std::cerr << "SetWindowLongA() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
if(!SetWindowLongA(hWnd, GWL_STYLE, dwStyle)) {
|
||||
std::cerr << "SetWindowLongA() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
|
||||
if(!SetWindowPos(hWnd, HWND_TOP, 0, 0, context->windowed_size[0], context->windowed_size[1], SWP_FRAMECHANGED)) {
|
||||
std::cerr << "SetWindowPos() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
}
|
||||
|
||||
void WinWindow::ToggleFullscreen()
|
||||
{
|
||||
if(!context->is_fullscreen) {
|
||||
StartFullScreen();
|
||||
context->is_fullscreen = true;
|
||||
}else{
|
||||
StopFullScreen();
|
||||
context->is_fullscreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
void WinWindow::Move(int x, int y)
|
||||
{
|
||||
if( !SetWindowPos(hWnd, 0, x, y, 0, 0, SWP_NOSIZE) ) {
|
||||
std::cerr << "WinWindow::Move failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
}
|
||||
|
||||
void WinWindow::Resize(unsigned int w, unsigned int h)
|
||||
{
|
||||
if( !SetWindowPos(hWnd, 0, 0, 0, w, h, SWP_NOMOVE) ) {
|
||||
std::cerr << "WinWindow::Resize failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
}
|
||||
|
||||
void WinWindow::MakeCurrent()
|
||||
{
|
||||
if(wglMakeCurrent(hDC, hGLRC)==FALSE) {
|
||||
std::cerr << "wglMakeCurrent() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
|
||||
// Setup threadlocal context as this
|
||||
context = this;
|
||||
|
||||
RECT rect;
|
||||
if(!GetWindowRect(hWnd, &rect)) {
|
||||
std::cerr << "GetWindowRect() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
Resize(rect.right - rect.left, rect.bottom - rect.top);
|
||||
}
|
||||
|
||||
void WinWindow::RemoveCurrent()
|
||||
{
|
||||
if(wglMakeCurrent(NULL, NULL)==0) {
|
||||
std::cerr << "wglMakeCurrent() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
}
|
||||
|
||||
void WinWindow::SwapBuffers()
|
||||
{
|
||||
if(!::SwapBuffers(hDC)) {
|
||||
std::cerr << "SwapBuffers() failed" << std::endl;
|
||||
CheckWGLDieOnError();
|
||||
}
|
||||
}
|
||||
|
||||
void WinWindow::ProcessEvents()
|
||||
{
|
||||
MSG msg;
|
||||
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT) {
|
||||
pangolin::Quit();
|
||||
break;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageA(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<WindowInterface> CreateWinWindowAndBind(std::string window_title, int w, int h)
|
||||
{
|
||||
WinWindow* win = new WinWindow(window_title, w, h);
|
||||
|
||||
return std::unique_ptr<WindowInterface>(win);
|
||||
}
|
||||
|
||||
PANGOLIN_REGISTER_FACTORY(WinWindow)
|
||||
{
|
||||
struct WinWindowFactory : public FactoryInterface<WindowInterface> {
|
||||
std::unique_ptr<WindowInterface> Open(const Uri& uri) override {
|
||||
|
||||
const std::string window_title = uri.Get<std::string>("window_title", "window");
|
||||
const int w = uri.Get<int>("w", 640);
|
||||
const int h = uri.Get<int>("h", 480);
|
||||
return std::unique_ptr<WindowInterface>(CreateWinWindowAndBind(window_title, w, h));
|
||||
}
|
||||
};
|
||||
|
||||
auto factory = std::make_shared<WinWindowFactory>();
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 10, "winapi");
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 100, "default");
|
||||
}
|
||||
|
||||
}
|
||||
530
thirdparty/Pangolin/src/display/device/display_x11.cpp
vendored
Normal file
530
thirdparty/Pangolin/src/display/device/display_x11.cpp
vendored
Normal file
@@ -0,0 +1,530 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) 2011-2018 Steven Lovegrove, Andrey Mnatsakanov
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
// Code based on public domain sample at
|
||||
// https://www.opengl.org/wiki/Tutorial:_OpenGL_3.0_Context_Creation_%28GLX%29
|
||||
|
||||
#include <pangolin/factory/factory_registry.h>
|
||||
#include <pangolin/platform.h>
|
||||
#include <pangolin/gl/glinclude.h>
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/display_internal.h>
|
||||
#include <pangolin/display/window.h>
|
||||
|
||||
#include <pangolin/display/device/X11Window.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <GL/glx.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
extern __thread PangolinGl* context;
|
||||
|
||||
std::mutex window_mutex;
|
||||
std::weak_ptr<X11GlContext> global_gl_context;
|
||||
|
||||
const long EVENT_MASKS = ButtonPressMask|ButtonReleaseMask|StructureNotifyMask|ButtonMotionMask|PointerMotionMask|KeyPressMask|KeyReleaseMask|FocusChangeMask;
|
||||
|
||||
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
typedef GLXContext (*glXCreateContextAttribsARBProc)(::Display*, ::GLXFBConfig, ::GLXContext, Bool, const int*);
|
||||
|
||||
// Adapted from: http://www.opengl.org/resources/features/OGLextensions/
|
||||
bool isExtensionSupported(const char *extList, const char *extension)
|
||||
{
|
||||
/* Extension names should not have spaces. */
|
||||
const char* where = strchr(extension, ' ');
|
||||
if (where || *extension == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(const char* start=extList;;) {
|
||||
where = strstr(start, extension);
|
||||
if (!where) {
|
||||
break;
|
||||
}
|
||||
|
||||
const char *terminator = where + strlen(extension);
|
||||
|
||||
if ( where == start || *(where - 1) == ' ' ) {
|
||||
if ( *terminator == ' ' || *terminator == '\0' ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
start = terminator;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
::GLXFBConfig ChooseFrameBuffer(
|
||||
::Display *display, bool glx_doublebuffer,
|
||||
int glx_sample_buffers, int glx_samples
|
||||
) {
|
||||
// Desired attributes
|
||||
int visual_attribs[] =
|
||||
{
|
||||
GLX_X_RENDERABLE , True,
|
||||
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
|
||||
GLX_RENDER_TYPE , GLX_RGBA_BIT,
|
||||
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
|
||||
GLX_RED_SIZE , 8,
|
||||
GLX_GREEN_SIZE , 8,
|
||||
GLX_BLUE_SIZE , 8,
|
||||
GLX_ALPHA_SIZE , 8,
|
||||
GLX_DEPTH_SIZE , 24,
|
||||
GLX_STENCIL_SIZE , 8,
|
||||
GLX_DOUBLEBUFFER , glx_doublebuffer ? True : False,
|
||||
None
|
||||
};
|
||||
|
||||
int fbcount;
|
||||
GLXFBConfig* fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
|
||||
if (!fbc) {
|
||||
throw std::runtime_error("Pangolin X11: Unable to retrieve framebuffer options");
|
||||
}
|
||||
|
||||
int best_fbc = -1;
|
||||
int worst_fbc = -1;
|
||||
int best_num_samp = -1;
|
||||
int worst_num_samp = 999;
|
||||
|
||||
// Enumerate framebuffer options, storing the best and worst that match our attribs
|
||||
for (int i=0; i<fbcount; ++i)
|
||||
{
|
||||
XVisualInfo *vi = glXGetVisualFromFBConfig( display, fbc[i] );
|
||||
if ( vi )
|
||||
{
|
||||
int samp_buf, samples;
|
||||
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
|
||||
glXGetFBConfigAttrib( display, fbc[i], GLX_SAMPLES , &samples );
|
||||
|
||||
// Filter for the best available.
|
||||
if ( samples > best_num_samp ) {
|
||||
best_fbc = i;
|
||||
best_num_samp = samples;
|
||||
}
|
||||
|
||||
// Filter lowest settings which match minimum user requirement.
|
||||
if ( samp_buf >= glx_sample_buffers && samples >= glx_samples && samples < worst_num_samp ) {
|
||||
worst_fbc = i;
|
||||
worst_num_samp = samples;
|
||||
}
|
||||
}
|
||||
XFree( vi );
|
||||
}
|
||||
|
||||
// Select the minimum suitable option. The 'best' is often too slow.
|
||||
int chosen_fbc_id = worst_fbc;
|
||||
|
||||
// If minimum requested isn't available, return the best that is.
|
||||
if(chosen_fbc_id < 0) {
|
||||
pango_print_warn("Framebuffer with requested attributes not available. Using available framebuffer. You may see visual artifacts.");
|
||||
chosen_fbc_id = best_fbc;
|
||||
}
|
||||
|
||||
::GLXFBConfig chosenFbc = fbc[ chosen_fbc_id ];
|
||||
XFree( fbc );
|
||||
return chosenFbc;
|
||||
}
|
||||
|
||||
static bool ctxErrorOccurred = false;
|
||||
static int ctxErrorHandler( ::Display * /*dpy*/, ::XErrorEvent * ev )
|
||||
{
|
||||
const int buffer_size = 10240;
|
||||
char buffer[buffer_size];
|
||||
XGetErrorText(ev->display, ev->error_code, buffer, buffer_size );
|
||||
pango_print_error("X11 Error: %s\n", buffer);
|
||||
ctxErrorOccurred = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLXContext CreateGlContext(::Display *display, ::GLXFBConfig chosenFbc, GLXContext share_context = 0)
|
||||
{
|
||||
int glx_major, glx_minor;
|
||||
if ( !glXQueryVersion( display, &glx_major, &glx_minor ) ||
|
||||
( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) )
|
||||
{
|
||||
throw std::runtime_error("Pangolin X11: Invalid GLX version. Require GLX >= 1.3");
|
||||
}
|
||||
|
||||
GLXContext new_ctx;
|
||||
|
||||
// Get the default screen's GLX extension list
|
||||
const char *glxExts = glXQueryExtensionsString( display, DefaultScreen( display ) );
|
||||
|
||||
glXCreateContextAttribsARBProc glXCreateContextAttribsARB =
|
||||
(glXCreateContextAttribsARBProc) glXGetProcAddressARB(
|
||||
(const GLubyte *) "glXCreateContextAttribsARB"
|
||||
);
|
||||
|
||||
// Install an X error handler so the application won't exit if GL 3.0
|
||||
// context allocation fails. Handler is global and shared across all threads.
|
||||
ctxErrorOccurred = false;
|
||||
int (*oldHandler)(::Display*, ::XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
|
||||
|
||||
if ( isExtensionSupported( glxExts, "GLX_ARB_create_context" ) && glXCreateContextAttribsARB )
|
||||
{
|
||||
int context_attribs[] = {
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
None
|
||||
};
|
||||
|
||||
new_ctx = glXCreateContextAttribsARB( display, chosenFbc, share_context, True, context_attribs );
|
||||
|
||||
// Sync to ensure any errors generated are processed.
|
||||
XSync( display, False );
|
||||
if ( ctxErrorOccurred || !new_ctx ) {
|
||||
ctxErrorOccurred = false;
|
||||
// Fall back to old-style 2.x context. Implementations will return the newest
|
||||
// context version compatible with OpenGL versions less than version 3.0.
|
||||
context_attribs[1] = 1; // GLX_CONTEXT_MAJOR_VERSION_ARB = 1
|
||||
context_attribs[3] = 0; // GLX_CONTEXT_MINOR_VERSION_ARB = 0
|
||||
new_ctx = glXCreateContextAttribsARB( display, chosenFbc, share_context, True, context_attribs );
|
||||
}
|
||||
} else {
|
||||
// Fallback to GLX 1.3 Context
|
||||
new_ctx = glXCreateNewContext( display, chosenFbc, GLX_RGBA_TYPE, share_context, True );
|
||||
}
|
||||
|
||||
// Sync to ensure any errors generated are processed.
|
||||
XSync( display, False );
|
||||
|
||||
// Restore the original error handler
|
||||
XSetErrorHandler( oldHandler );
|
||||
|
||||
if ( ctxErrorOccurred || !new_ctx ) {
|
||||
throw std::runtime_error("Pangolin X11: Failed to create an OpenGL context");
|
||||
}
|
||||
|
||||
// Verifying that context is a direct context
|
||||
if ( ! glXIsDirect ( display, new_ctx ) ) {
|
||||
pango_print_warn("Pangolin X11: Indirect GLX rendering context obtained\n");
|
||||
}
|
||||
|
||||
return new_ctx;
|
||||
}
|
||||
|
||||
X11GlContext::X11GlContext(std::shared_ptr<X11Display>& d, ::GLXFBConfig chosenFbc, std::shared_ptr<X11GlContext> shared_context)
|
||||
: display(d), shared_context(shared_context)
|
||||
{
|
||||
// prevent chained sharing
|
||||
while(shared_context && shared_context->shared_context) {
|
||||
shared_context = shared_context->shared_context;
|
||||
}
|
||||
|
||||
// Contexts can't be shared across different displays.
|
||||
if(shared_context && shared_context->display != d) {
|
||||
shared_context.reset();
|
||||
}
|
||||
|
||||
glcontext = CreateGlContext(display->display, chosenFbc, shared_context ? shared_context->glcontext : 0);
|
||||
}
|
||||
|
||||
X11GlContext::~X11GlContext()
|
||||
{
|
||||
glXDestroyContext( display->display, glcontext );
|
||||
}
|
||||
|
||||
X11Window::X11Window(
|
||||
const std::string& title, int width, int height,
|
||||
std::shared_ptr<X11Display>& display, ::GLXFBConfig chosenFbc
|
||||
) : display(display), glcontext(0), win(0), cmap(0)
|
||||
{
|
||||
PangolinGl::windowed_size[0] = width;
|
||||
PangolinGl::windowed_size[1] = height;
|
||||
|
||||
// Get a visual
|
||||
XVisualInfo *vi = glXGetVisualFromFBConfig( display->display, chosenFbc );
|
||||
|
||||
// Create colourmap
|
||||
XSetWindowAttributes swa;
|
||||
swa.background_pixmap = None;
|
||||
swa.border_pixel = 0;
|
||||
swa.event_mask = StructureNotifyMask;
|
||||
swa.colormap = cmap = XCreateColormap( display->display,
|
||||
RootWindow( display->display, vi->screen ),
|
||||
vi->visual, AllocNone );
|
||||
|
||||
// Create window
|
||||
win = XCreateWindow( display->display, RootWindow( display->display, vi->screen ),
|
||||
0, 0, width, height, 0, vi->depth, InputOutput,
|
||||
vi->visual,
|
||||
CWBorderPixel|CWColormap|CWEventMask, &swa );
|
||||
|
||||
XFree( vi );
|
||||
|
||||
if ( !win ) {
|
||||
throw std::runtime_error("Pangolin X11: Failed to create window." );
|
||||
}
|
||||
|
||||
XStoreName( display->display, win, title.c_str() );
|
||||
XMapWindow( display->display, win );
|
||||
|
||||
// Request to be notified of these events
|
||||
XSelectInput(display->display, win, EVENT_MASKS );
|
||||
|
||||
delete_message = XInternAtom(display->display, "WM_DELETE_WINDOW", False);
|
||||
XSetWMProtocols(display->display, win, &delete_message, 1);
|
||||
}
|
||||
|
||||
X11Window::~X11Window()
|
||||
{
|
||||
glXMakeCurrent( display->display, 0, 0 );
|
||||
XDestroyWindow( display->display, win );
|
||||
XFreeColormap( display->display, cmap );
|
||||
}
|
||||
|
||||
void X11Window::MakeCurrent(GLXContext ctx)
|
||||
{
|
||||
glXMakeCurrent( display->display, win, ctx );
|
||||
context = this;
|
||||
}
|
||||
|
||||
void X11Window::MakeCurrent()
|
||||
{
|
||||
MakeCurrent(glcontext ? glcontext->glcontext : global_gl_context.lock()->glcontext);
|
||||
}
|
||||
|
||||
void X11Window::RemoveCurrent()
|
||||
{
|
||||
glXMakeCurrent(display->display, 0, nullptr);
|
||||
}
|
||||
|
||||
void X11Window::ToggleFullscreen()
|
||||
{
|
||||
const Atom _NET_WM_STATE_FULLSCREEN = XInternAtom(display->display, "_NET_WM_STATE_FULLSCREEN", True);
|
||||
const Atom _NET_WM_STATE = XInternAtom(display->display, "_NET_WM_STATE", True);
|
||||
XEvent e;
|
||||
e.xclient.type = ClientMessage;
|
||||
e.xclient.window = win;
|
||||
e.xclient.message_type = _NET_WM_STATE;
|
||||
e.xclient.format = 32;
|
||||
e.xclient.data.l[0] = 2; // Toggle
|
||||
e.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
|
||||
e.xclient.data.l[2] = 0;
|
||||
e.xclient.data.l[3] = 1;
|
||||
e.xclient.data.l[4] = 0;
|
||||
|
||||
XSendEvent(display->display, DefaultRootWindow(display->display), False, SubstructureRedirectMask | SubstructureNotifyMask, &e);
|
||||
XMoveResizeWindow(display->display, win, 0, 0, windowed_size[0], windowed_size[1]);
|
||||
}
|
||||
|
||||
void X11Window::Move(int x, int y)
|
||||
{
|
||||
XMoveWindow(display->display, win, x, y);
|
||||
}
|
||||
|
||||
void X11Window::Resize(unsigned int w, unsigned int h)
|
||||
{
|
||||
XResizeWindow(display->display, win, w, h);
|
||||
}
|
||||
|
||||
void X11Window::ProcessEvents()
|
||||
{
|
||||
XEvent ev;
|
||||
while(!pangolin::ShouldQuit() && XPending(display->display) > 0)
|
||||
{
|
||||
XNextEvent(display->display, &ev);
|
||||
|
||||
switch(ev.type){
|
||||
case ConfigureNotify:
|
||||
pangolin::process::Resize(ev.xconfigure.width, ev.xconfigure.height);
|
||||
break;
|
||||
case ClientMessage:
|
||||
// We've only registered to receive WM_DELETE_WINDOW, so no further checks needed.
|
||||
pangolin::Quit();
|
||||
break;
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
{
|
||||
const int button = ev.xbutton.button-1;
|
||||
pangolin::process::Mouse(
|
||||
button,
|
||||
ev.xbutton.type == ButtonRelease,
|
||||
ev.xbutton.x, ev.xbutton.y
|
||||
);
|
||||
break;
|
||||
}
|
||||
case FocusOut:
|
||||
pangolin::context->mouse_state = 0;
|
||||
break;
|
||||
case MotionNotify:
|
||||
if(ev.xmotion.state & (Button1Mask|Button2Mask|Button3Mask) ) {
|
||||
pangolin::process::MouseMotion(ev.xmotion.x, ev.xmotion.y);
|
||||
}else{
|
||||
pangolin::process::PassiveMouseMotion(ev.xmotion.x, ev.xmotion.y);
|
||||
}
|
||||
break;
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
int key;
|
||||
char ch;
|
||||
KeySym sym;
|
||||
|
||||
if( XLookupString(&ev.xkey,&ch,1,&sym,0) == 0) {
|
||||
switch (sym) {
|
||||
case XK_F1: key = PANGO_SPECIAL + PANGO_KEY_F1 ; break;
|
||||
case XK_F2: key = PANGO_SPECIAL + PANGO_KEY_F2 ; break;
|
||||
case XK_F3: key = PANGO_SPECIAL + PANGO_KEY_F3 ; break;
|
||||
case XK_F4: key = PANGO_SPECIAL + PANGO_KEY_F4 ; break;
|
||||
case XK_F5: key = PANGO_SPECIAL + PANGO_KEY_F5 ; break;
|
||||
case XK_F6: key = PANGO_SPECIAL + PANGO_KEY_F6 ; break;
|
||||
case XK_F7: key = PANGO_SPECIAL + PANGO_KEY_F7 ; break;
|
||||
case XK_F8: key = PANGO_SPECIAL + PANGO_KEY_F8 ; break;
|
||||
case XK_F9: key = PANGO_SPECIAL + PANGO_KEY_F9 ; break;
|
||||
case XK_F10: key = PANGO_SPECIAL + PANGO_KEY_F10 ; break;
|
||||
case XK_F11: key = PANGO_SPECIAL + PANGO_KEY_F11 ; break;
|
||||
case XK_F12: key = PANGO_SPECIAL + PANGO_KEY_F12 ; break;
|
||||
case XK_Left: key = PANGO_SPECIAL + PANGO_KEY_LEFT ; break;
|
||||
case XK_Up: key = PANGO_SPECIAL + PANGO_KEY_UP ; break;
|
||||
case XK_Right: key = PANGO_SPECIAL + PANGO_KEY_RIGHT ; break;
|
||||
case XK_Down: key = PANGO_SPECIAL + PANGO_KEY_DOWN ; break;
|
||||
case XK_Page_Up: key = PANGO_SPECIAL + PANGO_KEY_PAGE_UP ; break;
|
||||
case XK_Page_Down: key = PANGO_SPECIAL + PANGO_KEY_PAGE_DOWN ; break;
|
||||
case XK_Home: key = PANGO_SPECIAL + PANGO_KEY_HOME ; break;
|
||||
case XK_End: key = PANGO_SPECIAL + PANGO_KEY_END ; break;
|
||||
case XK_Insert: key = PANGO_SPECIAL + PANGO_KEY_INSERT ; break;
|
||||
case XK_Shift_L:
|
||||
case XK_Shift_R:
|
||||
key = -1;
|
||||
if(ev.type==KeyPress) {
|
||||
pangolin::context->mouse_state |= pangolin::KeyModifierShift;
|
||||
}else{
|
||||
pangolin::context->mouse_state &= ~pangolin::KeyModifierShift;
|
||||
}
|
||||
break;
|
||||
case XK_Control_L:
|
||||
case XK_Control_R:
|
||||
key = -1;
|
||||
if(ev.type==KeyPress) {
|
||||
pangolin::context->mouse_state |= pangolin::KeyModifierCtrl;
|
||||
}else{
|
||||
pangolin::context->mouse_state &= ~pangolin::KeyModifierCtrl;
|
||||
}
|
||||
break;
|
||||
case XK_Alt_L:
|
||||
case XK_Alt_R:
|
||||
key = -1;
|
||||
if(ev.type==KeyPress) {
|
||||
pangolin::context->mouse_state |= pangolin::KeyModifierAlt;
|
||||
}else{
|
||||
pangolin::context->mouse_state &= ~pangolin::KeyModifierAlt;
|
||||
}
|
||||
break;
|
||||
case XK_Super_L:
|
||||
case XK_Super_R:
|
||||
key = -1;
|
||||
if(ev.type==KeyPress) {
|
||||
pangolin::context->mouse_state |= pangolin::KeyModifierCmd;
|
||||
}else{
|
||||
pangolin::context->mouse_state &= ~pangolin::KeyModifierCmd;
|
||||
}
|
||||
break;
|
||||
default: key = -1; break;
|
||||
}
|
||||
}else{
|
||||
key = ch;
|
||||
}
|
||||
|
||||
if(key >=0) {
|
||||
if(ev.type == KeyPress) {
|
||||
pangolin::process::Keyboard(key, ev.xkey.x, ev.xkey.y);
|
||||
}else{
|
||||
pangolin::process::KeyboardUp(key, ev.xkey.x, ev.xkey.y);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void X11Window::SwapBuffers() {
|
||||
glXSwapBuffers(display->display, win);
|
||||
}
|
||||
|
||||
std::unique_ptr<WindowInterface> CreateX11WindowAndBind(const std::string& window_title, const int w, const int h, const std::string& display_name, const bool double_buffered, const int sample_buffers, const int samples)
|
||||
{
|
||||
std::shared_ptr<X11Display> newdisplay = std::make_shared<X11Display>(display_name.empty() ? NULL : display_name.c_str() );
|
||||
if (!newdisplay) {
|
||||
throw std::runtime_error("Pangolin X11: Failed to open X display");
|
||||
}
|
||||
::GLXFBConfig newfbc = ChooseFrameBuffer(newdisplay->display, double_buffered, sample_buffers, samples);
|
||||
|
||||
window_mutex.lock();
|
||||
std::shared_ptr<X11GlContext> newglcontext = std::make_shared<X11GlContext>(
|
||||
newdisplay, newfbc, global_gl_context.lock()
|
||||
);
|
||||
|
||||
if(!global_gl_context.lock()) {
|
||||
global_gl_context = newglcontext;
|
||||
}
|
||||
window_mutex.unlock();
|
||||
|
||||
X11Window* win = new X11Window(window_title, w, h, newdisplay, newfbc);
|
||||
win->glcontext = newglcontext;
|
||||
win->is_double_buffered = double_buffered;
|
||||
|
||||
return std::unique_ptr<WindowInterface>(win);
|
||||
}
|
||||
|
||||
PANGOLIN_REGISTER_FACTORY(X11Window)
|
||||
{
|
||||
struct X11WindowFactory : public FactoryInterface<WindowInterface> {
|
||||
std::unique_ptr<WindowInterface> Open(const Uri& uri) override {
|
||||
|
||||
const std::string window_title = uri.Get<std::string>("window_title", "window");
|
||||
const int w = uri.Get<int>("w", 640);
|
||||
const int h = uri.Get<int>("h", 480);
|
||||
const std::string display_name = uri.Get<std::string>("display_name", "");
|
||||
const bool double_buffered = uri.Get<bool>("double_buffered", true);
|
||||
const int sample_buffers = uri.Get<int>("sample_buffers", 1);
|
||||
const int samples = uri.Get<int>("samples", 1);
|
||||
return std::unique_ptr<WindowInterface>(CreateX11WindowAndBind(window_title, w, h, display_name, double_buffered, sample_buffers, samples));
|
||||
}
|
||||
};
|
||||
|
||||
auto factory = std::make_shared<X11WindowFactory>();
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 10, "x11");
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 10, "linux");
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 100, "default");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
660
thirdparty/Pangolin/src/display/display.cpp
vendored
Normal file
660
thirdparty/Pangolin/src/display/display.cpp
vendored
Normal file
@@ -0,0 +1,660 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/platform.h>
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#include <pangolin/python/pyinterpreter.h>
|
||||
#include <pangolin/console/ConsoleView.h>
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <pangolin/factory/factory_registry.h>
|
||||
#include <pangolin/window_frameworks.h>
|
||||
#include <pangolin/gl/glinclude.h>
|
||||
#include <pangolin/gl/gldraw.h>
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/display_internal.h>
|
||||
#include <pangolin/handler/handler.h>
|
||||
#include <pangolin/utils/simple_math.h>
|
||||
#include <pangolin/utils/timer.h>
|
||||
#include <pangolin/utils/type_convert.h>
|
||||
#include <pangolin/image/image_io.h>
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VARS
|
||||
#include <pangolin/var/var.h>
|
||||
#endif
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
// Forward declaration.
|
||||
void SaveFramebuffer(VideoOutput& video, const Viewport& v);
|
||||
#endif // BUILD_PANGOLIN_VIDEO
|
||||
|
||||
const char* PARAM_DISPLAYNAME = "DISPLAYNAME";
|
||||
const char* PARAM_DOUBLEBUFFER = "DOUBLEBUFFER";
|
||||
const char* PARAM_SAMPLE_BUFFERS = "SAMPLE_BUFFERS";
|
||||
const char* PARAM_SAMPLES = "SAMPLES";
|
||||
const char* PARAM_HIGHRES = "HIGHRES";
|
||||
|
||||
|
||||
typedef std::map<std::string,std::shared_ptr<PangolinGl> > ContextMap;
|
||||
|
||||
// Map of active contexts
|
||||
ContextMap contexts;
|
||||
std::recursive_mutex contexts_mutex;
|
||||
bool one_time_window_frameworks_init = false;
|
||||
|
||||
// Context active for current thread
|
||||
__thread PangolinGl* context = 0;
|
||||
|
||||
PangolinGl::PangolinGl()
|
||||
: user_app(0), is_high_res(false), quit(false), mouse_state(0),activeDisplay(0)
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
, record_view(0)
|
||||
#endif
|
||||
#ifdef HAVE_PYTHON
|
||||
, console_view(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
PangolinGl::~PangolinGl()
|
||||
{
|
||||
// Free displays owned by named_managed_views
|
||||
for(ViewMap::iterator iv = named_managed_views.begin(); iv != named_managed_views.end(); ++iv) {
|
||||
delete iv->second;
|
||||
}
|
||||
named_managed_views.clear();
|
||||
}
|
||||
|
||||
PangolinGl* GetCurrentContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
PangolinGl *FindContext(const std::string& name)
|
||||
{
|
||||
contexts_mutex.lock();
|
||||
ContextMap::iterator ic = contexts.find(name);
|
||||
PangolinGl* context = (ic == contexts.end()) ? 0 : ic->second.get();
|
||||
contexts_mutex.unlock();
|
||||
return context;
|
||||
}
|
||||
|
||||
WindowInterface& CreateWindowAndBind(std::string window_title, int w, int h, const Params& params)
|
||||
{
|
||||
std::unique_lock<std::recursive_mutex> l(contexts_mutex);
|
||||
|
||||
if(!one_time_window_frameworks_init) {
|
||||
one_time_window_frameworks_init = LoadBuiltInWindowFrameworks();
|
||||
}
|
||||
|
||||
pangolin::Uri win_uri;
|
||||
|
||||
if(const char* extra_params = std::getenv("PANGOLIN_WINDOW_URI"))
|
||||
{
|
||||
// Take any defaults from the environment
|
||||
win_uri = pangolin::ParseUri(extra_params);
|
||||
}else{
|
||||
// Otherwise revert to 'default' scheme.
|
||||
win_uri.scheme = "default";
|
||||
}
|
||||
|
||||
// Allow params to override
|
||||
win_uri.scheme = params.Get("scheme", win_uri.scheme);
|
||||
|
||||
// Override with anything the program specified
|
||||
win_uri.params.insert(std::end(win_uri.params), std::begin(params.params), std::end(params.params));
|
||||
win_uri.Set("w", w);
|
||||
win_uri.Set("h", h);
|
||||
win_uri.Set("window_title", window_title);
|
||||
|
||||
std::unique_ptr<WindowInterface> window = FactoryRegistry<WindowInterface>::I().Open(win_uri);
|
||||
|
||||
// We're expecting not only a WindowInterface, but a PangolinGl.
|
||||
if(!window || !dynamic_cast<PangolinGl*>(window.get())) {
|
||||
throw WindowExceptionNoKnownHandler(win_uri.scheme);
|
||||
}
|
||||
|
||||
std::shared_ptr<PangolinGl> context(dynamic_cast<PangolinGl*>(window.release()));
|
||||
RegisterNewContext(window_title, context );
|
||||
// is_high_res will alter default font size and a few other gui elements.
|
||||
context->is_high_res = win_uri.Get(PARAM_HIGHRES,false);
|
||||
context->MakeCurrent();
|
||||
context->ProcessEvents();
|
||||
glewInit();
|
||||
|
||||
return *context;
|
||||
}
|
||||
|
||||
// Assumption: unique lock is held on contexts_mutex for multi-threaded operation
|
||||
void RegisterNewContext(const std::string& name, std::shared_ptr<PangolinGl> newcontext)
|
||||
{
|
||||
// Set defaults
|
||||
newcontext->base.left = 0.0;
|
||||
newcontext->base.bottom = 0.0;
|
||||
newcontext->base.top = 1.0;
|
||||
newcontext->base.right = 1.0;
|
||||
newcontext->base.aspect = 0;
|
||||
newcontext->base.handler = &StaticHandler;
|
||||
newcontext->is_fullscreen = false;
|
||||
|
||||
// Create and add
|
||||
if( contexts.find(name) != contexts.end() ) {
|
||||
throw std::runtime_error("Context already exists.");
|
||||
}
|
||||
contexts[name] = newcontext;
|
||||
|
||||
// Process the following as if this context is now current.
|
||||
PangolinGl *oldContext = context;
|
||||
context = newcontext.get();
|
||||
process::Resize(
|
||||
newcontext->windowed_size[0],
|
||||
newcontext->windowed_size[1]
|
||||
);
|
||||
|
||||
// Default key bindings can be overridden
|
||||
RegisterKeyPressCallback(PANGO_KEY_ESCAPE, Quit );
|
||||
RegisterKeyPressCallback('\t', ToggleFullscreen );
|
||||
RegisterKeyPressCallback('`', ToggleConsole );
|
||||
|
||||
context = oldContext;
|
||||
}
|
||||
|
||||
WindowInterface* GetBoundWindow()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
void DestroyWindow(const std::string& name)
|
||||
{
|
||||
contexts_mutex.lock();
|
||||
ContextMap::iterator ic = contexts.find(name);
|
||||
PangolinGl *context_to_destroy = (ic == contexts.end()) ? 0 : ic->second.get();
|
||||
if (context_to_destroy == context) {
|
||||
context = nullptr;
|
||||
}
|
||||
size_t erased = contexts.erase(name);
|
||||
if(erased == 0) {
|
||||
pango_print_warn("Context '%s' doesn't exist for deletion.\n", name.c_str());
|
||||
}
|
||||
contexts_mutex.unlock();
|
||||
}
|
||||
|
||||
WindowInterface& BindToContext(std::string name)
|
||||
{
|
||||
std::unique_lock<std::recursive_mutex> l(contexts_mutex);
|
||||
|
||||
// N.B. context is modified prior to invoking MakeCurrent so that
|
||||
// state management callbacks (such as Resize()) can be correctly
|
||||
// processed.
|
||||
PangolinGl *context_to_bind = FindContext(name);
|
||||
if( !context_to_bind )
|
||||
{
|
||||
std::shared_ptr<PangolinGl> newcontext(new PangolinGl());
|
||||
RegisterNewContext(name, newcontext);
|
||||
return *(newcontext.get());
|
||||
}else{
|
||||
context_to_bind->MakeCurrent();
|
||||
return *context_to_bind;
|
||||
}
|
||||
}
|
||||
|
||||
void Quit()
|
||||
{
|
||||
context->quit = true;
|
||||
}
|
||||
|
||||
void QuitAll()
|
||||
{
|
||||
for(auto nc : contexts) {
|
||||
nc.second->quit = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ShouldQuit()
|
||||
{
|
||||
return !context || context->quit;
|
||||
}
|
||||
|
||||
bool HadInput()
|
||||
{
|
||||
if( context->had_input > 0 )
|
||||
{
|
||||
--context->had_input;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasResized()
|
||||
{
|
||||
if( context->has_resized > 0 )
|
||||
{
|
||||
--context->has_resized;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void StartFullScreen() {
|
||||
if(!context->is_fullscreen) {
|
||||
context->ToggleFullscreen();
|
||||
context->is_fullscreen = true;
|
||||
}
|
||||
}
|
||||
|
||||
void StopFullScreen() {
|
||||
if(context->is_fullscreen) {
|
||||
context->ToggleFullscreen();
|
||||
context->is_fullscreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetFullscreen(bool fullscreen)
|
||||
{
|
||||
if(fullscreen) {
|
||||
StartFullScreen();
|
||||
}else{
|
||||
StopFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderViews()
|
||||
{
|
||||
Viewport::DisableScissor();
|
||||
DisplayBase().Render();
|
||||
}
|
||||
|
||||
void RenderRecordGraphic(const Viewport& v)
|
||||
{
|
||||
const float r = 7;
|
||||
v.ActivatePixelOrthographic();
|
||||
glRecordGraphic(v.w-2*r, v.h-2*r, r);
|
||||
}
|
||||
|
||||
void PostRender()
|
||||
{
|
||||
while(context->screen_capture.size()) {
|
||||
std::pair<std::string,Viewport> fv = context->screen_capture.front();
|
||||
context->screen_capture.pop();
|
||||
SaveFramebuffer(fv.first, fv.second);
|
||||
}
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
if(context->recorder.IsOpen()) {
|
||||
SaveFramebuffer(context->recorder, context->record_view->GetBounds() );
|
||||
RenderRecordGraphic(context->record_view->GetBounds());
|
||||
}
|
||||
#endif // BUILD_PANGOLIN_VIDEO
|
||||
|
||||
// Disable scissor each frame
|
||||
Viewport::DisableScissor();
|
||||
}
|
||||
|
||||
void FinishFrame()
|
||||
{
|
||||
RenderViews();
|
||||
PostRender();
|
||||
context->SwapBuffers();
|
||||
context->ProcessEvents();
|
||||
}
|
||||
|
||||
View& DisplayBase()
|
||||
{
|
||||
return context->base;
|
||||
}
|
||||
|
||||
View& CreateDisplay()
|
||||
{
|
||||
int iguid = rand();
|
||||
std::stringstream ssguid;
|
||||
ssguid << iguid;
|
||||
return Display(ssguid.str());
|
||||
}
|
||||
|
||||
void ToggleConsole()
|
||||
{
|
||||
#ifdef HAVE_PYTHON
|
||||
if( !context->console_view) {
|
||||
// Create console and let the pangolin context take ownership
|
||||
context->console_view = new ConsoleView(new PyInterpreter());
|
||||
context->named_managed_views["pangolin_console"] = context->console_view;
|
||||
context->console_view->SetFocus();
|
||||
context->console_view->zorder = std::numeric_limits<int>::max();
|
||||
DisplayBase().AddDisplay(*context->console_view);
|
||||
}else{
|
||||
context->console_view->ToggleShow();
|
||||
if(context->console_view->IsShown()) {
|
||||
context->console_view->SetFocus();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ToggleFullscreen()
|
||||
{
|
||||
SetFullscreen(!context->is_fullscreen);
|
||||
}
|
||||
|
||||
View& Display(const std::string& name)
|
||||
{
|
||||
// Get / Create View
|
||||
ViewMap::iterator vi = context->named_managed_views.find(name);
|
||||
if( vi != context->named_managed_views.end() )
|
||||
{
|
||||
return *(vi->second);
|
||||
}else{
|
||||
View * v = new View();
|
||||
context->named_managed_views[name] = v;
|
||||
v->handler = &StaticHandler;
|
||||
context->base.views.push_back(v);
|
||||
return *v;
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterKeyPressCallback(int key, std::function<void(void)> func)
|
||||
{
|
||||
context->keypress_hooks[key] = func;
|
||||
}
|
||||
|
||||
void SaveWindowOnRender(std::string prefix)
|
||||
{
|
||||
context->screen_capture.push(std::pair<std::string,Viewport>(prefix, context->base.v) );
|
||||
}
|
||||
|
||||
void SaveFramebuffer(std::string prefix, const Viewport& v)
|
||||
{
|
||||
PANGOLIN_UNUSED(prefix);
|
||||
PANGOLIN_UNUSED(v);
|
||||
|
||||
#ifndef HAVE_GLES
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
PixelFormat fmt = PixelFormatFromString("RGBA32");
|
||||
TypedImage buffer(v.w, v.h, fmt );
|
||||
glReadBuffer(GL_BACK);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1); // TODO: Avoid this?
|
||||
glReadPixels(v.l, v.b, v.w, v.h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.ptr );
|
||||
SaveImage(buffer, fmt, prefix + ".png", false);
|
||||
#endif // HAVE_PNG
|
||||
|
||||
#endif // HAVE_GLES
|
||||
}
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
void SaveFramebuffer(VideoOutput& video, const Viewport& v)
|
||||
{
|
||||
#ifndef HAVE_GLES
|
||||
const StreamInfo& si = video.Streams()[0];
|
||||
if(video.Streams().size()==0 || (int)si.Width() != v.w || (int)si.Height() != v.h) {
|
||||
video.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
static basetime last_time = TimeNow();
|
||||
const basetime time_now = TimeNow();
|
||||
last_time = time_now;
|
||||
|
||||
static std::vector<unsigned char> img;
|
||||
img.resize(v.w*v.h*4);
|
||||
|
||||
glReadBuffer(GL_BACK);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1); // TODO: Avoid this?
|
||||
glReadPixels(v.l, v.b, v.w, v.h, GL_RGB, GL_UNSIGNED_BYTE, &img[0] );
|
||||
video.WriteStreams(&img[0]);
|
||||
#endif // HAVE_GLES
|
||||
}
|
||||
#endif // BUILD_PANGOLIN_VIDEO
|
||||
|
||||
|
||||
namespace process
|
||||
{
|
||||
float last_x = 0;
|
||||
float last_y = 0;
|
||||
|
||||
void Keyboard( unsigned char key, int x, int y)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
|
||||
#ifdef HAVE_APPLE_OPENGL_FRAMEWORK
|
||||
// Switch backspace and delete for OSX!
|
||||
if(key== '\b') {
|
||||
key = 127;
|
||||
}else if(key == 127) {
|
||||
key = '\b';
|
||||
}
|
||||
#endif
|
||||
|
||||
context->had_input = context->is_double_buffered ? 2 : 1;
|
||||
|
||||
// Check if global key hook exists
|
||||
const KeyhookMap::iterator hook = context->keypress_hooks.find(key);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
// Console receives all input when it is open
|
||||
if( context->console_view && context->console_view->IsShown() ) {
|
||||
context->console_view->Keyboard(*(context->console_view),key,x,y,true);
|
||||
}else
|
||||
#endif
|
||||
if(hook != context->keypress_hooks.end() ) {
|
||||
hook->second();
|
||||
} else if(context->activeDisplay && context->activeDisplay->handler) {
|
||||
context->activeDisplay->handler->Keyboard(*(context->activeDisplay),key,x,y,true);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardUp(unsigned char key, int x, int y)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
|
||||
if(context->activeDisplay && context->activeDisplay->handler)
|
||||
{
|
||||
context->activeDisplay->handler->Keyboard(*(context->activeDisplay),key,x,y,false);
|
||||
}
|
||||
}
|
||||
|
||||
void SpecialFunc(int key, int x, int y)
|
||||
{
|
||||
Keyboard(key+128,x,y);
|
||||
}
|
||||
|
||||
void SpecialFuncUp(int key, int x, int y)
|
||||
{
|
||||
KeyboardUp(key+128,x,y);
|
||||
}
|
||||
|
||||
|
||||
void Mouse( int button_raw, int state, int x, int y)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
|
||||
last_x = (float)x;
|
||||
last_y = (float)y;
|
||||
|
||||
const MouseButton button = (MouseButton)(1 << (button_raw & 0xf) );
|
||||
const bool pressed = (state == 0);
|
||||
|
||||
context->had_input = context->is_double_buffered ? 2 : 1;
|
||||
|
||||
const bool fresh_input = ( (context->mouse_state & 7) == 0);
|
||||
|
||||
if( pressed ) {
|
||||
context->mouse_state |= (button&7);
|
||||
}else{
|
||||
context->mouse_state &= ~(button&7);
|
||||
}
|
||||
|
||||
#if defined(_WIN_)
|
||||
context->mouse_state &= 0x0000ffff;
|
||||
context->mouse_state |= (button_raw >> 4) << 16;
|
||||
#endif
|
||||
|
||||
if(fresh_input) {
|
||||
context->base.handler->Mouse(context->base,button,x,y,pressed,context->mouse_state);
|
||||
}else if(context->activeDisplay && context->activeDisplay->handler) {
|
||||
context->activeDisplay->handler->Mouse(*(context->activeDisplay),button,x,y,pressed,context->mouse_state);
|
||||
}
|
||||
}
|
||||
|
||||
void MouseMotion( int x, int y)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
|
||||
last_x = (float)x;
|
||||
last_y = (float)y;
|
||||
|
||||
context->had_input = context->is_double_buffered ? 2 : 1;
|
||||
|
||||
if( context->activeDisplay)
|
||||
{
|
||||
if( context->activeDisplay->handler )
|
||||
context->activeDisplay->handler->MouseMotion(*(context->activeDisplay),x,y,context->mouse_state);
|
||||
}else{
|
||||
context->base.handler->MouseMotion(context->base,x,y,context->mouse_state);
|
||||
}
|
||||
}
|
||||
|
||||
void PassiveMouseMotion(int x, int y)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
|
||||
context->base.handler->PassiveMouseMotion(context->base,x,y,context->mouse_state);
|
||||
|
||||
last_x = (float)x;
|
||||
last_y = (float)y;
|
||||
}
|
||||
|
||||
void Display()
|
||||
{
|
||||
// No implementation
|
||||
}
|
||||
|
||||
void Resize( int width, int height )
|
||||
{
|
||||
if( !context->is_fullscreen )
|
||||
{
|
||||
context->windowed_size[0] = width;
|
||||
context->windowed_size[1] = height;
|
||||
}
|
||||
// TODO: Fancy display managers seem to cause this to mess up?
|
||||
context->had_input = 20; //context->is_double_buffered ? 2 : 1;
|
||||
context->has_resized = 20; //context->is_double_buffered ? 2 : 1;
|
||||
Viewport win(0,0,width,height);
|
||||
context->base.Resize(win);
|
||||
}
|
||||
|
||||
void SpecialInput(InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4)
|
||||
{
|
||||
// Assume coords already match OpenGl Window Coords
|
||||
|
||||
context->had_input = context->is_double_buffered ? 2 : 1;
|
||||
|
||||
const bool fresh_input = (context->mouse_state == 0);
|
||||
|
||||
if(fresh_input) {
|
||||
context->base.handler->Special(context->base,inType,x,y,p1,p2,p3,p4,context->mouse_state);
|
||||
}else if(context->activeDisplay && context->activeDisplay->handler) {
|
||||
context->activeDisplay->handler->Special(*(context->activeDisplay),inType,x,y,p1,p2,p3,p4,context->mouse_state);
|
||||
}
|
||||
}
|
||||
|
||||
void Scroll(float x, float y)
|
||||
{
|
||||
SpecialInput(InputSpecialScroll, last_x, last_y, x, y, 0, 0);
|
||||
}
|
||||
|
||||
void Zoom(float m)
|
||||
{
|
||||
SpecialInput(InputSpecialZoom, last_x, last_y, m, 0, 0, 0);
|
||||
}
|
||||
|
||||
void Rotate(float r)
|
||||
{
|
||||
SpecialInput(InputSpecialRotate, last_x, last_y, r, 0, 0, 0);
|
||||
}
|
||||
|
||||
void SubpixMotion(float x, float y, float pressure, float rotation, float tiltx, float tilty)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
SpecialInput(InputSpecialTablet, x, y, pressure, rotation, tiltx, tilty);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTextureToViewport(GLuint texid)
|
||||
{
|
||||
OpenGlRenderState::ApplyIdentity();
|
||||
glBindTexture(GL_TEXTURE_2D, texid);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
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);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
ToggleViewFunctor::ToggleViewFunctor(View& view)
|
||||
: view(view)
|
||||
{
|
||||
}
|
||||
|
||||
ToggleViewFunctor::ToggleViewFunctor(const std::string& name)
|
||||
: view(Display(name))
|
||||
{
|
||||
}
|
||||
|
||||
void ToggleViewFunctor::operator()()
|
||||
{
|
||||
view.ToggleShow();
|
||||
}
|
||||
|
||||
}
|
||||
223
thirdparty/Pangolin/src/display/image_view.cpp
vendored
Normal file
223
thirdparty/Pangolin/src/display/image_view.cpp
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
#include <pangolin/display/image_view.h>
|
||||
#include <pangolin/image/image_utils.h>
|
||||
#include <pangolin/image/image_convert.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
ImageView::ImageView()
|
||||
: offset_scale(0.0f, 1.0f), lastPressed(false), mouseReleased(false), mousePressed(false), overlayRender(true)
|
||||
{
|
||||
SetHandler(this);
|
||||
}
|
||||
|
||||
ImageView::~ImageView()
|
||||
{
|
||||
}
|
||||
|
||||
void ImageView::Render()
|
||||
{
|
||||
LoadPending();
|
||||
|
||||
glPushAttrib(GL_DEPTH_BITS);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
Activate();
|
||||
this->UpdateView();
|
||||
this->glSetViewOrtho();
|
||||
|
||||
if(tex.IsValid())
|
||||
{
|
||||
if(offset_scale.first != 0.0 || offset_scale.second != 1.0)
|
||||
{
|
||||
pangolin::GlSlUtilities::OffsetAndScale(offset_scale.first, offset_scale.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
glColor4f(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
this->glRenderTexture(tex);
|
||||
pangolin::GlSlUtilities::UseNone();
|
||||
}
|
||||
|
||||
if(overlayRender)
|
||||
{
|
||||
this->glRenderOverlay();
|
||||
}
|
||||
|
||||
if(extern_draw_function)
|
||||
{
|
||||
extern_draw_function(*this);
|
||||
}
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
void ImageView::Mouse(View& view, pangolin::MouseButton button, int x, int y, bool pressed, int button_state)
|
||||
{
|
||||
ImageViewHandler::Mouse(view, button, x, y, pressed, button_state);
|
||||
|
||||
mouseReleased = (!pressed && lastPressed);
|
||||
|
||||
mousePressed = lastPressed = (pressed && button == pangolin::MouseButtonLeft);
|
||||
}
|
||||
|
||||
void ImageView::Keyboard(View& view, unsigned char key, int x, int y, bool pressed)
|
||||
{
|
||||
if(key == 'a')
|
||||
{
|
||||
if(!tex.IsValid())
|
||||
{
|
||||
std::cerr << "ImageViewHandler does not contain valid texture." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// compute scale
|
||||
const bool have_selection = std::isfinite(GetSelection().Area()) && std::abs(GetSelection().Area()) >= 4;
|
||||
const pangolin::XYRangef froi = have_selection ? GetSelection() : GetViewToRender();
|
||||
|
||||
// Download texture so that we can take min / max
|
||||
pangolin::TypedImage img;
|
||||
tex.Download(img);
|
||||
offset_scale = pangolin::GetOffsetScale(img, pangolin::Round(froi), img.fmt);
|
||||
}
|
||||
else if(key == 'b')
|
||||
{
|
||||
if(!tex.IsValid())
|
||||
{
|
||||
std::cerr << "ImageViewHandler does not contain valid texture." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// compute scale
|
||||
const bool have_selection = std::isfinite(GetSelection().Area()) && std::abs(GetSelection().Area()) >= 4;
|
||||
const pangolin::XYRangef froi = have_selection ? GetSelection() : GetViewToRender();
|
||||
|
||||
// Download texture so that we can take min / max
|
||||
pangolin::TypedImage img;
|
||||
tex.Download(img);
|
||||
std::pair<float, float> mm = pangolin::GetMinMax(img, pangolin::Round(froi), img.fmt);
|
||||
|
||||
printf("Min / Max in Region: %f / %f\n", mm.first, mm.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
pangolin::ImageViewHandler::Keyboard(view, key, x, y, pressed);
|
||||
}
|
||||
}
|
||||
|
||||
pangolin::GlTexture& ImageView::Tex() {
|
||||
return tex;
|
||||
}
|
||||
|
||||
ImageView& ImageView::SetImage(void* ptr, size_t w, size_t h, size_t pitch, pangolin::GlPixFormat img_fmt, bool delayed_upload )
|
||||
{
|
||||
const size_t pix_bytes =
|
||||
pangolin::GlFormatChannels(img_fmt.glformat) * pangolin::GlDataTypeBytes(img_fmt.gltype);
|
||||
|
||||
const bool convert_first = (img_fmt.gltype == GL_DOUBLE);
|
||||
|
||||
if(delayed_upload || !pangolin::GetBoundWindow() || IsDevicePtr(ptr) || convert_first )
|
||||
{
|
||||
texlock.lock();
|
||||
if(!convert_first) {
|
||||
img_to_load = ManagedImage<unsigned char>(w,h,w*pix_bytes);
|
||||
PitchedCopy((char*)img_to_load.ptr, img_to_load.pitch, (char*)ptr, pitch, w * pix_bytes, h);
|
||||
img_fmt_to_load = img_fmt;
|
||||
}else if(img_fmt.gltype == GL_DOUBLE) {
|
||||
Image<double> double_image( (double*)ptr, w, h, pitch);
|
||||
img_to_load.OwnAndReinterpret(ImageConvert<float>(double_image));
|
||||
img_fmt_to_load = GlPixFormat::FromType<float>();
|
||||
}else{
|
||||
pango_print_warn("TextureView: Unable to display image.\n");
|
||||
}
|
||||
texlock.unlock();
|
||||
return *this;
|
||||
}
|
||||
|
||||
PANGO_ASSERT(pitch % pix_bytes == 0);
|
||||
const size_t stride = pitch / pix_bytes;
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
|
||||
|
||||
// Initialise if it didn't already exist or the size was too small
|
||||
if(!tex.tid || tex.width != (int)w || tex.height != (int)h ||
|
||||
tex.internal_format != img_fmt.scalable_internal_format)
|
||||
{
|
||||
fmt = img_fmt;
|
||||
SetDimensions(w, h);
|
||||
SetAspect((float)w / (float)h);
|
||||
tex.Reinitialise(w, h, img_fmt.scalable_internal_format, true, 0, img_fmt.glformat, img_fmt.gltype, ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
tex.Upload(ptr, img_fmt.glformat, img_fmt.gltype);
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ImageView& ImageView::SetImage(const pangolin::Image<unsigned char>& img, const pangolin::GlPixFormat& glfmt, bool delayed_upload )
|
||||
{
|
||||
return SetImage(img.ptr, img.w, img.h, img.pitch, glfmt, delayed_upload);
|
||||
}
|
||||
|
||||
ImageView& ImageView::SetImage(const pangolin::TypedImage& img, bool delayed_upload )
|
||||
{
|
||||
return SetImage(img.ptr, img.w, img.h, img.pitch, pangolin::GlPixFormat(img.fmt), delayed_upload);
|
||||
}
|
||||
|
||||
ImageView& ImageView::SetImage(const pangolin::GlTexture& texture)
|
||||
{
|
||||
// Initialise if it didn't already exist or the size was too small
|
||||
if(!tex.tid || tex.width != texture.width || tex.height != texture.height ||
|
||||
tex.internal_format != texture.internal_format)
|
||||
{
|
||||
SetDimensions(texture.width, texture.height);
|
||||
SetAspect((float)texture.width / (float)texture.height);
|
||||
tex.Reinitialise(texture.width, texture.height, texture.internal_format, true);
|
||||
}
|
||||
|
||||
glCopyImageSubData(
|
||||
texture.tid, GL_TEXTURE_2D, 0, 0, 0, 0, tex.tid, GL_TEXTURE_2D, 0, 0, 0, 0, tex.width, tex.height, 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ImageView::LoadPending()
|
||||
{
|
||||
if(img_to_load.ptr)
|
||||
{
|
||||
// Scoped lock
|
||||
texlock.lock();
|
||||
SetImage(img_to_load, img_fmt_to_load, false);
|
||||
img_to_load.Deallocate();
|
||||
texlock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
ImageView& ImageView::Clear()
|
||||
{
|
||||
tex.Delete();
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<float, float>& ImageView::GetOffsetScale() {
|
||||
return offset_scale;
|
||||
}
|
||||
|
||||
bool ImageView::MouseReleased() const {
|
||||
return mouseReleased;
|
||||
}
|
||||
|
||||
bool ImageView::MousePressed() const {
|
||||
return mousePressed;
|
||||
}
|
||||
|
||||
void ImageView::SetRenderOverlay(const bool& val) {
|
||||
overlayRender = val;
|
||||
}
|
||||
|
||||
}
|
||||
707
thirdparty/Pangolin/src/display/opengl_render_state.cpp
vendored
Normal file
707
thirdparty/Pangolin/src/display/opengl_render_state.cpp
vendored
Normal file
@@ -0,0 +1,707 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/display/opengl_render_state.h>
|
||||
#include <pangolin/gl/glinclude.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
inline void glLoadMatrix(const float* m) { glLoadMatrixf(m); }
|
||||
inline void glMultMatrix(const float* m) { glMultMatrixf(m); }
|
||||
|
||||
#ifndef HAVE_GLES
|
||||
inline void glLoadMatrix(const double* m) { glLoadMatrixd(m); }
|
||||
inline void glMultMatrix(const double* m) { glMultMatrixd(m); }
|
||||
#endif
|
||||
|
||||
OpenGlMatrix OpenGlMatrix::Translate(GLprecision x, GLprecision y, GLprecision z)
|
||||
{
|
||||
OpenGlMatrix mat;
|
||||
mat.SetIdentity();
|
||||
mat(0, 3) = x;
|
||||
mat(1, 3) = y;
|
||||
mat(2, 3) = z;
|
||||
return mat;
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlMatrix::Scale(GLprecision x, GLprecision y, GLprecision z)
|
||||
{
|
||||
OpenGlMatrix mat;
|
||||
mat.SetIdentity();
|
||||
mat(0, 0) = x;
|
||||
mat(1, 1) = y;
|
||||
mat(2, 2) = z;
|
||||
return mat;
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlMatrix::RotateX(GLprecision theta_rad)
|
||||
{
|
||||
OpenGlMatrix mat;
|
||||
mat.SetIdentity();
|
||||
const GLprecision costh = cos(theta_rad);
|
||||
const GLprecision sinth = sin(theta_rad);
|
||||
mat(1, 1) = costh;
|
||||
mat(1, 2) = -sinth;
|
||||
mat(2, 1) = sinth;
|
||||
mat(2, 2) = costh;
|
||||
return mat;
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlMatrix::RotateY(GLprecision theta_rad)
|
||||
{
|
||||
OpenGlMatrix mat;
|
||||
mat.SetIdentity();
|
||||
const GLprecision costh = cos(theta_rad);
|
||||
const GLprecision sinth = sin(theta_rad);
|
||||
mat(0, 0) = costh;
|
||||
mat(0, 2) = sinth;
|
||||
mat(2, 0) = -sinth;
|
||||
mat(2, 2) = costh;
|
||||
return mat;
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlMatrix::RotateZ(GLprecision theta_rad)
|
||||
{
|
||||
OpenGlMatrix mat;
|
||||
mat.SetIdentity();
|
||||
const GLprecision costh = cos(theta_rad);
|
||||
const GLprecision sinth = sin(theta_rad);
|
||||
mat(0, 0) = costh;
|
||||
mat(0, 1) = -sinth;
|
||||
mat(1, 0) = sinth;
|
||||
mat(1, 1) = costh;
|
||||
return mat;
|
||||
}
|
||||
|
||||
void OpenGlMatrix::Load() const
|
||||
{
|
||||
glLoadMatrix(m);
|
||||
}
|
||||
|
||||
void OpenGlMatrix::Multiply() const
|
||||
{
|
||||
glMultMatrix(m);
|
||||
}
|
||||
|
||||
void OpenGlMatrix::SetIdentity()
|
||||
{
|
||||
m[0] = 1.0f; m[1] = 0.0f; m[2] = 0.0f; m[3] = 0.0f;
|
||||
m[4] = 0.0f; m[5] = 1.0f; m[6] = 0.0f; m[7] = 0.0f;
|
||||
m[8] = 0.0f; m[9] = 0.0f; m[10] = 1.0f; m[11] = 0.0f;
|
||||
m[12] = 0.0f; m[13] = 0.0f; m[14] = 0.0f; m[15] = 1.0f;
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlMatrix::Transpose() const
|
||||
{
|
||||
OpenGlMatrix trans;
|
||||
trans.m[0] = m[0]; trans.m[4] = m[1]; trans.m[8] = m[2]; trans.m[12] = m[3];
|
||||
trans.m[1] = m[4]; trans.m[5] = m[5]; trans.m[9] = m[6]; trans.m[13] = m[7];
|
||||
trans.m[2] = m[8]; trans.m[6] = m[9]; trans.m[10] = m[10]; trans.m[14] = m[11];
|
||||
trans.m[3] = m[12]; trans.m[7] = m[13]; trans.m[11] = m[14]; trans.m[15] = m[15];
|
||||
return trans;
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlMatrix::Inverse() const
|
||||
{
|
||||
OpenGlMatrix inv;
|
||||
inv.m[0] = m[0]; inv.m[4] = m[1]; inv.m[8] = m[2]; inv.m[12] = -(m[0]*m[12] + m[1]*m[13] + m[2]*m[14]);
|
||||
inv.m[1] = m[4]; inv.m[5] = m[5]; inv.m[9] = m[6]; inv.m[13] = -(m[4]*m[12] + m[5]*m[13] + m[6]*m[14]);
|
||||
inv.m[2] = m[8]; inv.m[6] = m[9]; inv.m[10] = m[10]; inv.m[14] = -(m[8]*m[12] + m[9]*m[13] + m[10]*m[14]);
|
||||
inv.m[3] = 0; inv.m[7] = 0; inv.m[11] = 0; inv.m[15] = 1;
|
||||
return inv;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const OpenGlMatrix& mat)
|
||||
{
|
||||
for(int r=0; r< 4; ++r) {
|
||||
for(int c=0; c<4; ++c) {
|
||||
std::cout << mat.m[4*c+r] << '\t';
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
void OpenGlRenderState::Apply() const
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
projection[0].Load();
|
||||
|
||||
// Leave in MODEVIEW mode
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
modelview.Load();
|
||||
|
||||
if(follow) {
|
||||
T_cw.Multiply();
|
||||
}
|
||||
}
|
||||
|
||||
OpenGlMatrix& OpenGlRenderState::GetProjectionMatrix(unsigned int view)
|
||||
{
|
||||
if( projection.size() <= view ) {
|
||||
projection.resize(view+1);
|
||||
}
|
||||
return projection[view];
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlRenderState::GetProjectionMatrix(unsigned int view) const
|
||||
{
|
||||
if( projection.size() <= view ) {
|
||||
return IdentityMatrix();
|
||||
}
|
||||
return projection[view];
|
||||
}
|
||||
|
||||
OpenGlMatrix& OpenGlRenderState::GetViewOffset(unsigned int view)
|
||||
{
|
||||
if( modelview_premult.size() <= view ) {
|
||||
modelview_premult.resize(view+1);
|
||||
}
|
||||
return modelview_premult[view];
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlRenderState::GetViewOffset(unsigned int view) const
|
||||
{
|
||||
if( modelview_premult.size() <= view ) {
|
||||
return IdentityMatrix();
|
||||
}
|
||||
return modelview_premult[view];
|
||||
}
|
||||
|
||||
void OpenGlRenderState::ApplyNView(int view) const
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
projection[view].Load();
|
||||
|
||||
// Leave in MODEVIEW mode
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
OpenGlMatrix m = GetModelViewMatrix(view);
|
||||
m.Load();
|
||||
|
||||
if(follow) {
|
||||
T_cw.Multiply();
|
||||
}
|
||||
}
|
||||
|
||||
OpenGlRenderState::OpenGlRenderState()
|
||||
: modelview(IdentityMatrix()), follow(false)
|
||||
{
|
||||
projection.push_back( IdentityMatrix() );
|
||||
}
|
||||
|
||||
OpenGlRenderState::OpenGlRenderState(const OpenGlMatrix& projection_matrix)
|
||||
: modelview(IdentityMatrix()), follow(false)
|
||||
{
|
||||
projection.push_back( projection_matrix );
|
||||
}
|
||||
|
||||
OpenGlRenderState::OpenGlRenderState(const OpenGlMatrix& projection_matrix, const OpenGlMatrix& modelview_matrx)
|
||||
: modelview(modelview_matrx), follow(false)
|
||||
{
|
||||
projection.push_back( projection_matrix );
|
||||
}
|
||||
|
||||
void OpenGlRenderState::ApplyIdentity()
|
||||
{
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
OpenGlRenderState& OpenGlRenderState::SetProjectionMatrix(OpenGlMatrix m)
|
||||
{
|
||||
projection[0] = m;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OpenGlRenderState& OpenGlRenderState::SetModelViewMatrix(OpenGlMatrix m)
|
||||
{
|
||||
modelview = m;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OpenGlRenderState& OpenGlRenderState::Set(OpenGlMatrixSpec m)
|
||||
{
|
||||
switch (m.type) {
|
||||
case GlProjectionStack:
|
||||
projection[0] = m;
|
||||
break;
|
||||
case GlModelViewStack:
|
||||
modelview = m;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unexpected matrix type");
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OpenGlMatrix operator*(const OpenGlMatrix& lhs, const OpenGlMatrix& rhs)
|
||||
{
|
||||
OpenGlMatrix ret;
|
||||
pangolin::MatMul<4,4,4>(ret.m, lhs.m, rhs.m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
OpenGlMatrix& OpenGlRenderState::GetProjectionMatrix()
|
||||
{
|
||||
// guarenteed to have at least one projection matrix element
|
||||
return projection[0];
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlRenderState::GetProjectionMatrix() const
|
||||
{
|
||||
// guarenteed to have at least one projection matrix element
|
||||
return projection[0];
|
||||
}
|
||||
|
||||
OpenGlMatrix& OpenGlRenderState::GetModelViewMatrix()
|
||||
{
|
||||
return modelview;
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlRenderState::GetModelViewMatrix() const
|
||||
{
|
||||
return modelview;
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlRenderState::GetModelViewMatrix(int i) const
|
||||
{
|
||||
return modelview_premult[i] * modelview;
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlRenderState::GetProjectionModelViewMatrix() const
|
||||
{
|
||||
return GetProjectionMatrix() * GetModelViewMatrix();
|
||||
}
|
||||
|
||||
OpenGlMatrix OpenGlRenderState::GetProjectiveTextureMatrix() const
|
||||
{
|
||||
return OpenGlMatrix::Translate(0.5,0.5,0.5) * OpenGlMatrix::Scale(0.5,0.5,0.5) * GetProjectionModelViewMatrix();
|
||||
}
|
||||
|
||||
void OpenGlRenderState::EnableProjectiveTexturing() const
|
||||
{
|
||||
#ifndef HAVE_GLES
|
||||
const pangolin::OpenGlMatrix projmattrans = GetProjectiveTextureMatrix().Transpose();
|
||||
glEnable(GL_TEXTURE_GEN_S);
|
||||
glEnable(GL_TEXTURE_GEN_T);
|
||||
glEnable(GL_TEXTURE_GEN_R);
|
||||
glEnable(GL_TEXTURE_GEN_Q);
|
||||
glTexGendv(GL_S, GL_EYE_PLANE, projmattrans.m);
|
||||
glTexGendv(GL_T, GL_EYE_PLANE, projmattrans.m+4);
|
||||
glTexGendv(GL_R, GL_EYE_PLANE, projmattrans.m+8);
|
||||
glTexGendv(GL_Q, GL_EYE_PLANE, projmattrans.m+12);
|
||||
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
||||
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
||||
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
||||
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGlRenderState::DisableProjectiveTexturing() const
|
||||
{
|
||||
#ifndef HAVE_GLES
|
||||
glDisable(GL_TEXTURE_GEN_S);
|
||||
glDisable(GL_TEXTURE_GEN_T);
|
||||
glDisable(GL_TEXTURE_GEN_R);
|
||||
glDisable(GL_TEXTURE_GEN_Q);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGlRenderState::Follow(const OpenGlMatrix& T_wc, bool follow)
|
||||
{
|
||||
this->T_cw = T_wc.Inverse();
|
||||
|
||||
if(follow != this->follow) {
|
||||
if(follow) {
|
||||
const OpenGlMatrix T_vc = GetModelViewMatrix() * T_wc;
|
||||
SetModelViewMatrix(T_vc);
|
||||
this->follow = true;
|
||||
}else{
|
||||
Unfollow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGlRenderState::Unfollow()
|
||||
{
|
||||
const OpenGlMatrix T_vw = GetModelViewMatrix() * T_cw;
|
||||
SetModelViewMatrix(T_vw);
|
||||
this->follow = false;
|
||||
}
|
||||
|
||||
// Use OpenGl's default frame of reference
|
||||
OpenGlMatrixSpec ProjectionMatrix(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar )
|
||||
{
|
||||
return ProjectionMatrixRUB_BottomLeft(w,h,fu,fv,u0,v0,zNear,zFar);
|
||||
}
|
||||
|
||||
OpenGlMatrixSpec ProjectionMatrixOrthographic(GLprecision l, GLprecision r, GLprecision b, GLprecision t, GLprecision n, GLprecision f )
|
||||
{
|
||||
OpenGlMatrixSpec P;
|
||||
P.type = GlProjectionStack;
|
||||
|
||||
P.m[0] = 2/(r-l);
|
||||
P.m[1] = 0;
|
||||
P.m[2] = 0;
|
||||
P.m[3] = 0;
|
||||
|
||||
P.m[4] = 0;
|
||||
P.m[5] = 2/(t-b);
|
||||
P.m[6] = 0;
|
||||
P.m[7] = 0;
|
||||
|
||||
P.m[8] = 0;
|
||||
P.m[9] = 0;
|
||||
P.m[10] = -2/(f-n);
|
||||
P.m[11] = 0;
|
||||
|
||||
P.m[12] = -(r+l)/(r-l);
|
||||
P.m[13] = -(t+b)/(t-b);
|
||||
P.m[14] = -(f+n)/(f-n);
|
||||
P.m[15] = 1;
|
||||
|
||||
return P;
|
||||
}
|
||||
|
||||
|
||||
// Camera Axis:
|
||||
// X - Right, Y - Up, Z - Back
|
||||
// Image Origin:
|
||||
// Bottom Left
|
||||
// Caution: Principal point defined with respect to image origin (0,0) at
|
||||
// top left of top-left pixel (not center, and in different frame
|
||||
// of reference to projection function image)
|
||||
OpenGlMatrixSpec ProjectionMatrixRUB_BottomLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar )
|
||||
{
|
||||
// http://www.songho.ca/opengl/gl_projectionmatrix.html
|
||||
const GLprecision L = +(u0) * zNear / -fu;
|
||||
const GLprecision T = +(v0) * zNear / fv;
|
||||
const GLprecision R = -(w-u0) * zNear / -fu;
|
||||
const GLprecision B = -(h-v0) * zNear / fv;
|
||||
|
||||
OpenGlMatrixSpec P;
|
||||
P.type = GlProjectionStack;
|
||||
std::fill_n(P.m,4*4,0);
|
||||
|
||||
P.m[0*4+0] = 2 * zNear / (R-L);
|
||||
P.m[1*4+1] = 2 * zNear / (T-B);
|
||||
P.m[2*4+2] = -(zFar +zNear) / (zFar - zNear);
|
||||
P.m[2*4+0] = (R+L)/(R-L);
|
||||
P.m[2*4+1] = (T+B)/(T-B);
|
||||
P.m[2*4+3] = -1.0;
|
||||
P.m[3*4+2] = -(2*zFar*zNear)/(zFar-zNear);
|
||||
|
||||
return P;
|
||||
}
|
||||
|
||||
// Camera Axis:
|
||||
// X - Right, Y - Up, Z - Back
|
||||
// Image Origin:
|
||||
// Top Left
|
||||
// Caution: Principal point defined with respect to image origin (0,0) at
|
||||
// top left of top-left pixel (not center, and in different frame
|
||||
// of reference to projection function image)
|
||||
OpenGlMatrixSpec ProjectionMatrixRUB_TopLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar )
|
||||
{
|
||||
// http://www.songho.ca/opengl/gl_projectionmatrix.html
|
||||
const GLprecision L = +(u0) * zNear / -fu;
|
||||
const GLprecision R = -(w-u0) * zNear / -fu;
|
||||
const GLprecision T = -(h-v0) * zNear / fv;
|
||||
const GLprecision B = +(v0) * zNear / fv;
|
||||
|
||||
OpenGlMatrixSpec P;
|
||||
P.type = GlProjectionStack;
|
||||
std::fill_n(P.m,4*4,0);
|
||||
|
||||
P.m[0*4+0] = 2 * zNear / (R-L);
|
||||
P.m[1*4+1] = 2 * zNear / (T-B);
|
||||
P.m[2*4+2] = -(zFar +zNear) / (zFar - zNear);
|
||||
P.m[2*4+0] = (R+L)/(R-L);
|
||||
P.m[2*4+1] = (T+B)/(T-B);
|
||||
P.m[2*4+3] = -1.0;
|
||||
P.m[3*4+2] = -(2*zFar*zNear)/(zFar-zNear);
|
||||
|
||||
return P;
|
||||
}
|
||||
|
||||
// Camera Axis:
|
||||
// X - Right, Y - Down, Z - Forward
|
||||
// Image Origin:
|
||||
// Top Left
|
||||
// Pricipal point specified with image origin (0,0) at top left of top-left pixel (not center)
|
||||
OpenGlMatrixSpec ProjectionMatrixRDF_TopLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar )
|
||||
{
|
||||
// http://www.songho.ca/opengl/gl_projectionmatrix.html
|
||||
const GLprecision L = -(u0) * zNear / fu;
|
||||
const GLprecision R = +(w-u0) * zNear / fu;
|
||||
const GLprecision T = -(v0) * zNear / fv;
|
||||
const GLprecision B = +(h-v0) * zNear / fv;
|
||||
|
||||
OpenGlMatrixSpec P;
|
||||
P.type = GlProjectionStack;
|
||||
std::fill_n(P.m,4*4,0);
|
||||
|
||||
P.m[0*4+0] = 2 * zNear / (R-L);
|
||||
P.m[1*4+1] = 2 * zNear / (T-B);
|
||||
|
||||
P.m[2*4+0] = (R+L)/(L-R);
|
||||
P.m[2*4+1] = (T+B)/(B-T);
|
||||
P.m[2*4+2] = (zFar +zNear) / (zFar - zNear);
|
||||
P.m[2*4+3] = 1.0;
|
||||
|
||||
P.m[3*4+2] = (2*zFar*zNear)/(zNear - zFar);
|
||||
return P;
|
||||
}
|
||||
|
||||
// Camera Axis:
|
||||
// X - Right, Y - Down, Z - Forward
|
||||
// Image Origin:
|
||||
// Top Right
|
||||
// Pricipal point specified with image origin (0,0) at top right of top-right pixel (not center)
|
||||
OpenGlMatrixSpec ProjectionMatrixRDF_TopRight(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar )
|
||||
{
|
||||
// http://www.songho.ca/opengl/gl_projectionmatrix.html
|
||||
const GLprecision L = +(w-u0) * zNear / fu;
|
||||
const GLprecision R = -(u0) * zNear / fu;
|
||||
const GLprecision T = -(v0) * zNear / fv;
|
||||
const GLprecision B = +(h-v0) * zNear / fv;
|
||||
|
||||
OpenGlMatrixSpec P;
|
||||
P.type = GlProjectionStack;
|
||||
std::fill_n(P.m,4*4,0);
|
||||
|
||||
P.m[0*4+0] = 2 * zNear / (R-L);
|
||||
P.m[1*4+1] = 2 * zNear / (T-B);
|
||||
|
||||
P.m[2*4+0] = (R+L)/(L-R);
|
||||
P.m[2*4+1] = (T+B)/(B-T);
|
||||
P.m[2*4+2] = (zFar +zNear) / (zFar - zNear);
|
||||
P.m[2*4+3] = 1.0;
|
||||
|
||||
P.m[3*4+2] = (2*zFar*zNear)/(zNear - zFar);
|
||||
return P;
|
||||
}
|
||||
|
||||
// Camera Axis:
|
||||
// X - Right, Y - Down, Z - Forward
|
||||
// Image Origin:
|
||||
// Bottom Left
|
||||
// Pricipal point specified with image origin (0,0) at top left of top-left pixel (not center)
|
||||
OpenGlMatrixSpec ProjectionMatrixRDF_BottomLeft(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar )
|
||||
{
|
||||
// http://www.songho.ca/opengl/gl_projectionmatrix.html
|
||||
const GLprecision L = -(u0) * zNear / fu;
|
||||
const GLprecision R = +(w-u0) * zNear / fu;
|
||||
const GLprecision B = -(v0) * zNear / fv;
|
||||
const GLprecision T = +(h-v0) * zNear / fv;
|
||||
|
||||
OpenGlMatrixSpec P;
|
||||
P.type = GlProjectionStack;
|
||||
std::fill_n(P.m,4*4,0);
|
||||
|
||||
P.m[0*4+0] = 2 * zNear / (R-L);
|
||||
P.m[1*4+1] = 2 * zNear / (T-B);
|
||||
|
||||
P.m[2*4+0] = (R+L)/(L-R);
|
||||
P.m[2*4+1] = (T+B)/(B-T);
|
||||
P.m[2*4+2] = (zFar +zNear) / (zFar - zNear);
|
||||
P.m[2*4+3] = 1.0;
|
||||
|
||||
P.m[3*4+2] = (2*zFar*zNear)/(zNear - zFar);
|
||||
return P;
|
||||
}
|
||||
|
||||
// Camera Axis:
|
||||
// X - Right, Y - Down, Z - Forward
|
||||
// Image Origin:
|
||||
// Bottom Right
|
||||
// Pricipal point specified with image origin (0,0) at top right of top-right pixel (not center)
|
||||
OpenGlMatrixSpec ProjectionMatrixRDF_BottomRight(int w, int h, GLprecision fu, GLprecision fv, GLprecision u0, GLprecision v0, GLprecision zNear, GLprecision zFar )
|
||||
{
|
||||
// http://www.songho.ca/opengl/gl_projectionmatrix.html
|
||||
const GLprecision R = -(u0) * zNear / fu;
|
||||
const GLprecision L = +(w-u0) * zNear / fu;
|
||||
const GLprecision B = -(v0) * zNear / fv;
|
||||
const GLprecision T = +(h-v0) * zNear / fv;
|
||||
|
||||
OpenGlMatrixSpec P;
|
||||
P.type = GlProjectionStack;
|
||||
std::fill_n(P.m,4*4,0);
|
||||
|
||||
P.m[0*4+0] = 2 * zNear / (R-L);
|
||||
P.m[1*4+1] = 2 * zNear / (T-B);
|
||||
|
||||
P.m[2*4+0] = (R+L)/(L-R);
|
||||
P.m[2*4+1] = (T+B)/(B-T);
|
||||
P.m[2*4+2] = (zFar +zNear) / (zFar - zNear);
|
||||
P.m[2*4+3] = 1.0;
|
||||
|
||||
P.m[3*4+2] = (2*zFar*zNear)/(zNear - zFar);
|
||||
return P;
|
||||
}
|
||||
|
||||
OpenGlMatrix ModelViewLookAtRUB(GLprecision ex, GLprecision ey, GLprecision ez, GLprecision lx, GLprecision ly, GLprecision lz, GLprecision ux, GLprecision uy, GLprecision uz)
|
||||
{
|
||||
OpenGlMatrix mat;
|
||||
GLprecision* m = mat.m;
|
||||
|
||||
const GLprecision u_o[3] = {ux,uy,uz};
|
||||
|
||||
GLprecision x[3], y[3];
|
||||
GLprecision z[] = {ex - lx, ey - ly, ez - lz};
|
||||
Normalise<3>(z);
|
||||
|
||||
CrossProduct(x,u_o,z);
|
||||
CrossProduct(y,z,x);
|
||||
|
||||
// Normalize x, y
|
||||
const GLprecision lenx = Length<3>(x);
|
||||
const GLprecision leny = Length<3>(y);
|
||||
|
||||
if( lenx > 0 && leny > 0) {
|
||||
for(size_t r = 0; r < 3; ++r ) {
|
||||
x[r] /= lenx;
|
||||
y[r] /= leny;
|
||||
}
|
||||
#define M(row,col) m[col*4+row]
|
||||
M(0,0) = x[0];
|
||||
M(0,1) = x[1];
|
||||
M(0,2) = x[2];
|
||||
M(1,0) = y[0];
|
||||
M(1,1) = y[1];
|
||||
M(1,2) = y[2];
|
||||
M(2,0) = z[0];
|
||||
M(2,1) = z[1];
|
||||
M(2,2) = z[2];
|
||||
M(3,0) = 0.0;
|
||||
M(3,1) = 0.0;
|
||||
M(3,2) = 0.0;
|
||||
M(0,3) = -(M(0,0)*ex + M(0,1)*ey + M(0,2)*ez);
|
||||
M(1,3) = -(M(1,0)*ex + M(1,1)*ey + M(1,2)*ez);
|
||||
M(2,3) = -(M(2,0)*ex + M(2,1)*ey + M(2,2)*ez);
|
||||
M(3,3) = 1.0;
|
||||
#undef M
|
||||
return mat;
|
||||
}else{
|
||||
throw std::invalid_argument("'Look' and 'up' vectors cannot be parallel when calling ModelViewLookAt.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
OpenGlMatrix ModelViewLookAtRDF(GLprecision ex, GLprecision ey, GLprecision ez, GLprecision lx, GLprecision ly, GLprecision lz, GLprecision ux, GLprecision uy, GLprecision uz)
|
||||
{
|
||||
OpenGlMatrix mat;
|
||||
GLprecision* m = mat.m;
|
||||
|
||||
const GLprecision u_o[3] = {ux,uy,uz};
|
||||
|
||||
GLprecision x[3], y[3];
|
||||
GLprecision z[] = {lx - ex, ly - ey, lz - ez};
|
||||
Normalise<3>(z);
|
||||
|
||||
CrossProduct(x,z,u_o);
|
||||
CrossProduct(y,z,x);
|
||||
|
||||
// Normalize x, y
|
||||
const GLprecision lenx = Length<3>(x);
|
||||
const GLprecision leny = Length<3>(y);
|
||||
|
||||
if( lenx > 0 && leny > 0) {
|
||||
for(size_t r = 0; r < 3; ++r ) {
|
||||
x[r] /= lenx;
|
||||
y[r] /= leny;
|
||||
}
|
||||
#define M(row,col) m[col*4+row]
|
||||
M(0,0) = x[0];
|
||||
M(0,1) = x[1];
|
||||
M(0,2) = x[2];
|
||||
M(1,0) = y[0];
|
||||
M(1,1) = y[1];
|
||||
M(1,2) = y[2];
|
||||
M(2,0) = z[0];
|
||||
M(2,1) = z[1];
|
||||
M(2,2) = z[2];
|
||||
M(3,0) = 0.0;
|
||||
M(3,1) = 0.0;
|
||||
M(3,2) = 0.0;
|
||||
M(0,3) = -(M(0,0)*ex + M(0,1)*ey + M(0,2)*ez);
|
||||
M(1,3) = -(M(1,0)*ex + M(1,1)*ey + M(1,2)*ez);
|
||||
M(2,3) = -(M(2,0)*ex + M(2,1)*ey + M(2,2)*ez);
|
||||
M(3,3) = 1.0;
|
||||
#undef M
|
||||
return mat;
|
||||
}else{
|
||||
throw std::invalid_argument("'Look' and 'up' vectors cannot be parallel when calling ModelViewLookAt.");
|
||||
}
|
||||
}
|
||||
|
||||
OpenGlMatrix ModelViewLookAt(GLprecision ex, GLprecision ey, GLprecision ez, GLprecision lx, GLprecision ly, GLprecision lz, GLprecision ux, GLprecision uy, GLprecision uz)
|
||||
{
|
||||
return ModelViewLookAtRUB(ex,ey,ez,lx,ly,lz,ux,uy,uz);
|
||||
}
|
||||
|
||||
OpenGlMatrix ModelViewLookAt(GLprecision ex, GLprecision ey, GLprecision ez, GLprecision lx, GLprecision ly, GLprecision lz, AxisDirection up)
|
||||
{
|
||||
const GLprecision* u = AxisDirectionVector[up];
|
||||
return ModelViewLookAtRUB(ex,ey,ez,lx,ly,lz,u[0],u[1],u[2]);
|
||||
}
|
||||
|
||||
OpenGlMatrix IdentityMatrix()
|
||||
{
|
||||
OpenGlMatrix P;
|
||||
std::fill_n(P.m,4*4,0);
|
||||
for( int i=0; i<4; ++i ) P.m[i*4+i] = 1;
|
||||
return P;
|
||||
}
|
||||
|
||||
OpenGlMatrixSpec IdentityMatrix(OpenGlStack type)
|
||||
{
|
||||
OpenGlMatrixSpec P;
|
||||
P.type = type;
|
||||
std::fill_n(P.m,4*4,0);
|
||||
for( int i=0; i<4; ++i ) P.m[i*4+i] = 1;
|
||||
return P;
|
||||
}
|
||||
|
||||
OpenGlMatrixSpec negIdentityMatrix(OpenGlStack type)
|
||||
{
|
||||
OpenGlMatrixSpec P;
|
||||
P.type = type;
|
||||
std::fill_n(P.m,4*4,0);
|
||||
for( int i=0; i<4; ++i ) P.m[i*4+i] = -1;
|
||||
|
||||
P.m[3*4+3] =1;
|
||||
return P;
|
||||
}
|
||||
|
||||
}
|
||||
583
thirdparty/Pangolin/src/display/view.cpp
vendored
Normal file
583
thirdparty/Pangolin/src/display/view.cpp
vendored
Normal file
@@ -0,0 +1,583 @@
|
||||
/* 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/display/display.h>
|
||||
#include <pangolin/display/display_internal.h>
|
||||
#include <pangolin/display/opengl_render_state.h>
|
||||
#include <pangolin/display/view.h>
|
||||
#include <pangolin/display/viewport.h>
|
||||
#include <pangolin/gl/gl.h>
|
||||
#include <pangolin/platform.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
// Pointer to context defined in display.cpp
|
||||
extern __thread PangolinGl* context;
|
||||
|
||||
const int panal_v_margin = 6;
|
||||
|
||||
int AttachAbs( int low, int high, Attach a)
|
||||
{
|
||||
if( a.unit == Pixel ) return low + (int)a.p;
|
||||
if( a.unit == ReversePixel ) return high - (int)a.p;
|
||||
return (int)(low + a.p * (high - low));
|
||||
}
|
||||
|
||||
double AspectAreaWithinTarget(double target, double test)
|
||||
{
|
||||
if( test < target )
|
||||
return test / target;
|
||||
else
|
||||
return target / test;
|
||||
}
|
||||
|
||||
void SaveViewFromFbo(std::string prefix, View& view, float scale)
|
||||
{
|
||||
PANGOLIN_UNUSED(prefix);
|
||||
|
||||
#ifndef HAVE_GLES
|
||||
const Viewport orig = view.v;
|
||||
view.v.l = 0;
|
||||
view.v.b = 0;
|
||||
view.v.w = (int)(view.v.w * scale);
|
||||
view.v.h = (int)(view.v.h * scale);
|
||||
|
||||
const int w = view.v.w;
|
||||
const int h = view.v.h;
|
||||
|
||||
float origLineWidth;
|
||||
glGetFloatv(GL_LINE_WIDTH, &origLineWidth);
|
||||
glLineWidth(origLineWidth * scale);
|
||||
|
||||
float origPointSize;
|
||||
glGetFloatv(GL_POINT_SIZE, &origPointSize);
|
||||
glPointSize(origPointSize * scale);
|
||||
|
||||
// Create FBO
|
||||
GlTexture color(w,h);
|
||||
GlRenderBuffer depth(w,h);
|
||||
GlFramebuffer fbo(color, depth);
|
||||
|
||||
// Render into FBO
|
||||
fbo.Bind();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
view.Render();
|
||||
glFlush();
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
const PixelFormat fmt = PixelFormatFromString("RGBA32");
|
||||
TypedImage buffer(w, h, fmt );
|
||||
glReadBuffer(GL_BACK);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1); // TODO: Avoid this?
|
||||
glReadPixels(0,0,w,h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.ptr );
|
||||
SaveImage(buffer, fmt, prefix + ".png", false);
|
||||
#endif // HAVE_PNG
|
||||
|
||||
// unbind FBO
|
||||
fbo.Unbind();
|
||||
|
||||
// restore viewport / line width
|
||||
view.v = orig;
|
||||
glLineWidth(origLineWidth);
|
||||
glPointSize(origPointSize);
|
||||
#endif // HAVE_GLES
|
||||
}
|
||||
|
||||
void View::Resize(const Viewport& p)
|
||||
{
|
||||
// Compute Bounds based on specification
|
||||
v.l = AttachAbs(p.l,p.r(),left);
|
||||
v.b = AttachAbs(p.b,p.t(),bottom);
|
||||
int r = AttachAbs(p.l,p.r(),right);
|
||||
int t = AttachAbs(p.b,p.t(),top);
|
||||
|
||||
// Make sure left and right, top and bottom are correct order
|
||||
if( t < v.b ) std::swap(t,v.b);
|
||||
if( r < v.l ) std::swap(r,v.l);
|
||||
|
||||
v.w = r - v.l;
|
||||
v.h = t - v.b;
|
||||
|
||||
vp = v;
|
||||
|
||||
// Adjust based on aspect requirements
|
||||
if( aspect != 0 )
|
||||
{
|
||||
const float current_aspect = (float)v.w / (float)v.h;
|
||||
if( aspect > 0 )
|
||||
{
|
||||
// Fit to space
|
||||
if( current_aspect < aspect )
|
||||
{
|
||||
//Adjust height
|
||||
const int nh = (int)(v.w / aspect);
|
||||
v.b += vlock == LockBottom ? 0 : (vlock == LockCenter ? (v.h-nh)/2 : (v.h-nh) );
|
||||
v.h = nh;
|
||||
}else if( current_aspect > aspect )
|
||||
{
|
||||
//Adjust width
|
||||
const int nw = (int)(v.h * aspect);
|
||||
v.l += hlock == LockLeft? 0 : (hlock == LockCenter ? (v.w-nw)/2 : (v.w-nw) );
|
||||
v.w = nw;
|
||||
}
|
||||
}else{
|
||||
// Overfit
|
||||
double true_aspect = -aspect;
|
||||
if( current_aspect < true_aspect )
|
||||
{
|
||||
//Adjust width
|
||||
const int nw = (int)(v.h * true_aspect);
|
||||
v.l += hlock == LockLeft? 0 : (hlock == LockCenter ? (v.w-nw)/2 : (v.w-nw) );
|
||||
v.w = nw;
|
||||
}else if( current_aspect > true_aspect )
|
||||
{
|
||||
//Adjust height
|
||||
const int nh = (int)(v.w / true_aspect);
|
||||
v.b += vlock == LockBottom ? 0 : (vlock == LockCenter ? (v.h-nh)/2 : (v.h-nh) );
|
||||
v.h = nh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResizeChildren();
|
||||
}
|
||||
|
||||
inline int zcompare(const View* lhs, const View* rhs)
|
||||
{
|
||||
return lhs->zorder < rhs->zorder;
|
||||
}
|
||||
|
||||
void View::ResizeChildren()
|
||||
{
|
||||
if( layout == LayoutOverlay )
|
||||
{
|
||||
// Sort children into z-order
|
||||
std::sort(views.begin(), views.end(), zcompare);
|
||||
|
||||
for(std::vector<View*>::iterator iv = views.begin(); iv != views.end(); ++iv ) {
|
||||
(*iv)->Resize(v);
|
||||
}
|
||||
}else if( layout == LayoutVertical )
|
||||
{
|
||||
// Allocate space incrementally
|
||||
Viewport space = v.Inset(panal_v_margin);
|
||||
int num_children = 0;
|
||||
for(std::vector<View*>::iterator iv = views.begin(); iv != views.end(); ++iv )
|
||||
{
|
||||
if (!(*iv)->show) continue;
|
||||
num_children++;
|
||||
if(scroll_offset >= num_children ) {
|
||||
(*iv)->scroll_show = false;
|
||||
}else{
|
||||
(*iv)->scroll_show = true;
|
||||
(*iv)->Resize(space);
|
||||
space.h = (*iv)->v.b - panal_v_margin - space.b;
|
||||
}
|
||||
}
|
||||
}else if(layout == LayoutHorizontal )
|
||||
{
|
||||
// Allocate space incrementally
|
||||
const int margin = 8;
|
||||
Viewport space = v.Inset(margin);
|
||||
for(std::vector<View*>::iterator iv = views.begin(); iv != views.end(); ++iv )
|
||||
{
|
||||
(*iv)->Resize(space);
|
||||
space.w = (*iv)->v.l + margin + space.l;
|
||||
}
|
||||
}else if(layout == LayoutEqualVertical )
|
||||
{
|
||||
// Allocate vertical space equally
|
||||
const size_t visiblechildren = NumVisibleChildren();
|
||||
const float height = (float)v.h / (float)visiblechildren;
|
||||
|
||||
for( size_t i=0; i < visiblechildren; ++i) {
|
||||
Viewport space(v.l, (GLint)(v.b+(visiblechildren-1-i)*height), v.w, (GLint)(height) );
|
||||
VisibleChild(i).Resize(space);
|
||||
}
|
||||
}else if(layout == LayoutEqualHorizontal )
|
||||
{
|
||||
// Allocate vertical space equally
|
||||
const size_t visiblechildren = NumVisibleChildren();
|
||||
const float width = (float)v.w / (float)visiblechildren;
|
||||
|
||||
for( size_t i=0; i < visiblechildren; ++i) {
|
||||
Viewport space( (GLint)(v.l+i*width), v.b, (GLint)width, v.h);
|
||||
VisibleChild(i).Resize(space);
|
||||
}
|
||||
}else if(layout == LayoutEqual )
|
||||
{
|
||||
const size_t visiblechildren = NumVisibleChildren();
|
||||
// TODO: Make this neater, and make fewer assumptions!
|
||||
if( visiblechildren > 0 )
|
||||
{
|
||||
// This containers aspect
|
||||
const double this_a = std::fabs(v.aspect());
|
||||
|
||||
// Use first child with fixed aspect for all children
|
||||
double child_a = std::fabs(VisibleChild(0).aspect);
|
||||
for(size_t i=1; (child_a==0) && i < visiblechildren; ++i ) {
|
||||
child_a = std::fabs(VisibleChild(i).aspect);
|
||||
}
|
||||
|
||||
if(child_a == 0) {
|
||||
child_a = 1;
|
||||
}
|
||||
|
||||
double a = visiblechildren*child_a;
|
||||
double area = AspectAreaWithinTarget(this_a, a);
|
||||
|
||||
size_t cols = visiblechildren-1;
|
||||
for(; cols > 0; --cols)
|
||||
{
|
||||
const size_t rows = visiblechildren / cols + (visiblechildren % cols == 0 ? 0 : 1);
|
||||
const double na = cols * child_a / rows;
|
||||
const double new_area = visiblechildren*AspectAreaWithinTarget(this_a,na)/(rows*cols);
|
||||
if( new_area <= area )
|
||||
break;
|
||||
area = new_area;
|
||||
a = na;
|
||||
}
|
||||
|
||||
cols++;
|
||||
const size_t rows = visiblechildren / cols + (visiblechildren % cols == 0 ? 0 : 1);
|
||||
size_t cw, ch;
|
||||
if( a > this_a )
|
||||
{
|
||||
cw = v.w / cols;
|
||||
ch = (int)(cw / child_a); //v.h / rows;
|
||||
}else{
|
||||
ch = v.h / rows;
|
||||
cw = (int)(ch * child_a);
|
||||
}
|
||||
|
||||
for(size_t i=0; i< visiblechildren; ++i )
|
||||
{
|
||||
size_t c = i % cols;
|
||||
size_t r = i / cols;
|
||||
Viewport space( GLint(v.l + c*cw), GLint(v.t() - (r+1)*ch), GLint(cw), GLint(ch) );
|
||||
VisibleChild(i).Resize(space);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void View::Render()
|
||||
{
|
||||
if(extern_draw_function && show && scroll_show) {
|
||||
extern_draw_function(*this);
|
||||
}
|
||||
RenderChildren();
|
||||
}
|
||||
|
||||
void View::RenderChildren()
|
||||
{
|
||||
for(std::vector<View*>::iterator iv = views.begin(); iv != views.end(); ++iv )
|
||||
{
|
||||
if((*iv)->show && (*iv)->scroll_show) (*iv)->Render();
|
||||
}
|
||||
}
|
||||
|
||||
void View::Activate() const
|
||||
{
|
||||
v.Activate();
|
||||
}
|
||||
|
||||
void View::ActivateAndScissor() const
|
||||
{
|
||||
vp.Scissor();
|
||||
v.Activate();
|
||||
}
|
||||
|
||||
void View::ActivateScissorAndClear() const
|
||||
{
|
||||
vp.Scissor();
|
||||
v.Activate();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void View::Activate(const OpenGlRenderState& state ) const
|
||||
{
|
||||
v.Activate();
|
||||
state.Apply();
|
||||
}
|
||||
|
||||
void View::ActivateAndScissor(const OpenGlRenderState& state) const
|
||||
{
|
||||
vp.Scissor();
|
||||
v.Activate();
|
||||
state.Apply();
|
||||
}
|
||||
|
||||
void View::ActivateScissorAndClear(const OpenGlRenderState& state ) const
|
||||
{
|
||||
vp.Scissor();
|
||||
v.Activate();
|
||||
state.Apply();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void View::ActivatePixelOrthographic() const
|
||||
{
|
||||
v.ActivatePixelOrthographic();
|
||||
}
|
||||
|
||||
void View::ActivateIdentity() const
|
||||
{
|
||||
v.ActivateIdentity();
|
||||
}
|
||||
|
||||
GLfloat View::GetClosestDepth(int x, int y, int radius) const
|
||||
{
|
||||
// TODO: Get to work on android
|
||||
|
||||
#ifdef _MSVC_
|
||||
// MSVC Requires fixed sized arrays on stack
|
||||
radius = 5;
|
||||
const int zl = (5*2+1);
|
||||
#else
|
||||
const int zl = (radius*2+1);
|
||||
#endif
|
||||
|
||||
const int zsize = zl*zl;
|
||||
GLfloat zs[zsize];
|
||||
|
||||
#ifndef HAVE_GLES
|
||||
glReadBuffer(GL_FRONT);
|
||||
glReadPixels(x-radius,y-radius,zl,zl,GL_DEPTH_COMPONENT,GL_FLOAT,zs);
|
||||
#else
|
||||
std::fill(zs,zs+zsize, 0.8);
|
||||
#endif
|
||||
|
||||
const GLfloat mindepth = *(std::min_element(zs,zs+zsize));
|
||||
return mindepth;
|
||||
}
|
||||
|
||||
void View::GetObjectCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const
|
||||
{
|
||||
const GLint viewport[4] = {v.l,v.b,v.w,v.h};
|
||||
const OpenGlMatrix proj = cam_state.GetProjectionMatrix();
|
||||
const OpenGlMatrix mv = cam_state.GetModelViewMatrix();
|
||||
glUnProject(winx, winy, winzdepth, mv.m, proj.m, viewport, &x, &y, &z);
|
||||
}
|
||||
|
||||
void View::GetCamCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const
|
||||
{
|
||||
v.GetCamCoordinates(cam_state, winx, winy, winzdepth, x, y, z);
|
||||
}
|
||||
|
||||
View& View::SetFocus()
|
||||
{
|
||||
context->activeDisplay = this;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool View::HasFocus() const
|
||||
{
|
||||
return context->activeDisplay == this;
|
||||
}
|
||||
|
||||
View& View::SetBounds(Attach bottom, Attach top, Attach left, Attach right)
|
||||
{
|
||||
this->left = left;
|
||||
this->top = top;
|
||||
this->right = right;
|
||||
this->bottom = bottom;
|
||||
context->base.ResizeChildren();
|
||||
return *this;
|
||||
}
|
||||
|
||||
View& View::SetBounds(Attach bottom, Attach top, Attach left, Attach right, bool keep_aspect)
|
||||
{
|
||||
aspect = keep_aspect ? v.aspect() : 0;
|
||||
SetBounds(top,bottom,left,right);
|
||||
return *this;
|
||||
}
|
||||
|
||||
View& View::SetBounds(Attach bottom, Attach top, Attach left, Attach right, double aspect)
|
||||
{
|
||||
this->aspect = aspect;
|
||||
SetBounds(top,bottom,left,right);
|
||||
return *this;
|
||||
}
|
||||
|
||||
View& View::SetAspect(double aspect)
|
||||
{
|
||||
this->aspect = aspect;
|
||||
context->base.ResizeChildren();
|
||||
return *this;
|
||||
}
|
||||
|
||||
View& View::SetLock(Lock horizontal, Lock vertical )
|
||||
{
|
||||
vlock = vertical;
|
||||
hlock = horizontal;
|
||||
return *this;
|
||||
}
|
||||
|
||||
View& View::SetLayout(Layout l)
|
||||
{
|
||||
layout = l;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
View& View::AddDisplay(View& child)
|
||||
{
|
||||
// detach child from any other view, and add to this
|
||||
std::vector<View*>::iterator f = std::find(
|
||||
context->base.views.begin(), context->base.views.end(), &child
|
||||
);
|
||||
|
||||
if( f != context->base.views.end() )
|
||||
context->base.views.erase(f);
|
||||
|
||||
views.push_back(&child);
|
||||
context->base.ResizeChildren();
|
||||
return *this;
|
||||
}
|
||||
|
||||
View& View::Show(bool show)
|
||||
{
|
||||
this->show = show;
|
||||
context->base.ResizeChildren();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void View::ToggleShow()
|
||||
{
|
||||
Show(!show);
|
||||
}
|
||||
|
||||
bool View::IsShown() const
|
||||
{
|
||||
return show;
|
||||
}
|
||||
|
||||
Viewport View::GetBounds() const
|
||||
{
|
||||
return Viewport( std::max(v.l, vp.l), std::max(v.b, vp.b), std::min(v.w, vp.w), std::min(v.h, vp.h) );
|
||||
}
|
||||
|
||||
void View::SaveOnRender(const std::string& filename_prefix)
|
||||
{
|
||||
const Viewport tosave = this->v.Intersect(this->vp);
|
||||
context->screen_capture.push(std::pair<std::string,Viewport>(filename_prefix,tosave ) );
|
||||
}
|
||||
|
||||
void View::RecordOnRender(const std::string& record_uri)
|
||||
{
|
||||
PANGOLIN_UNUSED(record_uri);
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
if(!context->recorder.IsOpen()) {
|
||||
Viewport area = GetBounds();
|
||||
context->record_view = this;
|
||||
try{
|
||||
context->recorder.Open(record_uri);
|
||||
std::vector<StreamInfo> streams;
|
||||
const PixelFormat fmt = PixelFormatFromString("RGB24");
|
||||
streams.push_back( StreamInfo(fmt, area.w, area.h, area.w * fmt.bpp / 8) );
|
||||
context->recorder.SetStreams(streams);
|
||||
}catch(const std::exception& e) {
|
||||
pango_print_error("Unable to open VideoRecorder:\n\t%s\n", e.what());
|
||||
}
|
||||
}else{
|
||||
context->recorder.Close();
|
||||
}
|
||||
#else
|
||||
std::cerr << "Error: Video Support hasn't been built into this library." << std::endl;
|
||||
#endif // BUILD_PANGOLIN_VIDEO
|
||||
}
|
||||
|
||||
void View::SaveRenderNow(const std::string& filename_prefix, float scale)
|
||||
{
|
||||
SaveViewFromFbo(filename_prefix, *this, scale);
|
||||
}
|
||||
|
||||
View& View::operator[](size_t i)
|
||||
{
|
||||
return *views[i];
|
||||
}
|
||||
|
||||
size_t View::NumChildren() const
|
||||
{
|
||||
return views.size();
|
||||
}
|
||||
|
||||
size_t View::NumVisibleChildren() const
|
||||
{
|
||||
int numvis = 0;
|
||||
for(std::vector<View*>::const_iterator i=views.begin(); i!=views.end(); ++i)
|
||||
{
|
||||
if((*i)->show) {
|
||||
numvis++;
|
||||
}
|
||||
}
|
||||
return numvis;
|
||||
}
|
||||
|
||||
View& View::VisibleChild(size_t i)
|
||||
{
|
||||
size_t numvis = 0;
|
||||
for(size_t v=0; v < views.size(); ++v ) {
|
||||
if(views[v]->show) {
|
||||
if( i == numvis ) {
|
||||
return *views[v];
|
||||
}
|
||||
numvis++;
|
||||
}
|
||||
}
|
||||
// Shouldn't get here
|
||||
throw std::out_of_range("No such child.");
|
||||
}
|
||||
|
||||
View* View::FindChild(int x, int y)
|
||||
{
|
||||
// Find in reverse order to mirror draw order
|
||||
for( std::vector<View*>::const_reverse_iterator i = views.rbegin(); i != views.rend(); ++i )
|
||||
if( (*i)->show && (*i)->GetBounds().Contains(x,y) )
|
||||
return (*i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
View& View::SetHandler(Handler* h)
|
||||
{
|
||||
handler = h;
|
||||
return *this;
|
||||
}
|
||||
|
||||
View& View::SetDrawFunction(const std::function<void(View&)>& drawFunc)
|
||||
{
|
||||
extern_draw_function = drawFunc;
|
||||
return *this;
|
||||
}
|
||||
|
||||
}
|
||||
113
thirdparty/Pangolin/src/display/viewport.cpp
vendored
Normal file
113
thirdparty/Pangolin/src/display/viewport.cpp
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/display/viewport.h>
|
||||
#include <algorithm>
|
||||
#include <pangolin/utils/simple_math.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
void Viewport::Activate() const
|
||||
{
|
||||
glViewport(l,b,w,h);
|
||||
}
|
||||
|
||||
void Viewport::Scissor() const
|
||||
{
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(l,b,w,h);
|
||||
}
|
||||
|
||||
void Viewport::ActivateAndScissor() const
|
||||
{
|
||||
glViewport(l,b,w,h);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(l,b,w,h);
|
||||
}
|
||||
|
||||
|
||||
void Viewport::DisableScissor()
|
||||
{
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
bool Viewport::Contains(int x, int y) const
|
||||
{
|
||||
return l <= x && x < (l+w) && b <= y && y < (b+h);
|
||||
}
|
||||
|
||||
void Viewport::ActivatePixelOrthographic() const
|
||||
{
|
||||
Activate();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(-0.5, w-0.5, -0.5, h-0.5, -1, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
void Viewport::ActivateIdentity() const
|
||||
{
|
||||
Activate();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
|
||||
Viewport Viewport::Inset(int i) const
|
||||
{
|
||||
return Viewport(l+i, b+i, w-2*i, h-2*i);
|
||||
}
|
||||
|
||||
Viewport Viewport::Inset(int horiz, int vert) const
|
||||
{
|
||||
return Viewport(l+horiz, b+vert, w-horiz, h-vert);
|
||||
}
|
||||
|
||||
Viewport Viewport::Intersect(const Viewport& vp) const
|
||||
{
|
||||
GLint nl = std::max(l,vp.l);
|
||||
GLint nr = std::min(r(),vp.r());
|
||||
GLint nb = std::max(b,vp.b);
|
||||
GLint nt = std::min(t(),vp.t());
|
||||
return Viewport(nl,nb, nr-nl, nt-nb);
|
||||
}
|
||||
|
||||
void Viewport::GetCamCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const
|
||||
{
|
||||
const GLint viewport[4] = {l, b, w, h};
|
||||
const OpenGlMatrix proj = cam_state.GetProjectionMatrix();
|
||||
#ifndef HAVE_GLES
|
||||
glUnProject(winx, winy, winzdepth, Identity4d, proj.m, viewport, &x, &y, &z);
|
||||
#else
|
||||
glUnProject(winx, winy, winzdepth, Identity4f, proj.m, viewport, &x, &y, &z);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
680
thirdparty/Pangolin/src/display/widgets/widgets.cpp
vendored
Normal file
680
thirdparty/Pangolin/src/display/widgets/widgets.cpp
vendored
Normal file
@@ -0,0 +1,680 @@
|
||||
/* 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/display/widgets/widgets.h>
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/display_internal.h>
|
||||
#include <pangolin/gl/gldraw.h>
|
||||
#include <pangolin/var/varextra.h>
|
||||
#include <pangolin/utils/file_utils.h>
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
// Pointer to context defined in display.cpp
|
||||
extern __thread PangolinGl* context;
|
||||
|
||||
|
||||
const static GLfloat colour_s1[4] = {0.2f, 0.2f, 0.2f, 1.0f};
|
||||
const static GLfloat colour_s2[4] = {0.6f, 0.6f, 0.6f, 1.0f};
|
||||
const static GLfloat colour_bg[4] = {0.9f, 0.9f, 0.9f, 1.0f};
|
||||
const static GLfloat colour_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
const static GLfloat colour_tx[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
const static GLfloat colour_dn[4] = {1.0f, 0.7f, 0.7f, 1.0f};
|
||||
|
||||
static inline GlFont& font()
|
||||
{
|
||||
return GlFont::I();
|
||||
}
|
||||
|
||||
static inline int cb_height()
|
||||
{
|
||||
return (int)(font().Height() * 1.0);
|
||||
}
|
||||
|
||||
static inline int tab_h()
|
||||
{
|
||||
return (int)(font().Height() * 1.4);
|
||||
}
|
||||
|
||||
std::mutex display_mutex;
|
||||
|
||||
template<typename T>
|
||||
void GuiVarChanged( Var<T>& var)
|
||||
{
|
||||
VarState::I().FlagVarChanged();
|
||||
var.Meta().gui_changed = true;
|
||||
|
||||
for(std::vector<GuiVarChangedCallback>::iterator igvc = VarState::I().gui_var_changed_callbacks.begin(); igvc != VarState::I().gui_var_changed_callbacks.end(); ++igvc) {
|
||||
if( StartsWith(var.Meta().full_name, igvc->filter) ) {
|
||||
igvc->fn( igvc->data, var.Meta().full_name, var.Ref() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void glRect(Viewport v)
|
||||
{
|
||||
GLfloat vs[] = { (float)v.l,(float)v.b,
|
||||
(float)v.l,(float)v.t(),
|
||||
(float)v.r(),(float)v.t(),
|
||||
(float)v.r(),(float)v.b };
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, vs);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
void glRect(Viewport v, int inset)
|
||||
{
|
||||
glRect(v.Inset(inset));
|
||||
}
|
||||
|
||||
void DrawShadowRect(Viewport& v)
|
||||
{
|
||||
glColor4fv(colour_s2);
|
||||
glDrawRectPerimeter((GLfloat)v.l, (GLfloat)v.b, (GLfloat)v.r(), (GLfloat)v.t());
|
||||
}
|
||||
|
||||
void DrawShadowRect(Viewport& v, bool pushed)
|
||||
{
|
||||
const GLfloat* c1 = pushed ? colour_s1 : colour_s2;
|
||||
const GLfloat* c2 = pushed ? colour_s2 : colour_s1;
|
||||
|
||||
GLfloat vs[] = { (float)v.l,(float)v.b,
|
||||
(float)v.l,(float)v.t(),
|
||||
(float)v.r(),(float)v.t(),
|
||||
(float)v.r(),(float)v.b,
|
||||
(float)v.l,(float)v.b };
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, vs);
|
||||
glColor4fv(c1);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, 3);
|
||||
|
||||
glColor4fv(c2);
|
||||
glDrawArrays(GL_LINE_STRIP, 2, 3);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
}
|
||||
|
||||
Panel::Panel()
|
||||
{
|
||||
handler = &StaticHandlerScroll;
|
||||
layout = LayoutVertical;
|
||||
}
|
||||
|
||||
Panel::Panel(const std::string& auto_register_var_prefix)
|
||||
{
|
||||
handler = &StaticHandlerScroll;
|
||||
layout = LayoutVertical;
|
||||
RegisterNewVarCallback(&Panel::AddVariable,(void*)this,auto_register_var_prefix);
|
||||
ProcessHistoricCallbacks(&Panel::AddVariable,(void*)this,auto_register_var_prefix);
|
||||
}
|
||||
|
||||
void Panel::AddVariable(void* data, const std::string& name, VarValueGeneric& var, bool /*brand_new*/)
|
||||
{
|
||||
Panel* thisptr = (Panel*)data;
|
||||
|
||||
const string& title = var.Meta().friendly;
|
||||
|
||||
display_mutex.lock();
|
||||
|
||||
ViewMap::iterator pnl = context->named_managed_views.find(name);
|
||||
|
||||
// Only add if a widget by the same name doesn't
|
||||
// already exist
|
||||
if( pnl == context->named_managed_views.end() )
|
||||
{
|
||||
View* nv = NULL;
|
||||
if( !strcmp(var.TypeId(), typeid(bool).name()) ) {
|
||||
nv = (var.Meta().flags & META_FLAG_TOGGLE) ? (View*)new Checkbox(title,var) : (View*)new Button(title,var);
|
||||
} else if (!strcmp(var.TypeId(), typeid(double).name()) ||
|
||||
!strcmp(var.TypeId(), typeid(float).name()) ||
|
||||
!strcmp(var.TypeId(), typeid(int).name()) ||
|
||||
!strcmp(var.TypeId(), typeid(unsigned int).name()))
|
||||
{
|
||||
nv = new Slider(title, var);
|
||||
} else if (!strcmp(var.TypeId(), typeid(std::function<void(void)>).name() ) ) {
|
||||
nv = (View*)new FunctionButton(title, var);
|
||||
}else{
|
||||
nv = new TextInput(title,var);
|
||||
}
|
||||
if(nv) {
|
||||
context->named_managed_views[name] = nv;
|
||||
thisptr->views.push_back( nv );
|
||||
thisptr->ResizeChildren();
|
||||
}
|
||||
}
|
||||
|
||||
display_mutex.unlock();
|
||||
}
|
||||
|
||||
void Panel::Render()
|
||||
{
|
||||
#ifndef HAVE_GLES
|
||||
glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT | GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
||||
#endif
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
DisplayBase().ActivatePixelOrthographic();
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
glDisable( GL_COLOR_MATERIAL );
|
||||
glLineWidth(1.0);
|
||||
|
||||
glColor4fv(colour_bg);
|
||||
glRect(v);
|
||||
DrawShadowRect(v);
|
||||
|
||||
RenderChildren();
|
||||
|
||||
#ifndef HAVE_GLES
|
||||
glPopAttrib();
|
||||
#else
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Panel::ResizeChildren()
|
||||
{
|
||||
View::ResizeChildren();
|
||||
}
|
||||
|
||||
|
||||
View& CreatePanel(const std::string& name)
|
||||
{
|
||||
if(context->named_managed_views.find(name) != context->named_managed_views.end()) {
|
||||
throw std::runtime_error("Panel already registered with this name.");
|
||||
}
|
||||
Panel * p = new Panel(name);
|
||||
context->named_managed_views[name] = p;
|
||||
context->base.views.push_back(p);
|
||||
return *p;
|
||||
}
|
||||
|
||||
Button::Button(string title, VarValueGeneric& tv)
|
||||
: Widget<bool>(title,tv), down(false)
|
||||
{
|
||||
top = 1.0; bottom = Attach::Pix(-tab_h());
|
||||
left = 0.0; right = 1.0;
|
||||
hlock = LockLeft;
|
||||
vlock = LockBottom;
|
||||
gltext = font().Text(title);
|
||||
}
|
||||
|
||||
void Button::Mouse(View&, MouseButton button, int /*x*/, int /*y*/, bool pressed, int /*mouse_state*/)
|
||||
{
|
||||
if(button == MouseButtonLeft )
|
||||
{
|
||||
down = pressed;
|
||||
if( !pressed ) {
|
||||
var->Set(!var->Get());
|
||||
GuiVarChanged(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Button::Render()
|
||||
{
|
||||
glColor4fv(colour_fg );
|
||||
glRect(v);
|
||||
glColor4fv(colour_tx);
|
||||
gltext.DrawWindow(raster[0],raster[1]-down);
|
||||
DrawShadowRect(v, down);
|
||||
}
|
||||
|
||||
void Button::ResizeChildren()
|
||||
{
|
||||
raster[0] = floor(v.l + (v.w-gltext.Width())/2.0f);
|
||||
raster[1] = floor(v.b + (v.h-gltext.Height())/2.0f);
|
||||
}
|
||||
|
||||
FunctionButton::FunctionButton(string title, VarValueGeneric& tv)
|
||||
: Widget<std::function<void(void)> >(title, tv), down(false)
|
||||
{
|
||||
top = 1.0; bottom = Attach::Pix(-tab_h());
|
||||
left = 0.0; right = 1.0;
|
||||
hlock = LockLeft;
|
||||
vlock = LockBottom;
|
||||
gltext = font().Text(title);
|
||||
}
|
||||
|
||||
void FunctionButton::Mouse(View&, MouseButton button, int /*x*/, int /*y*/, bool pressed, int /*mouse_state*/)
|
||||
{
|
||||
if (button == MouseButtonLeft)
|
||||
{
|
||||
down = pressed;
|
||||
if (!pressed) {
|
||||
var->Get()();
|
||||
GuiVarChanged(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FunctionButton::Render()
|
||||
{
|
||||
glColor4fv(colour_fg);
|
||||
glRect(v);
|
||||
glColor4fv(colour_tx);
|
||||
gltext.DrawWindow(raster[0],raster[1]-down);
|
||||
DrawShadowRect(v, down);
|
||||
}
|
||||
|
||||
void FunctionButton::ResizeChildren()
|
||||
{
|
||||
raster[0] = v.l + (v.w - gltext.Width()) / 2.0f;
|
||||
raster[1] = v.b + (v.h - gltext.Height()) / 2.0f;
|
||||
}
|
||||
|
||||
Checkbox::Checkbox(std::string title, VarValueGeneric& tv)
|
||||
: Widget<bool>(title,tv)
|
||||
{
|
||||
top = 1.0; bottom = Attach::Pix(-tab_h());
|
||||
left = 0.0; right = 1.0;
|
||||
hlock = LockLeft;
|
||||
vlock = LockBottom;
|
||||
handler = this;
|
||||
gltext = font().Text(title);
|
||||
}
|
||||
|
||||
void Checkbox::Mouse(View&, MouseButton button, int /*x*/, int /*y*/, bool pressed, int /*mouse_state*/)
|
||||
{
|
||||
if( button == MouseButtonLeft && pressed ) {
|
||||
var->Set(!var->Get());
|
||||
GuiVarChanged(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void Checkbox::ResizeChildren()
|
||||
{
|
||||
raster[0] = v.l + cb_height() + 4.0f;
|
||||
raster[1] = v.b + (v.h-gltext.Height())/2.0f;
|
||||
const int h = v.h;
|
||||
const int t = (int)((h-cb_height()) / 2.0f);
|
||||
vcb = Viewport(v.l,v.b+t,cb_height(),cb_height());
|
||||
}
|
||||
|
||||
void Checkbox::Render()
|
||||
{
|
||||
const bool val = var->Get();
|
||||
|
||||
if( val )
|
||||
{
|
||||
glColor4fv(colour_dn);
|
||||
glRect(vcb);
|
||||
}
|
||||
glColor4fv(colour_tx);
|
||||
gltext.DrawWindow(raster[0],raster[1]);
|
||||
DrawShadowRect(vcb, val);
|
||||
}
|
||||
|
||||
inline bool IsIntegral(const char* typeidname)
|
||||
{
|
||||
// TODO: There must be a better way of doing this...
|
||||
return !strcmp(typeidname, typeid(char).name()) ||
|
||||
!strcmp(typeidname, typeid(short).name()) ||
|
||||
!strcmp(typeidname, typeid(int).name()) ||
|
||||
!strcmp(typeidname, typeid(long).name()) ||
|
||||
!strcmp(typeidname, typeid(unsigned char).name()) ||
|
||||
!strcmp(typeidname, typeid(unsigned short).name()) ||
|
||||
!strcmp(typeidname, typeid(unsigned int).name()) ||
|
||||
!strcmp(typeidname, typeid(unsigned long).name());
|
||||
}
|
||||
|
||||
Slider::Slider(std::string title, VarValueGeneric& tv)
|
||||
: Widget<double>(title+":", tv), lock_bounds(true)
|
||||
{
|
||||
top = 1.0; bottom = Attach::Pix(-tab_h());
|
||||
left = 0.0; right = 1.0;
|
||||
hlock = LockLeft;
|
||||
vlock = LockBottom;
|
||||
handler = this;
|
||||
logscale = (int)tv.Meta().logscale;
|
||||
gltext = font().Text(title);
|
||||
is_integral_type = IsIntegral(tv.TypeId());
|
||||
}
|
||||
|
||||
void Slider::Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed)
|
||||
{
|
||||
if( pressed && var->Meta().range[0] < var->Meta().range[1] )
|
||||
{
|
||||
double val = !logscale ? var->Get() : log(var->Get());
|
||||
|
||||
if(key=='-' || key=='_' || key=='=' || key=='+') {
|
||||
double inc = var->Meta().increment;
|
||||
if (key == '-') inc *= -1.0;
|
||||
if (key == '_') inc *= -0.1;
|
||||
if (key == '+') inc *= 0.1;
|
||||
const double newval = max(var->Meta().range[0], min(var->Meta().range[1], val + inc));
|
||||
var->Set( logscale ? exp(newval) : newval );
|
||||
}else if(key == 'r'){
|
||||
Reset();
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
GuiVarChanged(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void Slider::Mouse(View& view, MouseButton button, int x, int y, bool pressed, int mouse_state)
|
||||
{
|
||||
if(pressed)
|
||||
{
|
||||
// Wheel
|
||||
if( button == MouseWheelUp || button == MouseWheelDown )
|
||||
{
|
||||
// Change scale around current value
|
||||
const double frac = max(0.0,min(1.0,(double)(x - v.l)/(double)v.w));
|
||||
double val = frac * (var->Meta().range[1] - var->Meta().range[0]) + var->Meta().range[0];
|
||||
|
||||
if (logscale)
|
||||
{
|
||||
if (val<=0)
|
||||
val = std::numeric_limits<double>::min();
|
||||
else
|
||||
val = log(val);
|
||||
}
|
||||
|
||||
const double scale = (button == MouseWheelUp ? 1.2 : 1.0 / 1.2 );
|
||||
var->Meta().range[1] = val + (var->Meta().range[1] - val)*scale;
|
||||
var->Meta().range[0] = val - (val - var->Meta().range[0])*scale;
|
||||
}else{
|
||||
lock_bounds = (button == MouseButtonLeft);
|
||||
MouseMotion(view,x,y,mouse_state);
|
||||
}
|
||||
}else{
|
||||
if(!lock_bounds)
|
||||
{
|
||||
double val = !logscale ? var->Get() : log(var->Get());
|
||||
|
||||
var->Meta().range[0] = min(var->Meta().range[0], val);
|
||||
var->Meta().range[1] = max(var->Meta().range[1], val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Slider::MouseMotion(View&, int x, int /*y*/, int /*mouse_state*/)
|
||||
{
|
||||
if( var->Meta().range[0] != var->Meta().range[1] )
|
||||
{
|
||||
const double range = (var->Meta().range[1] - var->Meta().range[0]);
|
||||
const double frac = (double)(x - v.l)/(double)v.w;
|
||||
double val;
|
||||
|
||||
if( lock_bounds )
|
||||
{
|
||||
const double bfrac = max(0.0,min(1.0,frac));
|
||||
val = bfrac * range + var->Meta().range[0] ;
|
||||
}else{
|
||||
val = frac * range + var->Meta().range[0];
|
||||
}
|
||||
|
||||
if (logscale) {
|
||||
val = exp(val);
|
||||
}
|
||||
|
||||
if( is_integral_type ) {
|
||||
val = std::round(val);
|
||||
}
|
||||
|
||||
var->Set(val);
|
||||
GuiVarChanged(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Slider::ResizeChildren()
|
||||
{
|
||||
raster[0] = v.l + 2.0f;
|
||||
raster[1] = v.b + (v.h-gltext.Height())/2.0f;
|
||||
}
|
||||
|
||||
void Slider::Render()
|
||||
{
|
||||
const double val = var->Get();
|
||||
|
||||
if( var->Meta().range[0] != var->Meta().range[1] )
|
||||
{
|
||||
double rval = val;
|
||||
if (logscale)
|
||||
{
|
||||
rval = log(val);
|
||||
}
|
||||
glColor4fv(colour_fg);
|
||||
glRect(v);
|
||||
glColor4fv(colour_dn);
|
||||
const double norm_val = max(0.0,min(1.0,(rval - var->Meta().range[0]) / (var->Meta().range[1] - var->Meta().range[0])));
|
||||
glRect(Viewport(v.l,v.b, (int)(v.w*norm_val),v.h));
|
||||
DrawShadowRect(v);
|
||||
}
|
||||
|
||||
glColor4fv(colour_tx);
|
||||
if(gltext.Text() != var->Meta().friendly) {
|
||||
gltext = font().Text(var->Meta().friendly);
|
||||
}
|
||||
gltext.DrawWindow(raster[0], raster[1]);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << setprecision(4) << val;
|
||||
string str = oss.str();
|
||||
GlText glval = font().Text(str);
|
||||
const float l = glval.Width() + 2.0f;
|
||||
glval.DrawWindow( v.l + v.w - l, raster[1] );
|
||||
}
|
||||
|
||||
|
||||
TextInput::TextInput(std::string title, VarValueGeneric& tv)
|
||||
: Widget<std::string>(title+":", tv), can_edit(!(tv.Meta().flags & META_FLAG_READONLY)), do_edit(false)
|
||||
{
|
||||
top = 1.0; bottom = Attach::Pix(-tab_h());
|
||||
left = 0.0; right = 1.0;
|
||||
hlock = LockLeft;
|
||||
vlock = LockBottom;
|
||||
handler = this;
|
||||
sel[0] = -1;
|
||||
sel[1] = -1;
|
||||
gltext = font().Text(title);
|
||||
}
|
||||
|
||||
void TextInput::Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed)
|
||||
{
|
||||
if(can_edit && pressed && do_edit)
|
||||
{
|
||||
const bool selection = sel[1] > sel[0] && sel[0] >= 0;
|
||||
|
||||
if(key == 13)
|
||||
{
|
||||
var->Set(edit);
|
||||
GuiVarChanged(*this);
|
||||
|
||||
do_edit = false;
|
||||
sel[0] = sel[1] = -1;
|
||||
}else if(key == 8) {
|
||||
// backspace
|
||||
if(selection)
|
||||
{
|
||||
edit = edit.substr(0,sel[0]) + edit.substr(sel[1],edit.length()-sel[1]);
|
||||
sel[1] = sel[0];
|
||||
}else{
|
||||
if(sel[0] >0)
|
||||
{
|
||||
edit = edit.substr(0,sel[0]-1) + edit.substr(sel[0],edit.length()-sel[0]);
|
||||
sel[0]--;
|
||||
sel[1]--;
|
||||
}
|
||||
}
|
||||
}else if(key == 127){
|
||||
// delete
|
||||
if(selection)
|
||||
{
|
||||
edit = edit.substr(0,sel[0]) + edit.substr(sel[1],edit.length()-sel[1]);
|
||||
sel[1] = sel[0];
|
||||
}else{
|
||||
if(sel[0] < (int)edit.length())
|
||||
{
|
||||
edit = edit.substr(0,sel[0]) + edit.substr(sel[0]+1,edit.length()-sel[0]+1);
|
||||
}
|
||||
}
|
||||
}else if(key == 230){
|
||||
// right
|
||||
sel[0] = min((int)edit.length(),sel[0]+1);
|
||||
sel[1] = sel[0];
|
||||
}else if(key == 228){
|
||||
// left
|
||||
sel[0] = max(0,sel[0]-1);
|
||||
sel[1] = sel[0];
|
||||
}else if(key == 234){
|
||||
// home
|
||||
sel[0] = sel[1] = 0;
|
||||
}else if(key == 235){
|
||||
// end
|
||||
sel[0] = sel[1] = (int)edit.length();
|
||||
}else if(key < PANGO_SPECIAL){
|
||||
edit = edit.substr(0,sel[0]).append(1,key) + edit.substr(sel[1],edit.length()-sel[1]);
|
||||
sel[1] = sel[0];
|
||||
sel[0]++;
|
||||
sel[1]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextInput::Mouse(View& /*view*/, MouseButton button, int x, int /*y*/, bool pressed, int /*mouse_state*/)
|
||||
{
|
||||
if(can_edit && button != MouseWheelUp && button != MouseWheelDown )
|
||||
{
|
||||
|
||||
if(do_edit)
|
||||
{
|
||||
const int sl = (int)gledit.Width() + 2;
|
||||
const int rl = v.l + v.w - sl;
|
||||
int ep = (int)edit.length();
|
||||
|
||||
if( x < rl )
|
||||
{
|
||||
ep = 0;
|
||||
}else{
|
||||
for( unsigned i=0; i<edit.length(); ++i )
|
||||
{
|
||||
const int tl = (int)(rl + font().Text(edit.substr(0,i)).Width());
|
||||
if(x < tl+2)
|
||||
{
|
||||
ep = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pressed)
|
||||
{
|
||||
sel[0] = sel[1] = ep;
|
||||
}else{
|
||||
sel[1] = ep;
|
||||
}
|
||||
|
||||
if(sel[0] > sel[1])
|
||||
std::swap(sel[0],sel[1]);
|
||||
}else{
|
||||
do_edit = !pressed;
|
||||
sel[0] = 0;
|
||||
sel[1] = (int)edit.length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextInput::MouseMotion(View&, int x, int /*y*/, int /*mouse_state*/)
|
||||
{
|
||||
if(can_edit && do_edit)
|
||||
{
|
||||
const int sl = (int)gledit.Width() + 2;
|
||||
const int rl = v.l + v.w - sl;
|
||||
int ep = (int)edit.length();
|
||||
|
||||
if( x < rl )
|
||||
{
|
||||
ep = 0;
|
||||
}else{
|
||||
for( unsigned i=0; i<edit.length(); ++i )
|
||||
{
|
||||
const int tl = (int)(rl + font().Text(edit.substr(0,i)).Width());
|
||||
if(x < tl+2)
|
||||
{
|
||||
ep = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sel[1] = ep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TextInput::ResizeChildren()
|
||||
{
|
||||
raster[0] = v.l + 2.0f;
|
||||
raster[1] = v.b + (v.h-gltext.Height()) / 2.0f;
|
||||
}
|
||||
|
||||
void TextInput::Render()
|
||||
{
|
||||
if(!do_edit) edit = var->Get();
|
||||
|
||||
gledit = font().Text(edit);
|
||||
|
||||
glColor4fv(colour_fg);
|
||||
if(can_edit) glRect(v);
|
||||
|
||||
const int sl = (int)gledit.Width() + 2;
|
||||
const int rl = v.l + v.w - sl;
|
||||
|
||||
if( do_edit && sel[0] >= 0)
|
||||
{
|
||||
const int tl = (int)(rl + font().Text(edit.substr(0,sel[0])).Width());
|
||||
const int tr = (int)(rl + font().Text(edit.substr(0,sel[1])).Width());
|
||||
glColor4fv(colour_dn);
|
||||
glRect(Viewport(tl,v.b,tr-tl,v.h));
|
||||
}
|
||||
|
||||
glColor4fv(colour_tx);
|
||||
gltext.DrawWindow(raster[0], raster[1]);
|
||||
|
||||
gledit.DrawWindow((GLfloat)(rl), raster[1]);
|
||||
if(can_edit) DrawShadowRect(v);
|
||||
}
|
||||
|
||||
}
|
||||
42
thirdparty/Pangolin/src/display/window_factory.cpp
vendored
Normal file
42
thirdparty/Pangolin/src/display/window_factory.cpp
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) 2011-2017 Steven Lovegrove, Andrey Mnatsakanov
|
||||
*
|
||||
* 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/display/window.h>
|
||||
#include <pangolin/factory/factory_registry.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
template<>
|
||||
FactoryRegistry<WindowInterface>& FactoryRegistry<WindowInterface>::I()
|
||||
{
|
||||
// Singleton instance
|
||||
static FactoryRegistry instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
73
thirdparty/Pangolin/src/geometry/geometry.cpp
vendored
Normal file
73
thirdparty/Pangolin/src/geometry/geometry.cpp
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/* 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/geometry/geometry.h>
|
||||
#include <pangolin/geometry/geometry_ply.h>
|
||||
#include <pangolin/geometry/geometry_obj.h>
|
||||
|
||||
#include <pangolin/utils/file_extension.h>
|
||||
#include <pangolin/utils/file_utils.h>
|
||||
|
||||
// TODO: Should really get rid of this from API
|
||||
#include <pangolin/gl/gl.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
// TODO: Replace this with proper factory registry
|
||||
pangolin::Geometry LoadGeometry(const std::string& filename)
|
||||
{
|
||||
const std::string expanded_filename = PathExpand(filename);
|
||||
const ImageFileType ft = FileType(expanded_filename);
|
||||
if(ft == ImageFileTypePly) {
|
||||
return LoadGeometryPly(expanded_filename);
|
||||
}else if(ft == ImageFileTypeObj) {
|
||||
return LoadGeometryObj(expanded_filename);
|
||||
}else{
|
||||
throw std::runtime_error("Unsupported geometry file type.");
|
||||
}
|
||||
}
|
||||
|
||||
pangolin::Geometry::Element::Attribute MakeAttribute(GLenum datatype, size_t num_items, size_t count_per_item, void* ptr, size_t pitch_bytes)
|
||||
{
|
||||
switch(datatype) {
|
||||
case GL_FLOAT:
|
||||
return Image<float> ( (float*)ptr, count_per_item, num_items, pitch_bytes);
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return Image<uint32_t>( (uint32_t*)ptr, count_per_item, num_items, pitch_bytes);
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return Image<uint16_t>( (uint16_t*)ptr, count_per_item, num_items, pitch_bytes);
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return Image<uint8_t> ( (uint8_t*)ptr, count_per_item, num_items, pitch_bytes);
|
||||
default:
|
||||
throw std::runtime_error("Unsupported type");
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
254
thirdparty/Pangolin/src/geometry/geometry_obj.cpp
vendored
Normal file
254
thirdparty/Pangolin/src/geometry/geometry_obj.cpp
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
/* 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 <unordered_set>
|
||||
|
||||
#include <pangolin/geometry/geometry_obj.h>
|
||||
#include <tinyobj/tiny_obj_loader.h>
|
||||
#include <pangolin/utils/variadic_all.h>
|
||||
#include <pangolin/utils/simple_math.h>
|
||||
|
||||
// Needed for enum type. TODO: Make this independent of GL
|
||||
#include <pangolin/gl/glplatform.h>
|
||||
#include <pangolin/image/image_io.h>
|
||||
#include <pangolin/utils/file_utils.h>
|
||||
|
||||
namespace std {
|
||||
|
||||
template<>
|
||||
struct hash<tinyobj::index_t> {
|
||||
|
||||
std::size_t operator()(const tinyobj::index_t & t) const noexcept {
|
||||
static std::hash<int> h;
|
||||
return h(t.vertex_index) ^ h(t.normal_index) ^ h(t.texcoord_index);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace tinyobj {
|
||||
|
||||
bool operator==(const index_t a, const index_t b) {
|
||||
return a.vertex_index == b.vertex_index && a.normal_index == b.normal_index && a.texcoord_index == b.texcoord_index;
|
||||
}
|
||||
|
||||
} // namespace tinyobj
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
template<typename T>
|
||||
Geometry::Element ConvertVectorToGeometryElement(const std::vector<T>& v, size_t count_per_element, const std::string& attribute_name )
|
||||
{
|
||||
PANGO_ASSERT(v.size() % count_per_element == 0);
|
||||
const size_t num_elements = v.size() / count_per_element;
|
||||
|
||||
// Allocate buffer and copy into it
|
||||
Geometry::Element el(sizeof(T) * count_per_element, num_elements);
|
||||
el.CopyFrom(Image<T>(v.data(), count_per_element, num_elements));
|
||||
el.attributes[attribute_name] = el.template UnsafeReinterpret<T>();
|
||||
return el;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Image<T> GetImageWrapper(std::vector<T>& vec, size_t count_per_element)
|
||||
{
|
||||
PANGO_ASSERT(vec.size() % count_per_element == 0);
|
||||
if(vec.size()) {
|
||||
return Image<T>(vec.data(), count_per_element, vec.size() / count_per_element, count_per_element * sizeof(T));
|
||||
}else{
|
||||
return Image<T>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pangolin::Geometry LoadGeometryObj(const std::string& filename)
|
||||
{
|
||||
pangolin::Geometry geom;
|
||||
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string warn;
|
||||
std::string err;
|
||||
if(tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filename.c_str(), PathParent(filename).c_str())) {
|
||||
PANGO_ASSERT(attrib.vertices.size() % 3 == 0);
|
||||
PANGO_ASSERT(attrib.normals.size() % 3 == 0);
|
||||
PANGO_ASSERT(attrib.colors.size() % 3 == 0);
|
||||
PANGO_ASSERT(attrib.texcoords.size() % 2 == 0);
|
||||
|
||||
// Load textures - a bit of a hack for now.
|
||||
for(size_t i=0; i < materials.size(); ++i) {
|
||||
if(!materials[i].diffuse_texname.empty()) {
|
||||
const std::string tex_name = FormatString("texture_%",i);
|
||||
try {
|
||||
TypedImage& tex_image = geom.textures[tex_name];
|
||||
tex_image = LoadImage(PathParent(filename) + "/" + materials[i].diffuse_texname);
|
||||
const int row_bytes = tex_image.w * tex_image.fmt.bpp / 8;
|
||||
std::vector<unsigned char> tmp_row(row_bytes);
|
||||
for (std::size_t y=0; y < (tex_image.h >> 1); ++y) {
|
||||
std::memcpy(tmp_row.data(), tex_image.RowPtr(y), row_bytes);
|
||||
std::memcpy(tex_image.RowPtr(y), tex_image.RowPtr(tex_image.h - 1 - y), row_bytes);
|
||||
std::memcpy(tex_image.RowPtr(tex_image.h - 1 - y), tmp_row.data(), row_bytes);
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
pango_print_warn("Unable to read texture '%s'\n", tex_name.c_str());
|
||||
geom.textures.erase(tex_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PANGO_ASSERT(all_of(
|
||||
// [&](const size_t& v){return (v == 0) || (v == num_verts);},
|
||||
// attrib.normals.size() / 3,
|
||||
// attrib.colors.size() / 3));
|
||||
|
||||
// Get rid of color buffer if all elements are equal.
|
||||
if ( std::adjacent_find( attrib.colors.begin(), attrib.colors.end(), std::not_equal_to<float>() ) == attrib.colors.end() )
|
||||
{
|
||||
attrib.colors.clear();
|
||||
}
|
||||
|
||||
Image<float> tiny_vs = GetImageWrapper(attrib.vertices, 3);
|
||||
Image<float> tiny_ns = GetImageWrapper(attrib.normals, 3);
|
||||
Image<float> tiny_cs = GetImageWrapper(attrib.colors, 3);
|
||||
Image<float> tiny_ts = GetImageWrapper(attrib.texcoords, 2);
|
||||
|
||||
// Some vertices are used with multiple texture coordinates or multiple normals, and will need to be split.
|
||||
// First, we'll find the number of unique combinations of vertex, texture, and normal indices used, as each
|
||||
// will result in a separate vertex in the buffers
|
||||
std::unordered_map<tinyobj::index_t, std::size_t> reindex_map;
|
||||
|
||||
for(auto& shape : shapes) {
|
||||
|
||||
if(shape.mesh.indices.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t num_indices = shape.mesh.indices.size() ;
|
||||
|
||||
for(size_t i=0; i < num_indices; ++i) {
|
||||
|
||||
const tinyobj::index_t index = shape.mesh.indices[i];
|
||||
|
||||
if (reindex_map.find(index) == reindex_map.end()) {
|
||||
|
||||
reindex_map.insert(std::pair<tinyobj::index_t, std::size_t>(index, reindex_map.size()));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const int num_unique_verts = reindex_map.size();
|
||||
|
||||
// Create unified verts attribute
|
||||
auto& verts = geom.buffers["geometry"];
|
||||
Image<float> new_vs, new_ns, new_cs, new_ts;
|
||||
{
|
||||
verts.Reinitialise(sizeof(float)*(tiny_vs.w + tiny_ns.w + tiny_cs.w + tiny_ts.w),num_unique_verts);
|
||||
size_t float_offset = 0;
|
||||
if(tiny_vs.IsValid()) {
|
||||
new_vs = verts.UnsafeReinterpret<float>().SubImage(float_offset,0,3,num_unique_verts);
|
||||
verts.attributes["vertex"] = new_vs;
|
||||
float_offset += 3;
|
||||
for (auto& el : reindex_map) {
|
||||
new_vs.Row(el.second).CopyFrom(tiny_vs.Row(el.first.vertex_index));
|
||||
}
|
||||
}
|
||||
if(tiny_ns.IsValid()) {
|
||||
new_ns = verts.UnsafeReinterpret<float>().SubImage(float_offset,0,3,num_unique_verts);
|
||||
verts.attributes["normal"] = new_ns;
|
||||
float_offset += 3;
|
||||
for (auto& el : reindex_map) {
|
||||
new_ns.Row(el.second).CopyFrom(tiny_ns.Row(el.first.normal_index));
|
||||
}
|
||||
}
|
||||
if(tiny_cs.IsValid()) {
|
||||
new_cs = verts.UnsafeReinterpret<float>().SubImage(float_offset,0,3,num_unique_verts);
|
||||
verts.attributes["color"] = new_cs;
|
||||
float_offset += 3;
|
||||
for (auto& el : reindex_map) {
|
||||
new_cs.Row(el.second).CopyFrom(tiny_cs.Row(el.first.vertex_index));
|
||||
}
|
||||
}
|
||||
if(tiny_ts.IsValid()) {
|
||||
new_ts = verts.UnsafeReinterpret<float>().SubImage(float_offset,0,2,num_unique_verts);
|
||||
verts.attributes["uv"] = new_ts;
|
||||
float_offset += 2;
|
||||
for (auto& el : reindex_map) {
|
||||
new_ts.Row(el.second).CopyFrom(tiny_ts.Row(el.first.texcoord_index));
|
||||
}
|
||||
}
|
||||
PANGO_ASSERT(float_offset * sizeof(float) == verts.w);
|
||||
}
|
||||
|
||||
for(auto& shape : shapes) {
|
||||
if(shape.mesh.indices.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto faces = geom.objects.emplace(shape.name, Geometry::Element());
|
||||
|
||||
if(std::all_of( shape.mesh.num_face_vertices.begin(), shape.mesh.num_face_vertices.end(),
|
||||
[](unsigned char num){return num==3;}
|
||||
)) {
|
||||
// tri mesh
|
||||
const size_t num_indices = shape.mesh.indices.size() ;
|
||||
const size_t num_faces = shape.mesh.indices.size() / 3;
|
||||
PANGO_ASSERT(num_indices % 3 == 0);
|
||||
|
||||
// Use vert_ibo as our new IBO
|
||||
faces->second.Reinitialise(3*sizeof(uint32_t), num_faces);
|
||||
Image<uint32_t> new_ibo = faces->second.UnsafeReinterpret<uint32_t>().SubImage(0,0,3,num_faces);
|
||||
for(size_t f=0; f < num_faces; ++f) {
|
||||
for(size_t v=0; v < 3; ++v) {
|
||||
new_ibo(v,f) = reindex_map[shape.mesh.indices[3 * f + v]];
|
||||
}
|
||||
}
|
||||
faces->second.attributes["vertex_indices"] = new_ibo;
|
||||
|
||||
}else if(std::all_of( shape.mesh.num_face_vertices.begin(), shape.mesh.num_face_vertices.end(),
|
||||
[](unsigned char num){return num==4;}
|
||||
)) {
|
||||
// Quad mesh
|
||||
throw std::runtime_error("Do not support quad meshes yet.");
|
||||
}else{
|
||||
// ???
|
||||
throw std::runtime_error("Do not support meshes with mixed triangles and quads.");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
throw std::runtime_error(FormatString("Unable to load OBJ file '%'. Error: '%'", filename, err));
|
||||
}
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
}
|
||||
483
thirdparty/Pangolin/src/geometry/geometry_ply.cpp
vendored
Normal file
483
thirdparty/Pangolin/src/geometry/geometry_ply.cpp
vendored
Normal file
@@ -0,0 +1,483 @@
|
||||
/* 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/geometry/geometry_ply.h>
|
||||
|
||||
#include <pangolin/utils/file_utils.h>
|
||||
#include <pangolin/utils/variadic_all.h>
|
||||
#include <pangolin/utils/parse.h>
|
||||
#include <pangolin/utils/type_convert.h>
|
||||
#include <pangolin/utils/simple_math.h>
|
||||
|
||||
// TODO: Should really remove need for GL here.
|
||||
#include <pangolin/gl/gl.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
#define FORMAT_STRING_LIST(x) #x,
|
||||
|
||||
const char* PlyHeaderString[] = {
|
||||
PLY_HEADER_LIST(FORMAT_STRING_LIST)
|
||||
};
|
||||
|
||||
const char* PlyFormatString[] = {
|
||||
PLY_FORMAT_LIST(FORMAT_STRING_LIST)
|
||||
};
|
||||
|
||||
const char* PlyTypeString[] = {
|
||||
PLY_TYPE_LIST(FORMAT_STRING_LIST)
|
||||
};
|
||||
|
||||
#undef FORMAT_STRING_LIST
|
||||
|
||||
PLY_GROUP_LIST(PANGOLIN_DEFINE_PARSE_TOKEN)
|
||||
|
||||
void ParsePlyHeader(PlyHeaderDetails& ply, std::istream& is)
|
||||
{
|
||||
// 'Active' element for property definitions.
|
||||
int current_element = -1;
|
||||
|
||||
// Check header is correct
|
||||
PlyHeader token = ParseTokenPlyHeader(is);
|
||||
if( token != PlyHeader_ply) {
|
||||
throw std::runtime_error("Bad PLY header magic.");
|
||||
}
|
||||
ConsumeToNewline(is);
|
||||
|
||||
while(is.good() && token != PlyHeader_end_header) {
|
||||
token = ParseTokenPlyHeader(is);
|
||||
switch (token) {
|
||||
case PlyHeader_format:
|
||||
// parse PLY format and version
|
||||
ConsumeWhitespace(is);
|
||||
ply.format = ParseTokenPlyFormat(is);
|
||||
ConsumeWhitespace(is);
|
||||
ply.version = ReadToken(is);
|
||||
break;
|
||||
case PlyHeader_element:
|
||||
{
|
||||
current_element = ply.elements.size();
|
||||
PlyElementDetails el;
|
||||
el.stride_bytes = 0;
|
||||
ConsumeWhitespace(is);
|
||||
el.name = ReadToken(is);
|
||||
ConsumeWhitespace(is);
|
||||
el.num_items = FromString<int>(ReadToken(is));
|
||||
ply.elements.push_back(el);
|
||||
break;
|
||||
}
|
||||
case PlyHeader_property:
|
||||
if(current_element >= 0) {
|
||||
PlyElementDetails& el = ply.elements[current_element];
|
||||
PlyPropertyDetails prop;
|
||||
ConsumeWhitespace(is);
|
||||
const PlyType t = ParseTokenPlyType(is);
|
||||
if( t == PlyType_list) {
|
||||
ConsumeWhitespace(is);
|
||||
const PlyType idtype = ParseTokenPlyType(is);
|
||||
ConsumeWhitespace(is);
|
||||
const PlyType itemtype = ParseTokenPlyType(is);
|
||||
prop.list_index_type = PlyTypeGl[idtype];
|
||||
prop.type = PlyTypeGl[itemtype];
|
||||
prop.offset_bytes = el.stride_bytes;
|
||||
prop.num_items = -1;
|
||||
el.stride_bytes = -1;
|
||||
}else{
|
||||
prop.type = PlyTypeGl[t];
|
||||
prop.list_index_type = GL_NONE;
|
||||
prop.offset_bytes = el.stride_bytes;
|
||||
prop.num_items = 1;
|
||||
const size_t size_bytes = GlDataTypeBytes(prop.type);
|
||||
if( el.stride_bytes >= 0) {
|
||||
el.stride_bytes += size_bytes;
|
||||
}
|
||||
}
|
||||
ConsumeWhitespace(is);
|
||||
prop.name = ReadToken(is);
|
||||
el.properties.push_back(prop);
|
||||
}else{
|
||||
pango_print_warn("PLY Parser: property declaration before element. Ignoring line.");
|
||||
}
|
||||
break;
|
||||
case PlyHeader_comment:
|
||||
case PlyHeader_end_header:
|
||||
break;
|
||||
default:
|
||||
pango_print_warn("PLY Parser: Unknown token - ignoring line.");
|
||||
}
|
||||
ConsumeToNewline(is);
|
||||
}
|
||||
}
|
||||
|
||||
void ParsePlyAscii(pangolin::Geometry& /*geom*/, const PlyHeaderDetails& /*ply*/, std::istream& /*is*/)
|
||||
{
|
||||
throw std::runtime_error("Not implemented.");
|
||||
}
|
||||
|
||||
void AddVertexNormals(pangolin::Geometry& geom)
|
||||
{
|
||||
auto it_geom = geom.buffers.find("geometry");
|
||||
auto it_face = geom.objects.find("default");
|
||||
|
||||
if(it_geom != geom.buffers.end() && it_face != geom.objects.end())
|
||||
{
|
||||
const auto it_vbo = it_geom->second.attributes.find("vertex");
|
||||
const auto it_ibo = it_face->second.attributes.find("vertex_indices");
|
||||
|
||||
if(it_vbo != it_geom->second.attributes.end() && it_ibo != it_face->second.attributes.end()) {
|
||||
const auto& ibo = get<Image<uint32_t>>(it_ibo->second);
|
||||
const auto& vbo = get<Image<float>>(it_vbo->second);
|
||||
|
||||
// Assume we have triangles.
|
||||
PANGO_ASSERT(ibo.w == 3 && vbo.w == 3);
|
||||
|
||||
ManagedImage<float> vert_normals(3, vbo.h);
|
||||
ManagedImage<size_t> vert_face_count(1, vbo.h);
|
||||
vert_normals.Fill(0.0f);
|
||||
vert_face_count.Fill(0);
|
||||
|
||||
float ab[3];
|
||||
float ac[3];
|
||||
float fn[3];
|
||||
|
||||
for(size_t i=0; i < ibo.h; ++i) {
|
||||
uint32_t i0 = ibo(0,i);
|
||||
uint32_t i1 = ibo(1,i);
|
||||
uint32_t i2 = ibo(2,i);
|
||||
MatSub<3,1>(ab, vbo.RowPtr(i1), vbo.RowPtr(i0));
|
||||
MatSub<3,1>(ac, vbo.RowPtr(i2), vbo.RowPtr(i0));
|
||||
VecCross3(fn, ab, ac);
|
||||
Normalise<3>(fn);
|
||||
for(size_t v=0; v < 3; ++v) {
|
||||
MatAdd<3,1>(vert_normals.RowPtr(ibo(v,i)), vert_normals.RowPtr(ibo(v,i)), fn);
|
||||
++vert_face_count(0,ibo(v,i));
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t v=0; v < vert_normals.h; ++v) {
|
||||
// Compute average
|
||||
MatMul<3,1>(vert_normals.RowPtr(v), 1.0f / vert_face_count(0,v));
|
||||
}
|
||||
|
||||
auto& el = geom.buffers["normal"];
|
||||
(ManagedImage<float>&)el = std::move(vert_normals);
|
||||
auto& attr_norm = el.attributes["normal"];
|
||||
attr_norm = MakeAttribute(GL_FLOAT, el.h, 3, el.ptr, el.pitch);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void StandardizeXyzToVertex(pangolin::Geometry& geom)
|
||||
{
|
||||
auto it_verts = geom.buffers.find("geometry");
|
||||
|
||||
if(it_verts != geom.buffers.end()) {
|
||||
auto& verts = it_verts->second;
|
||||
auto it_x = verts.attributes.find("x");
|
||||
auto it_y = verts.attributes.find("y");
|
||||
auto it_z = verts.attributes.find("z");
|
||||
if(all_found(verts.attributes, it_x, it_y, it_z)) {
|
||||
if(verts.attributes.find("vertex") == verts.attributes.end()) {
|
||||
auto& vertex = verts.attributes["vertex"];
|
||||
auto& imx = get<Image<float>>(it_x->second);
|
||||
auto& imy = get<Image<float>>(it_y->second);
|
||||
auto& imz = get<Image<float>>(it_z->second);
|
||||
|
||||
if(imx.ptr + 1 == imy.ptr && imy.ptr + 1 == imz.ptr) {
|
||||
vertex = MakeAttribute(GL_FLOAT, verts.h, 3, imx.ptr, imx.pitch);
|
||||
}else{
|
||||
throw std::runtime_error("Ooops");
|
||||
}
|
||||
}
|
||||
verts.attributes.erase(it_x);
|
||||
verts.attributes.erase(it_y);
|
||||
verts.attributes.erase(it_z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StandardizeRgbToColor(pangolin::Geometry& geom)
|
||||
{
|
||||
auto it_verts = geom.buffers.find("geometry");
|
||||
|
||||
if(it_verts != geom.buffers.end()) {
|
||||
auto& verts = it_verts->second;
|
||||
auto it_r = verts.attributes.find("r");
|
||||
auto it_g = verts.attributes.find("g");
|
||||
auto it_b = verts.attributes.find("b");
|
||||
auto it_a = verts.attributes.find("a");
|
||||
|
||||
if(!all_found(verts.attributes, it_r, it_b, it_g)) {
|
||||
it_r = verts.attributes.find("red");
|
||||
it_g = verts.attributes.find("green");
|
||||
it_b = verts.attributes.find("blue");
|
||||
it_a = verts.attributes.find("alpha");
|
||||
}
|
||||
|
||||
if(all_found(verts.attributes, it_r, it_g, it_b)) {
|
||||
const bool have_alpha = it_a != verts.attributes.end();
|
||||
|
||||
if(verts.attributes.find("color") == verts.attributes.end()) {
|
||||
Geometry::Element::Attribute& red = it_r->second;
|
||||
Geometry::Element::Attribute& color = verts.attributes["color"];
|
||||
|
||||
// TODO: Check that these really are contiguous in memory...
|
||||
if(auto attrib = get_if<Image<float>>(&red)) {
|
||||
color = Image<float>(attrib->ptr, have_alpha ? 4 : 3, verts.h, verts.pitch);
|
||||
}else if(auto attrib = get_if<Image<uint8_t>>(&red)) {
|
||||
color = Image<uint8_t>(attrib->ptr, have_alpha ? 4 : 3, verts.h, verts.pitch);
|
||||
}else if(auto attrib = get_if<Image<uint16_t>>(&red)) {
|
||||
color = Image<uint16_t>(attrib->ptr, have_alpha ? 4 : 3, verts.h, verts.pitch);
|
||||
}else if(auto attrib = get_if<Image<uint32_t>>(&red)) {
|
||||
color = Image<uint32_t>(attrib->ptr, have_alpha ? 4 : 3, verts.h, verts.pitch);
|
||||
}
|
||||
}
|
||||
verts.attributes.erase(it_r);
|
||||
verts.attributes.erase(it_g);
|
||||
verts.attributes.erase(it_b);
|
||||
if(have_alpha) verts.attributes.erase(it_a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StandardizeMultiTextureFaceToXyzuv(pangolin::Geometry& geom)
|
||||
{
|
||||
const auto it_multi_texture_face = geom.buffers.find("multi_texture_face");
|
||||
const auto it_multi_texture_vertex = geom.buffers.find("multi_texture_vertex");
|
||||
const auto it_geom = geom.buffers.find("geometry");
|
||||
const auto it_face = geom.objects.find("default");
|
||||
|
||||
if(it_geom != geom.buffers.end() && it_face != geom.objects.end())
|
||||
{
|
||||
const auto it_vbo = it_geom->second.attributes.find("vertex");
|
||||
const auto it_ibo = it_face->second.attributes.find("vertex_indices");
|
||||
|
||||
if(all_found(geom.buffers, it_multi_texture_face, it_multi_texture_vertex) &&
|
||||
it_vbo != it_geom->second.attributes.end() &&
|
||||
it_ibo != it_face->second.attributes.end()
|
||||
) {
|
||||
const auto it_uv_ibo = it_multi_texture_face->second.attributes.find("texture_vertex_indices");
|
||||
const auto it_tx = it_multi_texture_face->second.attributes.find("tx");
|
||||
const auto it_tn = it_multi_texture_face->second.attributes.find("tn");
|
||||
|
||||
const auto it_u = it_multi_texture_vertex->second.attributes.find("u");
|
||||
const auto it_v = it_multi_texture_vertex->second.attributes.find("v");
|
||||
|
||||
if(all_found(it_multi_texture_vertex->second.attributes, it_u, it_v) &&
|
||||
it_uv_ibo != it_multi_texture_face->second.attributes.end()
|
||||
) {
|
||||
// We're going to create a new vertex buffer to hold uv's too
|
||||
auto& orig_ibo = get<Image<uint32_t>>(it_ibo->second);
|
||||
const auto& orig_xyz = get<Image<float>>(it_vbo->second);
|
||||
const auto& uv_ibo = get<Image<uint32_t>>(it_uv_ibo->second);
|
||||
const auto& u = get<Image<float>>(it_u->second);
|
||||
const auto& v = get<Image<float>>(it_v->second);
|
||||
const auto& tx = get<Image<uint8_t>>(it_tx->second);
|
||||
const auto& tn = get<Image<uint32_t>>(it_tn->second);
|
||||
|
||||
PANGO_ASSERT(u.h == v.h);
|
||||
PANGO_ASSERT(orig_ibo.w == 3 && uv_ibo.w == 3);
|
||||
|
||||
pangolin::Geometry::Element new_xyzuv(5*sizeof(float), u.h);
|
||||
Image<float> new_xyz = new_xyzuv.UnsafeReinterpret<float>().SubImage(0,0,3,new_xyzuv.h);
|
||||
Image<float> new_uv = new_xyzuv.UnsafeReinterpret<float>().SubImage(3,0,2,new_xyzuv.h);
|
||||
new_xyzuv.attributes["vertex"] = new_xyz;
|
||||
new_xyzuv.attributes["uv"] = new_uv;
|
||||
|
||||
for(size_t face=0; face < orig_ibo.h; ++face) {
|
||||
uint32_t vtn = tn(0,face);
|
||||
uint8_t vtx = tx(0,face);
|
||||
PANGO_ASSERT(vtx==0, "Haven't implemented multi-texture yet.");
|
||||
|
||||
for(size_t vert=0; vert < 3; ++vert)
|
||||
{
|
||||
uint32_t& orig_xyz_index = orig_ibo(vert,vtn);
|
||||
const uint32_t uv_index = uv_ibo(vert,face);
|
||||
PANGO_ASSERT(uv_index < new_xyzuv.h && orig_xyz_index < orig_xyz.h);
|
||||
|
||||
for(int el=0; el < 3; ++el) {
|
||||
new_xyz(el,uv_index) = orig_xyz(el,orig_xyz_index);
|
||||
}
|
||||
new_uv(0,uv_index) = u(0,uv_index);
|
||||
new_uv(1,uv_index) = v(0,uv_index);
|
||||
orig_xyz_index = uv_index;
|
||||
}
|
||||
}
|
||||
|
||||
geom.buffers["geometry"] = std::move(new_xyzuv);
|
||||
geom.buffers.erase(it_multi_texture_face);
|
||||
geom.buffers.erase(it_multi_texture_vertex);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Standardize(pangolin::Geometry& geom)
|
||||
{
|
||||
StandardizeXyzToVertex(geom);
|
||||
StandardizeRgbToColor(geom);
|
||||
StandardizeMultiTextureFaceToXyzuv(geom);
|
||||
AddVertexNormals(geom);
|
||||
}
|
||||
|
||||
inline int ReadGlIntType(GLenum type, std::istream& is)
|
||||
{
|
||||
// TODO: This seems really dodgey...
|
||||
// int may not be big enough and if the datatype is smaller will it be padded?
|
||||
int v = 0;
|
||||
is.read( (char*)&v, GlDataTypeBytes(type));
|
||||
return v;
|
||||
}
|
||||
|
||||
inline void ReadInto(std::vector<unsigned char>& vec, std::istream& is, size_t num_bytes)
|
||||
{
|
||||
const size_t current_size = vec.size();
|
||||
vec.resize(current_size + num_bytes);
|
||||
is.read((char*)vec.data() + current_size, num_bytes);
|
||||
}
|
||||
|
||||
void ParsePlyLE(pangolin::Geometry& geom, PlyHeaderDetails& ply, std::istream& is)
|
||||
{
|
||||
std::vector<uint8_t> buffer;
|
||||
|
||||
for(auto& el : ply.elements) {
|
||||
pangolin::Geometry::Element geom_el;
|
||||
|
||||
if(el.stride_bytes > 0) {
|
||||
// This will usually be the case for vertex buffers with a known number of attributes
|
||||
PANGO_ASSERT(el.num_items > 0);
|
||||
geom_el.Reinitialise(el.stride_bytes, el.num_items);
|
||||
is.read((char*)geom_el.ptr, geom_el.Area());
|
||||
}else {
|
||||
// This will generally be the case for face data (containing a list of vertex indices)
|
||||
|
||||
// Reserve enough space for a list of quads
|
||||
buffer.clear();
|
||||
buffer.reserve(el.num_items * el.properties.size() * 4);
|
||||
|
||||
for(int i=0; i< el.num_items; ++i) {
|
||||
size_t offset_bytes = 0;
|
||||
for(auto& prop : el.properties) {
|
||||
if(prop.isList()) {
|
||||
const int list_items = ReadGlIntType(prop.list_index_type, is);
|
||||
if(prop.num_items == -1) {
|
||||
prop.num_items = list_items;
|
||||
prop.offset_bytes = offset_bytes;
|
||||
}else{
|
||||
PANGO_ASSERT(prop.num_items == list_items);
|
||||
}
|
||||
}
|
||||
const size_t num_bytes = prop.num_items * GlDataTypeBytes(prop.type);
|
||||
ReadInto(buffer, is, num_bytes);
|
||||
offset_bytes += num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
// Update element stride now we know
|
||||
el.stride_bytes = 0;
|
||||
for(auto& prop : el.properties) {
|
||||
el.stride_bytes += prop.num_items * GlDataTypeBytes(prop.type);
|
||||
}
|
||||
|
||||
geom_el.Reinitialise(el.stride_bytes, el.num_items);
|
||||
PANGO_ASSERT(geom_el.SizeBytes() == buffer.size());
|
||||
std::memcpy(geom_el.ptr, buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
for(auto& prop : el.properties) {
|
||||
geom_el.attributes[prop.name] = MakeAttribute(
|
||||
prop.type, el.num_items, prop.num_items, geom_el.ptr + prop.offset_bytes, geom_el.pitch
|
||||
);
|
||||
}
|
||||
if(el.name == "vertex") {
|
||||
geom.buffers["geometry"] = std::move(geom_el);
|
||||
}else if(el.name == "face") {
|
||||
geom.objects.emplace("default", std::move(geom_el));
|
||||
}else{
|
||||
geom.buffers[el.name] = std::move(geom_el);
|
||||
}
|
||||
}
|
||||
|
||||
Standardize(geom);
|
||||
}
|
||||
|
||||
void ParsePlyBE(pangolin::Geometry& /*geom*/, const PlyHeaderDetails& /*ply*/, std::istream& /*is*/)
|
||||
{
|
||||
throw std::runtime_error("Not implemented.");
|
||||
}
|
||||
|
||||
void AttachAssociatedTexturesPly(pangolin::Geometry& geom, const std::string& filename)
|
||||
{
|
||||
// For PLY, texture names are generally implicit
|
||||
auto dot = filename.find_last_of('.');
|
||||
if(dot != filename.npos) {
|
||||
const std::string base = filename.substr(0, dot);
|
||||
for(int i=0; i < 10; ++i) {
|
||||
const std::string glob = FormatString("%_%.*", base, i);
|
||||
std::vector<std::string> file_vec;
|
||||
if(FilesMatchingWildcard(glob, file_vec)) {
|
||||
for(const auto& file : file_vec) {
|
||||
try {
|
||||
geom.textures[FormatString("texture_%",i)] = LoadImage(file);
|
||||
break;
|
||||
}catch(std::runtime_error&)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pangolin::Geometry LoadGeometryPly(const std::string& filename)
|
||||
{
|
||||
std::ifstream bFile( filename.c_str(), std::ios::in | std::ios::binary );
|
||||
if( !bFile.is_open() ) throw std::runtime_error("Unable to open PLY file: " + filename);
|
||||
|
||||
PlyHeaderDetails ply;
|
||||
ParsePlyHeader(ply, bFile);
|
||||
|
||||
// Initialise geom object
|
||||
pangolin::Geometry geom;
|
||||
|
||||
// Fill in geometry from file.
|
||||
if(ply.format == PlyFormat_ascii) {
|
||||
ParsePlyAscii(geom, ply, bFile);
|
||||
}else if(ply.format == PlyFormat_binary_little_endian) {
|
||||
ParsePlyLE(geom, ply, bFile);
|
||||
}else if(ply.format == PlyFormat_binary_big_endian) {
|
||||
ParsePlyBE(geom, ply, bFile);
|
||||
}
|
||||
|
||||
AttachAssociatedTexturesPly(geom, filename);
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
}
|
||||
142
thirdparty/Pangolin/src/geometry/glgeometry.cpp
vendored
Normal file
142
thirdparty/Pangolin/src/geometry/glgeometry.cpp
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/* 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/geometry/glgeometry.h>
|
||||
|
||||
#include <pangolin/gl/glformattraits.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
GlGeometry::Element ToGlGeometryElement(const Geometry::Element& el, GlBufferType buffertype)
|
||||
{
|
||||
GlGeometry::Element glel(buffertype, el.SizeBytes(), GL_STATIC_DRAW, el.ptr );
|
||||
for(const auto& attrib_variant : el.attributes) {
|
||||
visit([&](auto&& attrib){
|
||||
using T = std::decay_t<decltype(attrib)>;
|
||||
auto& glattrib = glel.attributes[attrib_variant.first];
|
||||
glattrib.gltype = GlFormatTraits<typename T::PixelType>::gltype;
|
||||
glattrib.count_per_element = attrib.w;
|
||||
glattrib.num_elements = attrib.h;
|
||||
glattrib.offset = (uint8_t*)attrib.ptr - el.ptr;
|
||||
glattrib.stride_bytes = attrib.pitch;
|
||||
}, attrib_variant.second);
|
||||
}
|
||||
return glel;
|
||||
}
|
||||
|
||||
GlGeometry ToGlGeometry(const Geometry& geom)
|
||||
{
|
||||
GlGeometry gl;
|
||||
for(const auto& b : geom.buffers)
|
||||
gl.buffers[b.first] = ToGlGeometryElement(b.second, GlArrayBuffer);
|
||||
|
||||
for(const auto& b : geom.objects)
|
||||
gl.objects.emplace(b.first, ToGlGeometryElement(b.second, GlElementArrayBuffer));
|
||||
|
||||
for(const auto& tex : geom.textures) {
|
||||
auto& gltex = gl.textures[tex.first];
|
||||
gltex.Load(tex.second);
|
||||
}
|
||||
return gl;
|
||||
}
|
||||
|
||||
void BindGlElement(GlSlProgram& prog, const GlGeometry::Element& el)
|
||||
{
|
||||
el.Bind();
|
||||
for(auto& a : el.attributes) {
|
||||
const GLint attrib_handle = prog.GetAttributeHandle(a.first);
|
||||
const GlGeometry::Element::Attribute& attr = a.second;
|
||||
if(attrib_handle >= 0) {
|
||||
glEnableVertexAttribArray(attrib_handle);
|
||||
glVertexAttribPointer(
|
||||
attrib_handle, attr.count_per_element, attr.gltype, GL_TRUE,
|
||||
attr.stride_bytes,
|
||||
(uint8_t*)0 + attr.offset
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnbindGlElements(GlSlProgram& prog, const GlGeometry::Element& el)
|
||||
{
|
||||
for(auto& a : el.attributes) {
|
||||
const GLint attrib_handle = prog.GetAttributeHandle(a.first);
|
||||
if(attrib_handle >= 0) {
|
||||
glDisableVertexAttribArray(attrib_handle);
|
||||
}
|
||||
}
|
||||
el.Unbind();
|
||||
}
|
||||
|
||||
void GlDraw(GlSlProgram& prog, const GlGeometry& geom, const GlTexture* matcap)
|
||||
{
|
||||
// Bind textures
|
||||
int num_tex_bound = 0;
|
||||
for(auto& tex : geom.textures) {
|
||||
glActiveTexture(GL_TEXTURE0 + num_tex_bound);
|
||||
tex.second.Bind();
|
||||
prog.SetUniform(tex.first, (int)num_tex_bound);
|
||||
++num_tex_bound;
|
||||
}
|
||||
|
||||
if(matcap) {
|
||||
glActiveTexture(GL_TEXTURE0 + num_tex_bound);
|
||||
matcap->Bind();
|
||||
prog.SetUniform("matcap", (int)num_tex_bound);
|
||||
++num_tex_bound;
|
||||
}
|
||||
|
||||
// Bind all attribute buffers
|
||||
for(auto& buffer : geom.buffers) {
|
||||
BindGlElement(prog, buffer.second);
|
||||
}
|
||||
|
||||
// Draw all geometry
|
||||
for(auto& buffer : geom.objects) {
|
||||
auto it_indices = buffer.second.attributes.find("vertex_indices");
|
||||
if(it_indices != buffer.second.attributes.end()) {
|
||||
buffer.second.Bind();
|
||||
auto& attrib = it_indices->second;
|
||||
glDrawElements(
|
||||
GL_TRIANGLES, attrib.count_per_element * attrib.num_elements,
|
||||
attrib.gltype, (uint8_t*)0 + attrib.offset
|
||||
);
|
||||
buffer.second.Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
// Unbind attribute buffers
|
||||
for(auto& buffer : geom.buffers) {
|
||||
UnbindGlElements(prog, buffer.second);
|
||||
}
|
||||
|
||||
// Unbind textures
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
}
|
||||
29
thirdparty/Pangolin/src/geometry/tinyobj.cpp
vendored
Normal file
29
thirdparty/Pangolin/src/geometry/tinyobj.cpp
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#define TINYOBJLOADER_IMPLEMENTATION
|
||||
#include <tinyobj/tiny_obj_loader.h>
|
||||
39
thirdparty/Pangolin/src/gl/compat/gl2engine.cpp
vendored
Normal file
39
thirdparty/Pangolin/src/gl/compat/gl2engine.cpp
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/* 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/gl/glinclude.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
GlEngine& glEngine()
|
||||
{
|
||||
static GlEngine engine;
|
||||
return engine;
|
||||
}
|
||||
|
||||
}
|
||||
70
thirdparty/Pangolin/src/gl/glchar.cpp
vendored
Normal file
70
thirdparty/Pangolin/src/gl/glchar.cpp
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/gl/glchar.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
GlChar::GlChar()
|
||||
: x_step(0.0f)
|
||||
{
|
||||
// Uninitialised
|
||||
}
|
||||
|
||||
GlChar::GlChar(int tw, int th, int x, int y, int w, int h, GLfloat advance, GLfloat ox, GLfloat oy)
|
||||
: x_step(advance)
|
||||
{
|
||||
const GLfloat u = (GLfloat)x / (GLfloat)tw;
|
||||
const GLfloat v = (GLfloat)y / (GLfloat)th;
|
||||
const GLfloat u2 = (GLfloat)(x + w) / (GLfloat)tw;
|
||||
const GLfloat v2 = (GLfloat)(y + h) / (GLfloat)th;
|
||||
|
||||
// Setup u,v tex coords
|
||||
vs[0] = XYUV(ox, oy, u,v );
|
||||
vs[1] = XYUV(ox, oy-h, u,v2 );
|
||||
vs[2] = XYUV(w+ox, oy-h, u2,v2 );
|
||||
vs[3] = XYUV(w+ox, oy, u2,v );
|
||||
|
||||
y_min = oy-h;
|
||||
y_max = oy;
|
||||
}
|
||||
|
||||
void GlChar::Draw() const
|
||||
{
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(XYUV), &vs[0].x);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(XYUV), &vs[0].tu);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
}
|
||||
51
thirdparty/Pangolin/src/gl/gldraw.cpp
vendored
Normal file
51
thirdparty/Pangolin/src/gl/gldraw.cpp
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <pangolin/gl/gldraw.h>
|
||||
#include <pangolin/utils/timer.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
void glRecordGraphic(float x, float y, float radius)
|
||||
{
|
||||
const int ticks = static_cast<int>(TimeNow_s());
|
||||
if( ticks % 2 )
|
||||
{
|
||||
// now, render a little red "recording" dot
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glColor3ub( 255, 0, 0 );
|
||||
glDrawCircle( x, y, radius );
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
214
thirdparty/Pangolin/src/gl/glfont.cpp
vendored
Normal file
214
thirdparty/Pangolin/src/gl/glfont.cpp
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/display/display_internal.h>
|
||||
#include <pangolin/gl/glfont.h>
|
||||
#include <pangolin/gl/glstate.h>
|
||||
#include <pangolin/image/image_io.h>
|
||||
#include <pangolin/utils/type_convert.h>
|
||||
|
||||
#if !defined(HAVE_GLES) || defined(HAVE_GLES_2)
|
||||
#include <pangolin/gl/glsl.h>
|
||||
#endif
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#define STBTT_STATIC
|
||||
|
||||
#if defined(_GCC_) || defined(_CLANG_)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wunused-function"
|
||||
# include "stb_truetype.h"
|
||||
# pragma GCC diagnostic pop
|
||||
#else
|
||||
# include "stb_truetype.h"
|
||||
#endif
|
||||
|
||||
#define MAX_TEXT_LENGTH 500
|
||||
|
||||
// Embedded fonts:
|
||||
extern const unsigned char AnonymousPro_ttf[];
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
extern __thread PangolinGl* context;
|
||||
|
||||
GlFont& GlFont::I()
|
||||
{
|
||||
if (!context->font) {
|
||||
context->font.reset(new GlFont(AnonymousPro_ttf, context->is_high_res ? 30 : 15));
|
||||
}
|
||||
return *context->font.get();
|
||||
}
|
||||
|
||||
GlFont::GlFont(const unsigned char* ttf_buffer, float pixel_height, int tex_w, int tex_h)
|
||||
{
|
||||
InitialiseFont(ttf_buffer, pixel_height, tex_w, tex_h);
|
||||
}
|
||||
|
||||
GlFont::GlFont(const std::string& filename, float pixel_height, int tex_w, int tex_h)
|
||||
{
|
||||
unsigned char* ttf_buffer = new unsigned char[1<<20];
|
||||
const size_t bytes_read = fread(ttf_buffer, 1, 1<<20, fopen(filename.c_str(), "rb"));
|
||||
if(bytes_read > 0) {
|
||||
InitialiseFont(ttf_buffer, pixel_height, tex_w, tex_h);
|
||||
}else{
|
||||
throw std::runtime_error("Unable to read font from file.");
|
||||
}
|
||||
delete[] ttf_buffer;
|
||||
}
|
||||
|
||||
GlFont::~GlFont()
|
||||
{
|
||||
delete[] font_bitmap;
|
||||
}
|
||||
|
||||
void GlFont::InitialiseFont(const unsigned char* ttf_buffer, float pixel_height, int tex_w, int tex_h)
|
||||
{
|
||||
font_height_px = pixel_height;
|
||||
this->tex_w = tex_w;
|
||||
this->tex_h = tex_h;
|
||||
font_bitmap = new unsigned char[tex_w*tex_h];
|
||||
const int offset = 0;
|
||||
|
||||
stbtt_fontinfo f;
|
||||
if (!stbtt_InitFont(&f, ttf_buffer, offset)) {
|
||||
throw std::runtime_error("Unable to initialise font");
|
||||
}
|
||||
|
||||
float scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
|
||||
|
||||
STBTT_memset(font_bitmap, 0, tex_w*tex_h);
|
||||
int x = 1;
|
||||
int y = 1;
|
||||
int bottom_y = 1;
|
||||
|
||||
// Generate bitmap and char indices
|
||||
for (int i=0; i < NUM_CHARS; ++i) {
|
||||
int advance, lsb, x0,y0,x1,y1,gw,gh;
|
||||
int g = stbtt_FindGlyphIndex(&f, FIRST_CHAR + i);
|
||||
stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
|
||||
stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
|
||||
gw = x1-x0;
|
||||
gh = y1-y0;
|
||||
if (x + gw + 1 >= tex_w)
|
||||
y = bottom_y, x = 1; // advance to next row
|
||||
if (y + gh + 1 >= tex_h) // check if it fits vertically AFTER potentially moving to next row
|
||||
throw std::runtime_error("Unable to initialise font");
|
||||
STBTT_assert(x+gw < tex_w);
|
||||
STBTT_assert(y+gh < tex_h);
|
||||
stbtt_MakeGlyphBitmap(&f, font_bitmap+x+y*tex_w, gw,gh,tex_w, scale,scale, g);
|
||||
|
||||
// Adjust offset for edges of pixels
|
||||
chardata[i] = GlChar(tex_w,tex_h, x, y, gw, gh, scale*advance, x0 -0.5f, -y0 -0.5f);
|
||||
|
||||
x = x + gw + 1;
|
||||
if (y+gh+1 > bottom_y)
|
||||
bottom_y = y+gh+1;
|
||||
}
|
||||
|
||||
// Generate kern table
|
||||
for (int i=0; i < NUM_CHARS; ++i) {
|
||||
for (int j=0; j < NUM_CHARS; ++j) {
|
||||
kern_table[i*NUM_CHARS+j] = scale * stbtt_GetCodepointKernAdvance(&f,i,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GlFont::InitialiseGlTexture()
|
||||
{
|
||||
if(font_bitmap) {
|
||||
mTex.Reinitialise(tex_w,tex_h, GL_ALPHA, true, 0, GL_ALPHA,GL_UNSIGNED_BYTE, font_bitmap);
|
||||
// mTex.SetNearestNeighbour();
|
||||
delete[] font_bitmap;
|
||||
font_bitmap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GlText GlFont::Text( const char* fmt, ... )
|
||||
{
|
||||
if(!mTex.IsValid()) InitialiseGlTexture();
|
||||
|
||||
GlText ret(mTex);
|
||||
|
||||
char text[MAX_TEXT_LENGTH];
|
||||
va_list ap;
|
||||
|
||||
if( fmt != NULL ) {
|
||||
va_start( ap, fmt );
|
||||
vsnprintf( text, MAX_TEXT_LENGTH, fmt, ap );
|
||||
va_end( ap );
|
||||
|
||||
const size_t len = strlen(text);
|
||||
char lc = ' ' - FIRST_CHAR;
|
||||
for(size_t i=0; i < len; ++i) {
|
||||
char c = text[i];
|
||||
if( !(FIRST_CHAR <= c /*&& c <FIRST_CHAR+NUM_CHARS*/) ) {
|
||||
c = ' ';
|
||||
}
|
||||
GlChar& ch = chardata[c-32];
|
||||
|
||||
// Kerning
|
||||
if(i) {
|
||||
const GLfloat kern = kern_table[ (lc-32)*NUM_CHARS + (c-32) ];
|
||||
ret.AddSpace(kern);
|
||||
}
|
||||
|
||||
ret.Add(c,ch);
|
||||
lc = c;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
GlText GlFont::Text( const std::string& str )
|
||||
{
|
||||
if(!mTex.IsValid()) InitialiseGlTexture();
|
||||
|
||||
GlText ret(mTex);
|
||||
|
||||
char lc = ' ' - FIRST_CHAR;
|
||||
for(size_t i=0; i < str.length(); ++i) {
|
||||
char c = str[i];
|
||||
if( !(FIRST_CHAR <= c /*&& c <FIRST_CHAR+NUM_CHARS*/) ) {
|
||||
c = ' ';
|
||||
}
|
||||
GlChar& ch = chardata[c-32];
|
||||
|
||||
// Kerning
|
||||
if(i) {
|
||||
const GLfloat kern = kern_table[ (lc-32)*NUM_CHARS + (c-32) ];
|
||||
ret.AddSpace(kern);
|
||||
}
|
||||
|
||||
ret.Add(c,ch);
|
||||
lc = c;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
274
thirdparty/Pangolin/src/gl/glpangoglu.cpp
vendored
Normal file
274
thirdparty/Pangolin/src/gl/glpangoglu.cpp
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
/* 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/gl/glpangoglu.h>
|
||||
#include <pangolin/utils/simple_math.h>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetError.xhtml
|
||||
static const std::unordered_map<GLenum, std::string> gl_error_string = {
|
||||
{GL_NO_ERROR, "GL_NO_ERROR: No error has been recorded."},
|
||||
{GL_INVALID_ENUM, "GL_INVALID_ENUM: An unacceptable value is specified for an enumerated argument."},
|
||||
{GL_INVALID_VALUE, "GL_INVALID_VALUE: A numeric argument is out of range."},
|
||||
{GL_INVALID_OPERATION, "GL_INVALID_OPERATION: The specified operation is not allowed in the current state."},
|
||||
{GL_INVALID_FRAMEBUFFER_OPERATION, "GL_INVALID_FRAMEBUFFER_OPERATION: The framebuffer object is not complete."},
|
||||
{GL_OUT_OF_MEMORY, "GL_OUT_OF_MEMORY: There is not enough memory left to execute the command."},
|
||||
{GL_STACK_UNDERFLOW, "GL_STACK_UNDERFLOW: An attempt has been made to perform an operation that would cause an internal stack to underflow."},
|
||||
{GL_STACK_OVERFLOW, "GL_STACK_OVERFLOW: An attempt has been made to perform an operation that would cause an internal stack to overflow."},
|
||||
};
|
||||
|
||||
const char* glErrorString(GLenum error)
|
||||
{
|
||||
return gl_error_string.count(error) ? gl_error_string.at(error).c_str() : nullptr;
|
||||
}
|
||||
|
||||
// Based on glu implementation.
|
||||
template<typename P>
|
||||
int InvertMatrix(const P m[16], P invOut[16])
|
||||
{
|
||||
P inv[16], det;
|
||||
int i;
|
||||
|
||||
inv[0] = m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15]
|
||||
+ m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
|
||||
inv[4] = -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15]
|
||||
- m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
|
||||
inv[8] = m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15]
|
||||
+ m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
|
||||
inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14]
|
||||
- m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
|
||||
inv[1] = -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15]
|
||||
- m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
|
||||
inv[5] = m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15]
|
||||
+ m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
|
||||
inv[9] = -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15]
|
||||
- m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
|
||||
inv[13] = m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14]
|
||||
+ m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
|
||||
inv[2] = m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15]
|
||||
+ m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
|
||||
inv[6] = -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15]
|
||||
- m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
|
||||
inv[10] = m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15]
|
||||
+ m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
|
||||
inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14]
|
||||
- m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
|
||||
inv[3] = -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11]
|
||||
- m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
|
||||
inv[7] = m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11]
|
||||
+ m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
|
||||
inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11]
|
||||
- m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
|
||||
inv[15] = m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10]
|
||||
+ m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
|
||||
|
||||
det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
|
||||
if (det == 0)
|
||||
return GL_FALSE;
|
||||
|
||||
det=1.0f/det;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
invOut[i] = inv[i] * det;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
// Based on glu implementation
|
||||
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)
|
||||
{
|
||||
float t1[4] = {objx, objy, objz, 1.0f};
|
||||
float t2[4];
|
||||
|
||||
MatMul<4,4,1,float>(t2, modelMatrix, t1);
|
||||
MatMul<4,4,1,float>(t1, projMatrix, t2);
|
||||
|
||||
if (t1[3] == 0.0) {
|
||||
return(GL_FALSE);
|
||||
}
|
||||
|
||||
// Normalise
|
||||
t1[0]/=t1[3];
|
||||
t1[1]/=t1[3];
|
||||
t1[2]/=t1[3];
|
||||
|
||||
// Map x, y and z to range 0-1
|
||||
t1[0]=t1[0]*0.5f+0.5f;
|
||||
t1[1]=t1[1]*0.5f+0.5f;
|
||||
t1[2]=t1[2]*0.5f+0.5f;
|
||||
|
||||
// Map x,y to viewport
|
||||
t1[0]=t1[0] * viewport[2] + viewport[0];
|
||||
t1[1]=t1[1] * viewport[3] + viewport[1];
|
||||
|
||||
*winx=t1[0];
|
||||
*winy=t1[1];
|
||||
*winz=t1[2];
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
// Based on glu implementation
|
||||
GLint glUnProject(
|
||||
float winx, float winy, float winz,
|
||||
const float mv[16],
|
||||
const float proj[16],
|
||||
const GLint viewport[4],
|
||||
float* objx, float* objy, float* objz)
|
||||
{
|
||||
float t1[16];
|
||||
|
||||
MatMul<4,4,4,float>(t1, proj, mv);
|
||||
|
||||
if (!InvertMatrix<float>(t1, t1)) {
|
||||
return(GL_FALSE);
|
||||
}
|
||||
|
||||
// Map x and y from window coordinates
|
||||
float in[4] = {winx, winy, winz, 1.0f};
|
||||
in[0] = (in[0] - viewport[0]) / viewport[2];
|
||||
in[1] = (in[1] - viewport[1]) / viewport[3];
|
||||
|
||||
// Map to range -1 to 1
|
||||
in[0] = in[0] * 2 - 1;
|
||||
in[1] = in[1] * 2 - 1;
|
||||
in[2] = in[2] * 2 - 1;
|
||||
|
||||
float out[4];
|
||||
MatMul<4,4,1,float>(out, t1, in);
|
||||
|
||||
if (out[3] == 0.0) {
|
||||
return(GL_FALSE);
|
||||
}
|
||||
|
||||
// Normalise
|
||||
out[0] /= out[3];
|
||||
out[1] /= out[3];
|
||||
out[2] /= out[3];
|
||||
|
||||
// Copy out
|
||||
*objx = out[0];
|
||||
*objy = out[1];
|
||||
*objz = out[2];
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
// Based on glu implementation
|
||||
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)
|
||||
{
|
||||
double t1[4] = {objx, objy, objz, 1.0f};
|
||||
double t2[4];
|
||||
|
||||
MatMul<4,4,1,double>(t2, modelMatrix, t1);
|
||||
MatMul<4,4,1,double>(t1, projMatrix, t2);
|
||||
|
||||
if (t1[3] == 0.0) {
|
||||
return(GL_FALSE);
|
||||
}
|
||||
|
||||
// Normalise
|
||||
t1[0]/=t1[3];
|
||||
t1[1]/=t1[3];
|
||||
t1[2]/=t1[3];
|
||||
|
||||
// Map x, y and z to range 0-1
|
||||
t1[0]=t1[0]*0.5f+0.5f;
|
||||
t1[1]=t1[1]*0.5f+0.5f;
|
||||
t1[2]=t1[2]*0.5f+0.5f;
|
||||
|
||||
// Map x,y to viewport
|
||||
t1[0]=t1[0] * viewport[2] + viewport[0];
|
||||
t1[1]=t1[1] * viewport[3] + viewport[1];
|
||||
|
||||
*winx=t1[0];
|
||||
*winy=t1[1];
|
||||
*winz=t1[2];
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
// Based on glu implementation
|
||||
GLint glUnProject(
|
||||
double winx, double winy, double winz,
|
||||
const double mv[16],
|
||||
const double proj[16],
|
||||
const GLint viewport[4],
|
||||
double* objx, double* objy, double* objz)
|
||||
{
|
||||
double t1[16];
|
||||
|
||||
MatMul<4,4,4,double>(t1, proj, mv);
|
||||
|
||||
if (!InvertMatrix<double>(t1, t1)) {
|
||||
return(GL_FALSE);
|
||||
}
|
||||
|
||||
// Map x and y from window coordinates
|
||||
double in[4] = {winx, winy, winz, 1.0f};
|
||||
in[0] = (in[0] - viewport[0]) / viewport[2];
|
||||
in[1] = (in[1] - viewport[1]) / viewport[3];
|
||||
|
||||
// Map to range -1 to 1
|
||||
in[0] = in[0] * 2 - 1;
|
||||
in[1] = in[1] * 2 - 1;
|
||||
in[2] = in[2] * 2 - 1;
|
||||
|
||||
double out[4];
|
||||
MatMul<4,4,1,double>(out, t1, in);
|
||||
|
||||
if (out[3] == 0.0) {
|
||||
return(GL_FALSE);
|
||||
}
|
||||
|
||||
// Normalise
|
||||
out[0] /= out[3];
|
||||
out[1] /= out[3];
|
||||
out[2] /= out[3];
|
||||
|
||||
// Copy out
|
||||
*objx = out[0];
|
||||
*objy = out[1];
|
||||
*objz = out[2];
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
202
thirdparty/Pangolin/src/gl/gltext.cpp
vendored
Normal file
202
thirdparty/Pangolin/src/gl/gltext.cpp
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/gl/gltext.h>
|
||||
#include <pangolin/gl/glsl.h>
|
||||
|
||||
#ifdef BUILD_PANGOLIN_GUI
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/view.h>
|
||||
#endif
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
GlText::GlText()
|
||||
: tex(NULL), width(0),
|
||||
ymin(std::numeric_limits<GLfloat>::max()),
|
||||
ymax(-std::numeric_limits<GLfloat>::max())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GlText::GlText(const GlText& txt)
|
||||
: tex(txt.tex), str(txt.str), width(txt.width),
|
||||
ymin(txt.ymin), ymax(txt.ymax), vs(txt.vs)
|
||||
{
|
||||
}
|
||||
|
||||
GlText::GlText(const GlTexture& font_tex)
|
||||
: tex(&font_tex), width(0),
|
||||
ymin(std::numeric_limits<GLfloat>::max()),
|
||||
ymax(-std::numeric_limits<GLfloat>::max())
|
||||
{
|
||||
}
|
||||
|
||||
void GlText::AddSpace(GLfloat s)
|
||||
{
|
||||
width += s;
|
||||
}
|
||||
|
||||
void GlText::Add(unsigned char c, const GlChar& glc)
|
||||
{
|
||||
GLfloat x = width;
|
||||
|
||||
vs.push_back(glc.GetVert(0) + x);
|
||||
vs.push_back(glc.GetVert(1) + x);
|
||||
vs.push_back(glc.GetVert(2) + x);
|
||||
vs.push_back(glc.GetVert(0) + x);
|
||||
vs.push_back(glc.GetVert(2) + x);
|
||||
vs.push_back(glc.GetVert(3) + x);
|
||||
|
||||
ymin = std::min(ymin, glc.YMin());
|
||||
ymax = std::max(ymax, glc.YMax());
|
||||
width = x + glc.StepX();
|
||||
|
||||
str.append(1,c);
|
||||
}
|
||||
|
||||
void GlText::Clear()
|
||||
{
|
||||
str.clear();
|
||||
vs.clear();
|
||||
width = 0;
|
||||
ymin = +std::numeric_limits<GLfloat>::max();
|
||||
ymax = -std::numeric_limits<GLfloat>::max();
|
||||
}
|
||||
|
||||
void GlText::DrawGlSl() const
|
||||
{
|
||||
#if !defined(HAVE_GLES) || defined(HAVE_GLES_2)
|
||||
if(vs.size() && tex) {
|
||||
glEnableVertexAttribArray(pangolin::DEFAULT_LOCATION_POSITION);
|
||||
glEnableVertexAttribArray(pangolin::DEFAULT_LOCATION_TEXCOORD);
|
||||
|
||||
glVertexAttribPointer(pangolin::DEFAULT_LOCATION_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(XYUV), &vs[0].x);
|
||||
glVertexAttribPointer(pangolin::DEFAULT_LOCATION_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(XYUV), &vs[0].tu);
|
||||
|
||||
tex->Bind();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vs.size() );
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glDisableVertexAttribArray(pangolin::DEFAULT_LOCATION_POSITION);
|
||||
glDisableVertexAttribArray(pangolin::DEFAULT_LOCATION_TEXCOORD);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GlText::Draw() const
|
||||
{
|
||||
if(vs.size() && tex) {
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(XYUV), &vs[0].x);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(XYUV), &vs[0].tu);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
tex->Bind();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vs.size() );
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BUILD_PANGOLIN_GUI
|
||||
void GlText::Draw(GLfloat x, GLfloat y, GLfloat z) const
|
||||
{
|
||||
// find object point (x,y,z)' in pixel coords
|
||||
GLdouble projection[16];
|
||||
GLdouble modelview[16];
|
||||
GLint view[4];
|
||||
GLdouble scrn[3];
|
||||
|
||||
#ifdef HAVE_GLES_2
|
||||
std::copy(glEngine().projection.top().m, glEngine().projection.top().m+16, projection);
|
||||
std::copy(glEngine().modelview.top().m, 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,
|
||||
scrn, scrn + 1, scrn + 2);
|
||||
|
||||
DisplayBase().Activate();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(-0.5, DisplayBase().v.w-0.5, -0.5, DisplayBase().v.h-0.5, -1, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glTranslatef(std::floor((GLfloat)scrn[0]), std::floor((GLfloat)scrn[1]), (GLfloat)scrn[2]);
|
||||
Draw();
|
||||
|
||||
// Restore viewport
|
||||
glViewport(view[0],view[1],view[2],view[3]);
|
||||
|
||||
// Restore modelview / project matrices
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// Render at (x,y) in window coordinates.
|
||||
void GlText::DrawWindow(GLfloat x, GLfloat y, GLfloat z) const
|
||||
{
|
||||
// Backup viewport
|
||||
GLint view[4];
|
||||
glGetIntegerv(GL_VIEWPORT, view );
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
DisplayBase().ActivatePixelOrthographic();
|
||||
|
||||
glTranslatef( std::floor(x), std::floor(y), z);
|
||||
Draw();
|
||||
|
||||
// Restore viewport
|
||||
glViewport(view[0],view[1],view[2],view[3]);
|
||||
|
||||
// Restore modelview / project matrices
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
#endif // BUILD_PANGOLIN_GUI
|
||||
|
||||
|
||||
}
|
||||
38
thirdparty/Pangolin/src/gl/gltexturecache.cpp
vendored
Normal file
38
thirdparty/Pangolin/src/gl/gltexturecache.cpp
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/gl/gltexturecache.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
TextureCache& TextureCache::I() {
|
||||
static TextureCache instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
4882
thirdparty/Pangolin/src/gl/stb_truetype.h
vendored
Normal file
4882
thirdparty/Pangolin/src/gl/stb_truetype.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
401
thirdparty/Pangolin/src/handler/handler.cpp
vendored
Normal file
401
thirdparty/Pangolin/src/handler/handler.cpp
vendored
Normal file
@@ -0,0 +1,401 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/handler/handler.h>
|
||||
#include <pangolin/display/display_internal.h>
|
||||
#include <pangolin/display/view.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
// Pointer to context defined in display.cpp
|
||||
extern __thread PangolinGl* context;
|
||||
|
||||
void Handler::Keyboard(View& d, unsigned char key, int x, int y, bool pressed)
|
||||
{
|
||||
View* child = d.FindChild(x,y);
|
||||
if( child)
|
||||
{
|
||||
context->activeDisplay = child;
|
||||
if( child->handler)
|
||||
child->handler->Keyboard(*child,key,x,y,pressed);
|
||||
}
|
||||
}
|
||||
|
||||
void Handler::Mouse(View& d, MouseButton button, int x, int y, bool pressed, int button_state)
|
||||
{
|
||||
View* child = d.FindChild(x,y);
|
||||
if( child )
|
||||
{
|
||||
context->activeDisplay = child;
|
||||
if( child->handler)
|
||||
child->handler->Mouse(*child,button,x,y,pressed,button_state);
|
||||
}
|
||||
}
|
||||
|
||||
void Handler::MouseMotion(View& d, int x, int y, int button_state)
|
||||
{
|
||||
View* child = d.FindChild(x,y);
|
||||
if( child )
|
||||
{
|
||||
context->activeDisplay = child;
|
||||
if( child->handler)
|
||||
child->handler->MouseMotion(*child,x,y,button_state);
|
||||
}
|
||||
}
|
||||
|
||||
void Handler::PassiveMouseMotion(View& d, int x, int y, int button_state)
|
||||
{
|
||||
View* child = d.FindChild(x,y);
|
||||
if( child )
|
||||
{
|
||||
if( child->handler)
|
||||
child->handler->PassiveMouseMotion(*child,x,y,button_state);
|
||||
}
|
||||
}
|
||||
|
||||
void Handler::Special(View& d, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state)
|
||||
{
|
||||
View* child = d.FindChild( (int)x, (int)y);
|
||||
if( child )
|
||||
{
|
||||
context->activeDisplay = child;
|
||||
if( child->handler)
|
||||
child->handler->Special(*child,inType, x,y, p1, p2, p3, p4, button_state);
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerScroll::Mouse(View& d, MouseButton button, int x, int y, bool pressed, int button_state)
|
||||
{
|
||||
if( pressed && (button == MouseWheelUp || button == MouseWheelDown) )
|
||||
{
|
||||
if( button == MouseWheelUp) d.scroll_offset -= 1;
|
||||
if( button == MouseWheelDown) d.scroll_offset += 1;
|
||||
d.scroll_offset = std::max(0, std::min(d.scroll_offset, (int)d.NumVisibleChildren()-1) );
|
||||
d.ResizeChildren();
|
||||
}else{
|
||||
Handler::Mouse(d,button,x,y,pressed,button_state);
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerScroll::Special(View& d, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state)
|
||||
{
|
||||
if( inType == InputSpecialScroll )
|
||||
{
|
||||
d.scroll_offset -= (int)(p2 / fabs(p2));
|
||||
d.scroll_offset = std::max(0, std::min(d.scroll_offset, (int)d.NumVisibleChildren()-1) );
|
||||
d.ResizeChildren();
|
||||
}else{
|
||||
Handler::Special(d,inType,x,y,p1,p2,p3,p4,button_state);
|
||||
}
|
||||
}
|
||||
|
||||
Handler3D::Handler3D(OpenGlRenderState& cam_state, AxisDirection enforce_up, float trans_scale, float zoom_fraction)
|
||||
: cam_state(&cam_state), enforce_up(enforce_up), tf(trans_scale), zf(zoom_fraction), cameraspec(CameraSpecOpenGl), last_z(0.8)
|
||||
{
|
||||
SetZero<3,1>(rot_center);
|
||||
}
|
||||
|
||||
void Handler3D::Keyboard(View&, unsigned char /*key*/, int /*x*/, int /*y*/, bool /*pressed*/)
|
||||
{
|
||||
// TODO: hooks for reset / changing mode (perspective / ortho etc)
|
||||
}
|
||||
|
||||
bool Handler3D::ValidWinDepth(GLprecision depth)
|
||||
{
|
||||
return depth != 1;
|
||||
}
|
||||
|
||||
void Handler3D::PixelUnproject( View& view, GLprecision winx, GLprecision winy, GLprecision winz, GLprecision Pc[3])
|
||||
{
|
||||
const GLint viewport[4] = {view.v.l,view.v.b,view.v.w,view.v.h};
|
||||
const pangolin::OpenGlMatrix proj = cam_state->GetProjectionMatrix();
|
||||
glUnProject(winx, winy, winz, Identity4d, proj.m, viewport, &Pc[0], &Pc[1], &Pc[2]);
|
||||
}
|
||||
|
||||
void Handler3D::GetPosNormal(pangolin::View& view, int winx, int winy, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision nw[3], GLprecision default_z)
|
||||
{
|
||||
// TODO: Get to work on android
|
||||
|
||||
const int zl = (hwin*2+1);
|
||||
const int zsize = zl*zl;
|
||||
GLfloat zs[zsize];
|
||||
|
||||
#ifndef HAVE_GLES
|
||||
glReadBuffer(GL_FRONT);
|
||||
glReadPixels(winx-hwin,winy-hwin,zl,zl,GL_DEPTH_COMPONENT,GL_FLOAT,zs);
|
||||
#else
|
||||
std::fill(zs,zs+zsize, 1);
|
||||
#endif
|
||||
GLfloat mindepth = *(std::min_element(zs,zs+zsize));
|
||||
|
||||
if(mindepth == 1) mindepth = (GLfloat)default_z;
|
||||
|
||||
p[0] = winx; p[1] = winy; p[2] = mindepth;
|
||||
PixelUnproject(view, winx, winy, mindepth, Pc);
|
||||
|
||||
const pangolin::OpenGlMatrix mv = cam_state->GetModelViewMatrix();
|
||||
|
||||
GLprecision T_wc[3*4];
|
||||
LieSE3from4x4(T_wc, mv.Inverse().m );
|
||||
LieApplySE3vec(Pw, T_wc, Pc);
|
||||
|
||||
// Neighboring points in camera coordinates
|
||||
GLprecision Pl[3]; GLprecision Pr[3]; GLprecision Pb[3]; GLprecision Pt[3];
|
||||
PixelUnproject(view, winx-hwin, winy, zs[hwin*zl + 0], Pl );
|
||||
PixelUnproject(view, winx+hwin, winy, zs[hwin*zl + zl-1], Pr );
|
||||
PixelUnproject(view, winx, winy-hwin, zs[hwin+1], Pb );
|
||||
PixelUnproject(view, winx, winy+hwin, zs[zsize-(hwin+1)], Pt );
|
||||
|
||||
// n = ((Pr-Pl).cross(Pt-Pb)).normalized();
|
||||
GLprecision PrmPl[3]; GLprecision PtmPb[3];
|
||||
MatSub<3,1>(PrmPl,Pr,Pl);
|
||||
MatSub<3,1>(PtmPb,Pt,Pb);
|
||||
|
||||
GLprecision nc[3];
|
||||
CrossProduct(nc, PrmPl, PtmPb);
|
||||
Normalise<3>(nc);
|
||||
|
||||
// T_wc is col major, so the rotation component is first.
|
||||
LieApplySO3(nw,T_wc,nc);
|
||||
}
|
||||
|
||||
void Handler3D::Mouse(View& display, MouseButton button, int x, int y, bool pressed, int button_state)
|
||||
{
|
||||
// mouse down
|
||||
last_pos[0] = (float)x;
|
||||
last_pos[1] = (float)y;
|
||||
|
||||
GLprecision T_nc[3*4];
|
||||
LieSetIdentity(T_nc);
|
||||
|
||||
funcKeyState = 0;
|
||||
if( pressed )
|
||||
{
|
||||
GetPosNormal(display,x,y,p,Pw,Pc,n,last_z);
|
||||
if( ValidWinDepth(p[2]) )
|
||||
{
|
||||
last_z = p[2];
|
||||
std::copy(Pc,Pc+3,rot_center);
|
||||
}
|
||||
|
||||
if( button == MouseWheelUp || button == MouseWheelDown)
|
||||
{
|
||||
LieSetIdentity(T_nc);
|
||||
const GLprecision t[3] = { 0,0,(button==MouseWheelUp?1:-1)*100*tf};
|
||||
LieSetTranslation<>(T_nc,t);
|
||||
if( !(button_state & MouseButtonRight) && !(rot_center[0]==0 && rot_center[1]==0 && rot_center[2]==0) )
|
||||
{
|
||||
LieSetTranslation<>(T_nc,rot_center);
|
||||
const GLprecision s = (button==MouseWheelUp?-1.0:1.0) * zf;
|
||||
MatMul<3,1>(T_nc+(3*3), s);
|
||||
}
|
||||
OpenGlMatrix& spec = cam_state->GetModelViewMatrix();
|
||||
LieMul4x4bySE3<>(spec.m,T_nc,spec.m);
|
||||
}
|
||||
|
||||
funcKeyState = button_state;
|
||||
}
|
||||
}
|
||||
|
||||
void Handler3D::MouseMotion(View& display, int x, int y, int button_state)
|
||||
{
|
||||
const GLprecision rf = 0.01;
|
||||
const float delta[2] = { (float)x - last_pos[0], (float)y - last_pos[1] };
|
||||
const float mag = delta[0]*delta[0] + delta[1]*delta[1];
|
||||
|
||||
if((button_state & KeyModifierCtrl) && (button_state & KeyModifierShift))
|
||||
{
|
||||
GLprecision T_nc[3 * 4];
|
||||
LieSetIdentity(T_nc);
|
||||
|
||||
GetPosNormal(display, x, y, p, Pw, Pc, n, last_z);
|
||||
if(ValidWinDepth(p[2]))
|
||||
{
|
||||
last_z = p[2];
|
||||
std::copy(Pc, Pc + 3, rot_center);
|
||||
}
|
||||
|
||||
funcKeyState = button_state;
|
||||
}
|
||||
else
|
||||
{
|
||||
funcKeyState = 0;
|
||||
}
|
||||
|
||||
// TODO: convert delta to degrees based of fov
|
||||
// TODO: make transformation with respect to cam spec
|
||||
if( mag < 50.0f*50.0f )
|
||||
{
|
||||
OpenGlMatrix& mv = cam_state->GetModelViewMatrix();
|
||||
const GLprecision* up = AxisDirectionVector[enforce_up];
|
||||
GLprecision T_nc[3*4];
|
||||
LieSetIdentity(T_nc);
|
||||
bool rotation_changed = false;
|
||||
|
||||
if( button_state == MouseButtonMiddle )
|
||||
{
|
||||
// Middle Drag: Rotate around view
|
||||
|
||||
// Try to correct for different coordinate conventions.
|
||||
GLprecision aboutx = -rf * delta[1];
|
||||
GLprecision abouty = rf * delta[0];
|
||||
OpenGlMatrix& pm = cam_state->GetProjectionMatrix();
|
||||
abouty *= -pm.m[2 * 4 + 3];
|
||||
|
||||
Rotation<>(T_nc, aboutx, abouty, (GLprecision)0.0);
|
||||
}else if( button_state == MouseButtonLeft )
|
||||
{
|
||||
// Left Drag: in plane translate
|
||||
if( ValidWinDepth(last_z) )
|
||||
{
|
||||
GLprecision np[3];
|
||||
PixelUnproject(display, x, y, last_z, np);
|
||||
const GLprecision t[] = { np[0] - rot_center[0], np[1] - rot_center[1], 0};
|
||||
LieSetTranslation<>(T_nc,t);
|
||||
std::copy(np,np+3,rot_center);
|
||||
}else{
|
||||
const GLprecision t[] = { -10*delta[0]*tf, 10*delta[1]*tf, 0};
|
||||
LieSetTranslation<>(T_nc,t);
|
||||
}
|
||||
}else if( button_state == (MouseButtonLeft | MouseButtonRight) )
|
||||
{
|
||||
// Left and Right Drag: in plane rotate about object
|
||||
// Rotation<>(T_nc,0.0,0.0, delta[0]*0.01);
|
||||
|
||||
GLprecision T_2c[3*4];
|
||||
Rotation<>(T_2c, (GLprecision)0.0, (GLprecision)0.0, delta[0]*rf);
|
||||
GLprecision mrotc[3];
|
||||
MatMul<3,1>(mrotc, rot_center, (GLprecision)-1.0);
|
||||
LieApplySO3<>(T_2c+(3*3),T_2c,mrotc);
|
||||
GLprecision T_n2[3*4];
|
||||
LieSetIdentity<>(T_n2);
|
||||
LieSetTranslation<>(T_n2,rot_center);
|
||||
LieMulSE3(T_nc, T_n2, T_2c );
|
||||
rotation_changed = true;
|
||||
}else if( button_state == MouseButtonRight)
|
||||
{
|
||||
GLprecision aboutx = -rf * delta[1];
|
||||
GLprecision abouty = -rf * delta[0];
|
||||
|
||||
// Try to correct for different coordinate conventions.
|
||||
if(cam_state->GetProjectionMatrix().m[2*4+3] <= 0) {
|
||||
abouty *= -1;
|
||||
}
|
||||
|
||||
if(enforce_up) {
|
||||
// Special case if view direction is parallel to up vector
|
||||
const GLprecision updotz = mv.m[2]*up[0] + mv.m[6]*up[1] + mv.m[10]*up[2];
|
||||
if(updotz > 0.98) aboutx = std::min(aboutx, (GLprecision)0.0);
|
||||
if(updotz <-0.98) aboutx = std::max(aboutx, (GLprecision)0.0);
|
||||
// Module rotation around y so we don't spin too fast!
|
||||
abouty *= (1-0.6*fabs(updotz));
|
||||
}
|
||||
|
||||
// Right Drag: object centric rotation
|
||||
GLprecision T_2c[3*4];
|
||||
Rotation<>(T_2c, aboutx, abouty, (GLprecision)0.0);
|
||||
GLprecision mrotc[3];
|
||||
MatMul<3,1>(mrotc, rot_center, (GLprecision)-1.0);
|
||||
LieApplySO3<>(T_2c+(3*3),T_2c,mrotc);
|
||||
GLprecision T_n2[3*4];
|
||||
LieSetIdentity<>(T_n2);
|
||||
LieSetTranslation<>(T_n2,rot_center);
|
||||
LieMulSE3(T_nc, T_n2, T_2c );
|
||||
rotation_changed = true;
|
||||
}
|
||||
|
||||
LieMul4x4bySE3<>(mv.m,T_nc,mv.m);
|
||||
|
||||
if(enforce_up != AxisNone && rotation_changed) {
|
||||
EnforceUpT_cw(mv.m, up);
|
||||
}
|
||||
}
|
||||
|
||||
last_pos[0] = (float)x;
|
||||
last_pos[1] = (float)y;
|
||||
}
|
||||
|
||||
void Handler3D::Special(View& display, InputSpecial inType, float x, float y, float p1, float p2, float /*p3*/, float /*p4*/, int button_state)
|
||||
{
|
||||
if( !(inType == InputSpecialScroll || inType == InputSpecialRotate) )
|
||||
return;
|
||||
|
||||
// mouse down
|
||||
last_pos[0] = x;
|
||||
last_pos[1] = y;
|
||||
|
||||
GLprecision T_nc[3*4];
|
||||
LieSetIdentity(T_nc);
|
||||
|
||||
GetPosNormal(display, (int)x, (int)y, p, Pw, Pc, n, last_z);
|
||||
if(p[2] < 1.0) {
|
||||
last_z = p[2];
|
||||
std::copy(Pc,Pc+3,rot_center);
|
||||
}
|
||||
|
||||
if( inType == InputSpecialScroll ) {
|
||||
if(button_state & KeyModifierCmd) {
|
||||
const GLprecision rx = -p2 / 1000;
|
||||
const GLprecision ry = -p1 / 1000;
|
||||
|
||||
Rotation<>(T_nc,rx, ry, (GLprecision)0.0);
|
||||
OpenGlMatrix& spec = cam_state->GetModelViewMatrix();
|
||||
LieMul4x4bySE3<>(spec.m,T_nc,spec.m);
|
||||
}else{
|
||||
const GLprecision scrolly = p2/10;
|
||||
|
||||
LieSetIdentity(T_nc);
|
||||
const GLprecision t[] = { 0,0, -scrolly*100*tf};
|
||||
LieSetTranslation<>(T_nc,t);
|
||||
if( !(button_state & MouseButtonRight) && !(rot_center[0]==0 && rot_center[1]==0 && rot_center[2]==0) )
|
||||
{
|
||||
LieSetTranslation<>(T_nc,rot_center);
|
||||
MatMul<3,1>(T_nc+(3*3), -scrolly * zf);
|
||||
}
|
||||
OpenGlMatrix& spec = cam_state->GetModelViewMatrix();
|
||||
LieMul4x4bySE3<>(spec.m,T_nc,spec.m);
|
||||
}
|
||||
}else if(inType == InputSpecialRotate) {
|
||||
const GLprecision r = p1 / 20;
|
||||
|
||||
GLprecision T_2c[3*4];
|
||||
Rotation<>(T_2c, (GLprecision)0.0, (GLprecision)0.0, r);
|
||||
GLprecision mrotc[3];
|
||||
MatMul<3,1>(mrotc, rot_center, (GLprecision)-1.0);
|
||||
LieApplySO3<>(T_2c+(3*3),T_2c,mrotc);
|
||||
GLprecision T_n2[3*4];
|
||||
LieSetIdentity<>(T_n2);
|
||||
LieSetTranslation<>(T_n2,rot_center);
|
||||
LieMulSE3(T_nc, T_n2, T_2c );
|
||||
OpenGlMatrix& spec = cam_state->GetModelViewMatrix();
|
||||
LieMul4x4bySE3<>(spec.m,T_nc,spec.m);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
45
thirdparty/Pangolin/src/handler/handler_glbuffer.cpp
vendored
Normal file
45
thirdparty/Pangolin/src/handler/handler_glbuffer.cpp
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/handler/handler_glbuffer.h>
|
||||
#include <pangolin/display/view.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
Handler3DFramebuffer::Handler3DFramebuffer(GlFramebuffer& fb, pangolin::OpenGlRenderState& cam_state, pangolin::AxisDirection enforce_up, float trans_scale)
|
||||
: pangolin::Handler3D(cam_state,enforce_up, trans_scale), fb(fb)
|
||||
{
|
||||
}
|
||||
|
||||
void Handler3DFramebuffer::GetPosNormal(pangolin::View& view, int x, int y, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision n[3], GLprecision default_z)
|
||||
{
|
||||
fb.Bind();
|
||||
Handler3D::GetPosNormal(view,x,y,p,Pw,Pc,n,default_z);
|
||||
fb.Unbind();
|
||||
}
|
||||
|
||||
}
|
||||
462
thirdparty/Pangolin/src/handler/handler_image.cpp
vendored
Normal file
462
thirdparty/Pangolin/src/handler/handler_image.cpp
vendored
Normal file
@@ -0,0 +1,462 @@
|
||||
#include <pangolin/handler/handler_image.h>
|
||||
#include <pangolin/gl/glfont.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
ImageViewHandler::ImageViewHandler()
|
||||
: linked_view_handler(0),
|
||||
use_nn(false), flipTextureX(false), flipTextureY(false)
|
||||
{
|
||||
SetDimensions(1, 1);
|
||||
}
|
||||
|
||||
ImageViewHandler::ImageViewHandler(size_t w, size_t h)
|
||||
: linked_view_handler(0),
|
||||
use_nn(false), flipTextureX(false), flipTextureY(false)
|
||||
{
|
||||
SetDimensions(w,h);
|
||||
}
|
||||
|
||||
void ImageViewHandler::SetDimensions(size_t w, size_t h)
|
||||
{
|
||||
rview_default = pangolin::XYRangef(-0.5f, w-0.5f, -0.5f, h-0.5f),
|
||||
rview_max = pangolin::XYRangef(-0.5f, w-0.5f, -0.5f, h-0.5f),
|
||||
rview = rview_default;
|
||||
target = rview;
|
||||
}
|
||||
|
||||
void ImageViewHandler::UpdateView()
|
||||
{
|
||||
// TODO: Base this on current framerate.
|
||||
const float animate_factor = 1.0f / 5.0f;
|
||||
|
||||
if( linked_view_handler ) {
|
||||
// Synchronise rview and target with linked plotter
|
||||
rview = linked_view_handler->rview;
|
||||
target = linked_view_handler->target;
|
||||
selection = linked_view_handler->selection;
|
||||
}else{
|
||||
// Clamp target to image dimensions.
|
||||
AdjustScale();
|
||||
AdjustTranslation();
|
||||
|
||||
// Animate view window toward target
|
||||
pangolin::XYRangef d = target - rview;
|
||||
rview += d * animate_factor;
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewHandler::glSetViewOrtho()
|
||||
{
|
||||
const pangolin::XYRangef& xy = GetViewToRender();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(xy.x.min, xy.x.max, xy.y.max, xy.y.min, -1, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
void ImageViewHandler::glRenderTexture(pangolin::GlTexture& tex)
|
||||
{
|
||||
glRenderTexture(tex.tid, tex.width, tex.height);
|
||||
}
|
||||
|
||||
void ImageViewHandler::glRenderTexture(GLuint tex, GLint width, GLint height)
|
||||
{
|
||||
if(tex != 0) {
|
||||
const pangolin::XYRangef& xy = GetViewToRender();
|
||||
const float w = (float)width;
|
||||
const float h = (float)height;
|
||||
|
||||
// discrete coords, (-0.5, -0.5) - (w-0.5, h-0.5)
|
||||
const GLfloat l = xy.x.min;
|
||||
const GLfloat r = xy.x.max;
|
||||
const GLfloat b = xy.y.max;
|
||||
const GLfloat t = xy.y.min;
|
||||
|
||||
// continuous coords, (0,0) - (1,1)
|
||||
GLfloat ln = (l + 0.5f) / w;
|
||||
GLfloat rn = (r + 0.5f) / w;
|
||||
GLfloat bn = (b + 0.5f) / h;
|
||||
GLfloat tn = (t + 0.5f) / h;
|
||||
|
||||
if(flipTextureX) {
|
||||
ln = 1-ln;
|
||||
rn = 1-rn;
|
||||
}
|
||||
|
||||
if(flipTextureY) {
|
||||
bn = 1-bn;
|
||||
tn = 1-tn;
|
||||
}
|
||||
|
||||
const GLfloat sq_vert[] = { l,t, r,t, r,b, l,b };
|
||||
const GLfloat sq_tex[] = { ln,tn, rn,tn, rn,bn, ln,bn };
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, UseNN() ? GL_NEAREST : GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, UseNN() ? GL_NEAREST : GL_LINEAR);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
|
||||
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewHandler::glRenderOverlay()
|
||||
{
|
||||
const pangolin::XYRangef& selxy = GetSelection();
|
||||
const GLfloat sq_select[] = {
|
||||
selxy.x.min, selxy.y.min,
|
||||
selxy.x.max, selxy.y.min,
|
||||
selxy.x.max, selxy.y.max,
|
||||
selxy.x.min, selxy.y.max
|
||||
};
|
||||
glColor4f(1.0,0.0,0.0,1.0);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, sq_select);
|
||||
glDrawArrays(GL_LINE_LOOP, 0, 4);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glColor4f(1.0,1.0,1.0,1.0);
|
||||
|
||||
if( std::abs(selxy.Area()) > 0) {
|
||||
// Render text
|
||||
pangolin::Viewport v;
|
||||
glGetIntegerv( GL_VIEWPORT, &v.l );
|
||||
float xpix, ypix;
|
||||
ImageToScreen(v, selxy.x.max, selxy.y.max, xpix, ypix);
|
||||
|
||||
// Save previous value
|
||||
GLboolean gl_blend_enabled;
|
||||
glGetBooleanv(GL_BLEND, &gl_blend_enabled);
|
||||
|
||||
// Ensure that blending is enabled for rendering text.
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
pangolin::GlFont::I().Text(
|
||||
"%.2f x %.2f",
|
||||
selxy.x.Size(), selxy.y.Size()
|
||||
).DrawWindow(xpix,ypix);
|
||||
|
||||
pangolin::GlFont::I().Text(
|
||||
"(%.1f,%.1f)->(%.1f,%.1f)",
|
||||
selxy.x.min, selxy.y.min,
|
||||
selxy.x.max, selxy.y.max
|
||||
).DrawWindow(xpix, ypix - 1.0f * pangolin::GlFont::I().Height());
|
||||
|
||||
// Restore previous value
|
||||
if(!gl_blend_enabled) glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewHandler::ScreenToImage(Viewport& v, float xpix, float ypix, float& ximg, float& yimg)
|
||||
{
|
||||
ximg = rview.x.min + rview.x.Size() * (xpix - v.l) / (float)v.w;
|
||||
yimg = rview.y.min + rview.y.Size() * ( 1.0f - (ypix - v.b) / (float)v.h);
|
||||
}
|
||||
|
||||
void ImageViewHandler::ImageToScreen(Viewport& v, float ximg, float yimg, float& xpix, float& ypix)
|
||||
{
|
||||
xpix = (ximg -rview.x.min) * (float)v.w / rview.x.Size() + v.l;
|
||||
ypix = v.b - (float)v.h * ((yimg - rview.y.min) / rview.y.Size() - 1.0f);
|
||||
}
|
||||
|
||||
bool ImageViewHandler::UseNN() const
|
||||
{
|
||||
return use_nn;
|
||||
}
|
||||
|
||||
bool& ImageViewHandler::UseNN()
|
||||
{
|
||||
return use_nn;
|
||||
}
|
||||
|
||||
bool& ImageViewHandler::FlipTextureX()
|
||||
{
|
||||
return flipTextureX;
|
||||
}
|
||||
|
||||
bool& ImageViewHandler::FlipTextureY()
|
||||
{
|
||||
return flipTextureY;
|
||||
}
|
||||
|
||||
pangolin::XYRangef& ImageViewHandler::GetViewToRender()
|
||||
{
|
||||
return rview;
|
||||
}
|
||||
|
||||
float ImageViewHandler::GetViewScale()
|
||||
{
|
||||
return rview_max.x.Size() / rview.x.Size();
|
||||
}
|
||||
|
||||
pangolin::XYRangef& ImageViewHandler::GetView()
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
pangolin::XYRangef& ImageViewHandler::GetDefaultView()
|
||||
{
|
||||
return rview_default;
|
||||
}
|
||||
|
||||
pangolin::XYRangef& ImageViewHandler::GetSelection()
|
||||
{
|
||||
return selection;
|
||||
}
|
||||
|
||||
void ImageViewHandler::GetHover(float& x, float& y)
|
||||
{
|
||||
ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
|
||||
x = tv.hover_img[0];
|
||||
y = tv.hover_img[1];
|
||||
}
|
||||
|
||||
void ImageViewHandler::SetView(const pangolin::XYRangef& range)
|
||||
{
|
||||
ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
|
||||
tv.rview = range;
|
||||
tv.target = range;
|
||||
}
|
||||
|
||||
void ImageViewHandler::SetViewSmooth(const pangolin::XYRangef& range)
|
||||
{
|
||||
ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
|
||||
tv.target = range;
|
||||
}
|
||||
|
||||
void ImageViewHandler::ScrollView(float x, float y)
|
||||
{
|
||||
ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
|
||||
ScrollViewSmooth(x,y);
|
||||
tv.rview.x += x;
|
||||
tv.rview.y += y;
|
||||
}
|
||||
|
||||
void ImageViewHandler::ScrollViewSmooth(float x, float y)
|
||||
{
|
||||
ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
|
||||
tv.target.x += x;
|
||||
tv.target.y += y;
|
||||
}
|
||||
|
||||
void ImageViewHandler::ScaleView(float x, float y, float cx, float cy)
|
||||
{
|
||||
ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
|
||||
ScaleViewSmooth(x,y,cx,cy);
|
||||
tv.rview.x.Scale(x,cx);
|
||||
tv.rview.y.Scale(y,cy);
|
||||
}
|
||||
|
||||
void ImageViewHandler::ScaleViewSmooth(float x, float y, float cx, float cy)
|
||||
{
|
||||
ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
|
||||
tv.target.x.Scale(x,cx);
|
||||
tv.target.y.Scale(y,cy);
|
||||
}
|
||||
|
||||
void ImageViewHandler::ResetView()
|
||||
{
|
||||
ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
|
||||
tv.target = tv.rview_default;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
/// pangolin::Handler
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
void ImageViewHandler::Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed)
|
||||
{
|
||||
XYRangef& sel = linked_view_handler ? linked_view_handler->selection : selection;
|
||||
const float mvfactor = 1.0f / 10.0f;
|
||||
const float c[2] = { rview.x.Mid(), rview.y.Mid() };
|
||||
|
||||
|
||||
if(pressed) {
|
||||
if(key == '\r') {
|
||||
if( sel.Area() != 0.0f && std::isfinite(sel.Area()) ) {
|
||||
// Set view to equal selection
|
||||
SetViewSmooth(sel);
|
||||
|
||||
// Reset selection
|
||||
sel.x.max = sel.x.min;
|
||||
sel.y.max = sel.y.min;
|
||||
}
|
||||
}else if(key == 'n') {
|
||||
use_nn = !use_nn;
|
||||
}else if(key == 'l') {
|
||||
if(to_link) {
|
||||
linked_view_handler = to_link;
|
||||
to_link = 0;
|
||||
}else{
|
||||
to_link = this;
|
||||
}
|
||||
}else if(key == PANGO_SPECIAL + PANGO_KEY_LEFT) {
|
||||
const float w = target.x.Size();
|
||||
const float dx = mvfactor*w;
|
||||
ScrollViewSmooth(-dx, 0);
|
||||
}else if(key == PANGO_SPECIAL + PANGO_KEY_RIGHT) {
|
||||
const float w = target.x.Size();
|
||||
const float dx = mvfactor*w;
|
||||
ScrollViewSmooth(+dx, 0);
|
||||
}else if(key == PANGO_SPECIAL + PANGO_KEY_DOWN) {
|
||||
const float h = target.y.Size();
|
||||
const float dy = mvfactor*h;
|
||||
ScrollViewSmooth(0, -dy);
|
||||
}else if(key == PANGO_SPECIAL + PANGO_KEY_UP) {
|
||||
const float h = target.y.Size();
|
||||
const float dy = mvfactor*h;
|
||||
ScrollViewSmooth(0, +dy);
|
||||
}else if(key == '=') {
|
||||
ScaleViewSmooth(0.5, 0.5, c[0], c[1]);
|
||||
}else if(key == '-') {
|
||||
ScaleViewSmooth(2.0, 2.0, c[0], c[1]);
|
||||
}else if(key == '#') {
|
||||
ResetView();
|
||||
}else if(key == 1) {
|
||||
// ctrl-a: select all.
|
||||
sel = rview;
|
||||
}else{
|
||||
pango_print_debug("Unhandled ImageViewHandler::Keyboard. Key: %u\n", (unsigned int)key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewHandler::Mouse(View& view, pangolin::MouseButton button, int x, int y, bool pressed, int button_state)
|
||||
{
|
||||
XYRangef& sel = linked_view_handler ? linked_view_handler->selection : selection;
|
||||
ScreenToImage(view.v, (float)x, (float)y, hover_img[0], hover_img[1]);
|
||||
|
||||
const float scinc = 1.05f;
|
||||
const float scdec = 1.0f/scinc;
|
||||
|
||||
if(button_state & KeyModifierCtrl) {
|
||||
const float mvfactor = 1.0f/20.0f;
|
||||
|
||||
if(button == MouseWheelUp) {
|
||||
ScrollViewSmooth(0.0f, +mvfactor*rview.y.Size() );
|
||||
}else if(button == MouseWheelDown) {
|
||||
ScrollViewSmooth(0.0f, -mvfactor*rview.y.Size() );
|
||||
}else if(button == MouseWheelLeft) {
|
||||
ScrollViewSmooth(+mvfactor*rview.x.Size(), 0.0f );
|
||||
}else if(button == MouseWheelRight) {
|
||||
ScrollViewSmooth(-mvfactor*rview.x.Size(), 0.0f );
|
||||
}
|
||||
}else{
|
||||
if(button == MouseButtonLeft) {
|
||||
// Update selected range
|
||||
if(pressed) {
|
||||
sel.x.min = hover_img[0];
|
||||
sel.y.min = hover_img[1];
|
||||
}
|
||||
sel.x.max = hover_img[0];
|
||||
sel.y.max = hover_img[1];
|
||||
}else if(button == MouseWheelUp) {
|
||||
ScaleViewSmooth(scdec, scdec, hover_img[0], hover_img[1]);
|
||||
}else if(button == MouseWheelDown) {
|
||||
ScaleViewSmooth(scinc, scinc, hover_img[0], hover_img[1]);
|
||||
}
|
||||
}
|
||||
|
||||
FixSelection(sel);
|
||||
last_mouse_pos[0] = x;
|
||||
last_mouse_pos[1] = y;
|
||||
|
||||
if(OnSelectionCallback) {
|
||||
OnSelectionCallback( OnSelectionEventData(view,*this,pressed) );
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewHandler::MouseMotion(View& view, int x, int y, int button_state)
|
||||
{
|
||||
XYRangef& sel = linked_view_handler ? linked_view_handler->selection : selection;
|
||||
const int d[2] = {x-last_mouse_pos[0], y-last_mouse_pos[1]};
|
||||
|
||||
// Update hover status (after potential resizing)
|
||||
ScreenToImage(view.v, (float)x, (float)y, hover_img[0], hover_img[1]);
|
||||
|
||||
if( button_state == MouseButtonLeft )
|
||||
{
|
||||
// Update selected range
|
||||
sel.x.max = hover_img[0];
|
||||
sel.y.max = hover_img[1];
|
||||
}else if(button_state == MouseButtonRight )
|
||||
{
|
||||
Special(view, InputSpecialScroll, (float)x, (float)y, (float)d[0], (float)d[1], 0.0f, 0.0f, button_state);
|
||||
}
|
||||
|
||||
last_mouse_pos[0] = x;
|
||||
last_mouse_pos[1] = y;
|
||||
|
||||
if( button_state == MouseButtonLeft && OnSelectionCallback) {
|
||||
OnSelectionCallback( OnSelectionEventData(view,*this,true) );
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewHandler::PassiveMouseMotion(View&, int /*x*/, int /*y*/, int /*button_state*/)
|
||||
{
|
||||
}
|
||||
|
||||
void ImageViewHandler::Special(View& view, pangolin::InputSpecial inType, float x, float y, float p1, float p2, float /*p3*/, float /*p4*/, int /*button_state*/)
|
||||
{
|
||||
ScreenToImage(view.v, x, y, hover_img[0], hover_img[1]);
|
||||
|
||||
if(inType == InputSpecialScroll) {
|
||||
const float d[2] = {p1,p2};
|
||||
const float is[2] = {rview.x.Size(),rview.y.Size() };
|
||||
const float df[2] = {is[0]*d[0]/(float)view.v.w, is[1]*d[1]/(float)view.v.h};
|
||||
ScrollView(-df[0], df[1]);
|
||||
} else if(inType == InputSpecialZoom) {
|
||||
float scale = 1.0f - p1;
|
||||
ScaleView(scale, scale, hover_img[0], hover_img[1]);
|
||||
}
|
||||
|
||||
// Update hover status (after potential resizing)
|
||||
ScreenToImage( view.v, x, y, hover_img[0], hover_img[1]);
|
||||
}
|
||||
|
||||
void ImageViewHandler::FixSelection(XYRangef& sel)
|
||||
{
|
||||
// Make sure selection matches sign of current viewport
|
||||
if( (sel.x.min<sel.x.max) != (rview.x.min<rview.x.max) ) {
|
||||
std::swap(sel.x.min, sel.x.max);
|
||||
}
|
||||
if( (sel.y.min<sel.y.max) != (rview.y.min<rview.y.max) ) {
|
||||
std::swap(sel.y.min, sel.y.max);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageViewHandler::AdjustScale()
|
||||
{
|
||||
ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
|
||||
if(tv.target.x.AbsSize() > tv.rview_max.x.AbsSize())
|
||||
tv.target.x.Scale(tv.rview_max.x.AbsSize() / tv.target.x.AbsSize(), tv.target.x.Mid());
|
||||
if(tv.target.y.AbsSize() > tv.rview_max.y.AbsSize())
|
||||
tv.target.y.Scale(tv.rview_max.y.AbsSize() / tv.target.y.AbsSize(), tv.target.y.Mid());
|
||||
}
|
||||
|
||||
void ImageViewHandler::AdjustTranslation()
|
||||
{
|
||||
ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
|
||||
if( tv.target.x.max > tv.rview_max.x.max) tv.target.x -= tv.target.x.max - tv.rview_max.x.max;
|
||||
if( tv.target.x.min < tv.rview_max.x.min) tv.target.x -= tv.target.x.min - tv.rview_max.x.min;
|
||||
|
||||
if( tv.target.y.max > tv.rview_max.y.max) tv.target.y -= tv.target.y.max - tv.rview_max.y.max;
|
||||
if( tv.target.y.min < tv.rview_max.y.min) tv.target.y -= tv.target.y.min - tv.rview_max.y.min;
|
||||
}
|
||||
|
||||
float ImageViewHandler::animate_factor = 1.0f / 2.0f;
|
||||
ImageViewHandler* ImageViewHandler::to_link = 0;
|
||||
|
||||
}
|
||||
177
thirdparty/Pangolin/src/image/image_io.cpp
vendored
Normal file
177
thirdparty/Pangolin/src/image/image_io.cpp
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/image/image_io.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
// PNG
|
||||
TypedImage LoadPng(std::istream& in);
|
||||
void SavePng(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, bool top_line_first, int zlib_compression_level );
|
||||
|
||||
// JPG
|
||||
TypedImage LoadJpg(std::istream& in);
|
||||
void SaveJpg(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, float quality);
|
||||
|
||||
// PPM
|
||||
TypedImage LoadPpm(std::istream& in);
|
||||
void SavePpm(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, bool top_line_first);
|
||||
|
||||
// TGA
|
||||
TypedImage LoadTga(std::istream& in);
|
||||
|
||||
// Pango
|
||||
TypedImage LoadPango(const std::string& filename);
|
||||
void SavePango(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first);
|
||||
|
||||
// EXR
|
||||
TypedImage LoadExr(std::istream& source);
|
||||
void SaveExr(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first);
|
||||
|
||||
// ZSTD (https://github.com/facebook/zstd)
|
||||
TypedImage LoadZstd(std::istream& in);
|
||||
void SaveZstd(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level);
|
||||
|
||||
// https://github.com/lz4/lz4
|
||||
TypedImage LoadLz4(std::istream& in);
|
||||
void SaveLz4(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level);
|
||||
|
||||
// packed 12 bit image (obtained from unpacked 16bit)
|
||||
TypedImage LoadPacked12bit(std::istream& in);
|
||||
void SavePacked12bit(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level);
|
||||
|
||||
TypedImage LoadImage(std::istream& in, ImageFileType file_type)
|
||||
{
|
||||
switch (file_type) {
|
||||
case ImageFileTypePng:
|
||||
return LoadPng(in);
|
||||
case ImageFileTypeJpg:
|
||||
return LoadJpg(in);
|
||||
case ImageFileTypePpm:
|
||||
return LoadPpm(in);
|
||||
case ImageFileTypeTga:
|
||||
return LoadTga(in);
|
||||
case ImageFileTypeZstd:
|
||||
return LoadZstd(in);
|
||||
case ImageFileTypeLz4:
|
||||
return LoadLz4(in);
|
||||
case ImageFileTypeP12b:
|
||||
return LoadPacked12bit(in);
|
||||
case ImageFileTypeExr:
|
||||
return LoadExr(in);
|
||||
default:
|
||||
throw std::runtime_error("Unable to load image file-type through std::istream");
|
||||
}
|
||||
}
|
||||
|
||||
TypedImage LoadImage(const std::string& filename, ImageFileType file_type)
|
||||
{
|
||||
switch (file_type) {
|
||||
case ImageFileTypePng:
|
||||
case ImageFileTypeJpg:
|
||||
case ImageFileTypePpm:
|
||||
case ImageFileTypeTga:
|
||||
case ImageFileTypeZstd:
|
||||
case ImageFileTypeLz4:
|
||||
case ImageFileTypeP12b:
|
||||
case ImageFileTypeExr:
|
||||
{
|
||||
std::ifstream ifs(filename, std::ios_base::in|std::ios_base::binary);
|
||||
return LoadImage(ifs, file_type);
|
||||
}
|
||||
case ImageFileTypePango:
|
||||
return LoadPango(filename);
|
||||
default:
|
||||
throw std::runtime_error("Unsupported image file type, '" + filename + "'");
|
||||
}
|
||||
}
|
||||
|
||||
TypedImage LoadImage(const std::string& filename)
|
||||
{
|
||||
ImageFileType file_type = FileType(filename);
|
||||
return LoadImage( filename, file_type );
|
||||
}
|
||||
|
||||
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, ImageFileType file_type, bool top_line_first, float quality)
|
||||
{
|
||||
switch (file_type) {
|
||||
case ImageFileTypePng:
|
||||
// map quality [0..100] to PNG compression levels [0..9]
|
||||
return SavePng(image, fmt, out, top_line_first, int(quality*0.09));
|
||||
case ImageFileTypeJpg:
|
||||
return SaveJpg(image, fmt, out, quality);
|
||||
case ImageFileTypePpm:
|
||||
return SavePpm(image,fmt,out,top_line_first);
|
||||
case ImageFileTypeZstd:
|
||||
return SaveZstd(image,fmt,out, quality);
|
||||
case ImageFileTypeLz4:
|
||||
return SaveLz4(image,fmt,out, quality);
|
||||
case ImageFileTypeP12b:
|
||||
return SavePacked12bit(image,fmt,out, quality);
|
||||
default:
|
||||
throw std::runtime_error("Unable to save image file-type through std::istream");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, ImageFileType file_type, bool top_line_first, float quality)
|
||||
{
|
||||
switch (file_type) {
|
||||
case ImageFileTypePng:
|
||||
case ImageFileTypeJpg:
|
||||
case ImageFileTypePpm:
|
||||
case ImageFileTypeZstd:
|
||||
case ImageFileTypeLz4:
|
||||
case ImageFileTypeP12b:
|
||||
{
|
||||
std::ofstream ofs(filename, std::ios_base::binary);
|
||||
return SaveImage(image, fmt, ofs, file_type, top_line_first, quality);
|
||||
}
|
||||
case ImageFileTypeExr:
|
||||
return SaveExr(image, fmt, filename, top_line_first);
|
||||
case ImageFileTypePango:
|
||||
return SavePango(image, fmt, filename, top_line_first);
|
||||
default:
|
||||
throw std::runtime_error("Unsupported image file type, '" + filename + "'");
|
||||
}
|
||||
}
|
||||
|
||||
void SaveImage(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first, float quality)
|
||||
{
|
||||
const std::string ext = FileLowercaseExtention(filename);
|
||||
const ImageFileType file_type = FileTypeExtension(ext);
|
||||
SaveImage(image, fmt, filename,file_type, top_line_first, quality);
|
||||
}
|
||||
|
||||
void SaveImage(const TypedImage& image, const std::string& filename, bool top_line_first, float quality)
|
||||
{
|
||||
SaveImage(image, image.fmt, filename, top_line_first, quality);
|
||||
}
|
||||
|
||||
}
|
||||
188
thirdparty/Pangolin/src/image/image_io_exr.cpp
vendored
Normal file
188
thirdparty/Pangolin/src/image/image_io_exr.cpp
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
#include <pangolin/platform.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <pangolin/image/typed_image.h>
|
||||
|
||||
#ifdef HAVE_OPENEXR
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfInputFile.h>
|
||||
#include <ImfOutputFile.h>
|
||||
#include <ImfIO.h>
|
||||
#endif // HAVE_OPENEXR
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
#ifdef HAVE_OPENEXR
|
||||
Imf::PixelType OpenEXRPixelType(int channel_bits)
|
||||
{
|
||||
if( channel_bits == 16 ) {
|
||||
return Imf::PixelType::HALF;
|
||||
}else if( channel_bits == 32 ) {
|
||||
return Imf::PixelType::FLOAT;
|
||||
}else{
|
||||
throw std::runtime_error("Unsupported OpenEXR Pixel Type.");
|
||||
}
|
||||
}
|
||||
|
||||
void SetOpenEXRChannels(Imf::ChannelList& ch, const pangolin::PixelFormat& fmt)
|
||||
{
|
||||
const char* CHANNEL_NAMES[] = {"R","G","B","A"};
|
||||
for(size_t c=0; c < fmt.channels; ++c) {
|
||||
ch.insert( CHANNEL_NAMES[c], Imf::Channel(OpenEXRPixelType(fmt.channel_bits[c])) );
|
||||
}
|
||||
}
|
||||
|
||||
class StdIStream: public Imf::IStream
|
||||
{
|
||||
public:
|
||||
StdIStream (std::istream &is):
|
||||
Imf::IStream ("stream"),
|
||||
_is (&is)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool read (char c[/*n*/], int n)
|
||||
{
|
||||
if (!*_is)
|
||||
throw std::runtime_error("Unexpected end of file.");
|
||||
_is->read (c, n);
|
||||
if (_is->gcount() < n)
|
||||
{
|
||||
throw std::runtime_error("Early end of file");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual Imf::Int64 tellg ()
|
||||
{
|
||||
return std::streamoff (_is->tellg());
|
||||
}
|
||||
|
||||
virtual void seekg (Imf::Int64 pos)
|
||||
{
|
||||
_is->seekg (pos);
|
||||
}
|
||||
|
||||
virtual void clear ()
|
||||
{
|
||||
_is->clear();
|
||||
}
|
||||
|
||||
private:
|
||||
std::istream * _is;
|
||||
};
|
||||
|
||||
PixelFormat GetPixelFormat(const Imf::Header& header)
|
||||
{
|
||||
const Imf::ChannelList &channels = header.channels();
|
||||
size_t count = 0;
|
||||
for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i){
|
||||
const Imf::Channel& channel = i.channel();
|
||||
if (channel.type != Imf::FLOAT){
|
||||
throw std::invalid_argument("Currently, only 32-bit float OpenEXR files are supported.");
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
|
||||
switch (count) {
|
||||
case 1: return PixelFormatFromString("GRAY32F");
|
||||
case 3: return PixelFormatFromString("RGB96F");
|
||||
case 4: return PixelFormatFromString("RGBA128F");
|
||||
default: throw std::invalid_argument("Currently, only 1, 3 or 4-channel OpenEXR files are supported.");
|
||||
}
|
||||
}
|
||||
|
||||
#endif //HAVE_OPENEXR
|
||||
|
||||
TypedImage LoadExr(std::istream& source)
|
||||
{
|
||||
#ifdef HAVE_OPENEXR
|
||||
StdIStream istream(source);
|
||||
Imf::InputFile file(istream);
|
||||
PANGO_ENSURE(file.isComplete());
|
||||
|
||||
Imath::Box2i dw = file.header().dataWindow();
|
||||
int width = dw.max.x - dw.min.x + 1;
|
||||
int height = dw.max.y - dw.min.y + 1;
|
||||
|
||||
PixelFormat format = GetPixelFormat(file.header());
|
||||
TypedImage img(width, height, format);
|
||||
|
||||
char *imgBase = (char *) img.ptr - (dw.min.x + dw.min.y * width) * sizeof(float) * format.channels;
|
||||
Imf::FrameBuffer fb;
|
||||
|
||||
const Imf::ChannelList &channels = file.header().channels();
|
||||
size_t c = 0;
|
||||
for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i){
|
||||
fb.insert(i.name(), Imf::Slice(
|
||||
Imf::FLOAT, imgBase + sizeof(float) * c++,
|
||||
sizeof(float) * format.channels,
|
||||
sizeof(float) * format.channels * size_t(width),
|
||||
1, 1,
|
||||
0.0));
|
||||
}
|
||||
|
||||
file.setFrameBuffer(fb);
|
||||
file.readPixels(dw.min.y, dw.max.y);
|
||||
|
||||
return img;
|
||||
#else
|
||||
PANGOLIN_UNUSED(source);
|
||||
throw std::runtime_error("Rebuild Pangolin for EXR support.");
|
||||
#endif //HAVE_OPENEXR
|
||||
}
|
||||
|
||||
void SaveExr(const Image<unsigned char>& image_in, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first)
|
||||
{
|
||||
#ifdef HAVE_OPENEXR
|
||||
ManagedImage<unsigned char> flip_image;
|
||||
Image<unsigned char> image;
|
||||
|
||||
if(top_line_first) {
|
||||
image = image_in;
|
||||
}else{
|
||||
flip_image.Reinitialise(image_in.pitch,image_in.h);
|
||||
for(size_t y=0; y<image_in.h; ++y) {
|
||||
std::memcpy(flip_image.RowPtr(y), image_in.RowPtr(y), image_in.pitch);
|
||||
}
|
||||
image = flip_image;
|
||||
}
|
||||
|
||||
|
||||
Imf::Header header (image.w, image.h);
|
||||
SetOpenEXRChannels(header.channels(), fmt);
|
||||
|
||||
Imf::OutputFile file (filename.c_str(), header);
|
||||
Imf::FrameBuffer frameBuffer;
|
||||
|
||||
int ch=0;
|
||||
size_t ch_bits = 0;
|
||||
for(Imf::ChannelList::Iterator it = header.channels().begin(); it != header.channels().end(); ++it)
|
||||
{
|
||||
frameBuffer.insert(
|
||||
it.name(),
|
||||
Imf::Slice(
|
||||
it.channel().type,
|
||||
(char*)image.ptr + ch_bits/8,
|
||||
fmt.channel_bits[ch]/8,
|
||||
image.pitch
|
||||
)
|
||||
);
|
||||
|
||||
ch_bits += fmt.channel_bits[ch++];
|
||||
}
|
||||
|
||||
file.setFrameBuffer(frameBuffer);
|
||||
file.writePixels(image.h);
|
||||
|
||||
#else
|
||||
PANGOLIN_UNUSED(image_in);
|
||||
PANGOLIN_UNUSED(fmt);
|
||||
PANGOLIN_UNUSED(filename);
|
||||
PANGOLIN_UNUSED(top_line_first);
|
||||
throw std::runtime_error("EXR Support not enabled. Please rebuild Pangolin.");
|
||||
#endif // HAVE_OPENEXR
|
||||
}
|
||||
|
||||
}
|
||||
263
thirdparty/Pangolin/src/image/image_io_jpg.cpp
vendored
Normal file
263
thirdparty/Pangolin/src/image/image_io_jpg.cpp
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
#include <pangolin/platform.h>
|
||||
|
||||
#include <pangolin/image/typed_image.h>
|
||||
|
||||
#ifdef HAVE_JPEG
|
||||
# include <jpeglib.h>
|
||||
# ifdef _WIN_
|
||||
// Undef windows Macro polution from jpeglib.h
|
||||
# undef LoadImage
|
||||
# endif
|
||||
#endif // HAVE_JPEG
|
||||
|
||||
|
||||
// Inspired by https://cs.stanford.edu/~acoates/jpegAndIOS.txt
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
#ifdef HAVE_JPEG
|
||||
|
||||
void error_handler(j_common_ptr cinfo) {
|
||||
char msg[JMSG_LENGTH_MAX];
|
||||
(*(cinfo->err->format_message)) (cinfo, msg);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
const static size_t PANGO_JPEG_BUF_SIZE = 16384;
|
||||
|
||||
struct pango_jpeg_source_mgr {
|
||||
struct jpeg_source_mgr pub;
|
||||
std::istream* is;
|
||||
JOCTET* buffer;
|
||||
};
|
||||
|
||||
static void pango_jpeg_init_source(j_decompress_ptr /*cinfo*/) {
|
||||
}
|
||||
|
||||
static boolean pango_jpeg_fill_input_buffer(j_decompress_ptr cinfo) {
|
||||
pango_jpeg_source_mgr* src = (pango_jpeg_source_mgr*)cinfo->src;
|
||||
|
||||
src->is->read((char*)src->buffer, PANGO_JPEG_BUF_SIZE);
|
||||
size_t bytes = src->is->gcount();
|
||||
if (bytes == 0) {
|
||||
/* Insert a fake EOI marker */
|
||||
src->buffer[0] = (JOCTET) 0xFF;
|
||||
src->buffer[1] = (JOCTET) JPEG_EOI;
|
||||
bytes = 2;
|
||||
}
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = bytes;
|
||||
return TRUE;
|
||||
}
|
||||
static void pango_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
|
||||
pango_jpeg_source_mgr* src = (pango_jpeg_source_mgr*)cinfo->src;
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long)src->pub.bytes_in_buffer) {
|
||||
num_bytes -= (long)src->pub.bytes_in_buffer;
|
||||
pango_jpeg_fill_input_buffer(cinfo);
|
||||
}
|
||||
src->pub.next_input_byte += num_bytes;
|
||||
src->pub.bytes_in_buffer -= num_bytes;
|
||||
}
|
||||
}
|
||||
static void pango_jpeg_term_source(j_decompress_ptr cinfo) {
|
||||
// must seek backward so that future reads will start at correct place.
|
||||
pango_jpeg_source_mgr* src = (pango_jpeg_source_mgr*)cinfo->src;
|
||||
src->is->clear();
|
||||
src->is->seekg( src->is->tellg() - (std::streampos)src->pub.bytes_in_buffer );
|
||||
}
|
||||
|
||||
static void pango_jpeg_set_source_mgr(j_decompress_ptr cinfo, std::istream& is) {
|
||||
pango_jpeg_source_mgr* src = nullptr;
|
||||
|
||||
if (cinfo->src == 0)
|
||||
{
|
||||
cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(pango_jpeg_source_mgr));
|
||||
|
||||
src = (pango_jpeg_source_mgr*) cinfo->src;
|
||||
src->buffer = (JOCTET *)(*cinfo->mem->alloc_small)
|
||||
((j_common_ptr) cinfo, JPOOL_PERMANENT, PANGO_JPEG_BUF_SIZE*sizeof(JOCTET));
|
||||
}else{
|
||||
src = (pango_jpeg_source_mgr*) cinfo->src;
|
||||
}
|
||||
|
||||
src->is = &is;
|
||||
src->pub.init_source = pango_jpeg_init_source;
|
||||
src->pub.fill_input_buffer = pango_jpeg_fill_input_buffer;
|
||||
src->pub.skip_input_data = pango_jpeg_skip_input_data;
|
||||
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
|
||||
src->pub.term_source = pango_jpeg_term_source;
|
||||
src->pub.bytes_in_buffer = 0;
|
||||
src->pub.next_input_byte = 0;
|
||||
}
|
||||
|
||||
struct pango_jpeg_destination_mgr {
|
||||
struct jpeg_destination_mgr pub; /* public fields */
|
||||
std::ostream* os; /* target stream */
|
||||
JOCTET * buffer; /* start of buffer */
|
||||
};
|
||||
|
||||
void pango_jpeg_init_destination (j_compress_ptr cinfo) {
|
||||
pango_jpeg_destination_mgr* dest = (pango_jpeg_destination_mgr*) cinfo->dest;
|
||||
dest->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
|
||||
PANGO_JPEG_BUF_SIZE * sizeof(JOCTET));
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = PANGO_JPEG_BUF_SIZE;
|
||||
}
|
||||
|
||||
boolean pango_jpeg_empty_output_buffer(j_compress_ptr cinfo) {
|
||||
pango_jpeg_destination_mgr* dest = (pango_jpeg_destination_mgr*)cinfo->dest;
|
||||
|
||||
dest->os->write((const char*)dest->buffer, PANGO_JPEG_BUF_SIZE);
|
||||
|
||||
if (dest->os->fail()) {
|
||||
throw std::runtime_error("Couldn't write entire jpeg buffer to stream.");
|
||||
}
|
||||
|
||||
dest->pub.next_output_byte = dest->buffer;
|
||||
dest->pub.free_in_buffer = PANGO_JPEG_BUF_SIZE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void pango_jpeg_term_destination (j_compress_ptr cinfo) {
|
||||
pango_jpeg_destination_mgr* dest = (pango_jpeg_destination_mgr*) cinfo->dest;
|
||||
size_t datacount = PANGO_JPEG_BUF_SIZE - dest->pub.free_in_buffer;
|
||||
|
||||
/* Write any data remaining in the buffer */
|
||||
if (datacount > 0) {
|
||||
dest->os->write((const char*)dest->buffer, datacount);
|
||||
if (dest->os->fail()) {
|
||||
throw std::runtime_error("Couldn't write remaining jpeg data to stream.");
|
||||
}
|
||||
}
|
||||
dest->os->flush();
|
||||
}
|
||||
|
||||
void pango_jpeg_set_dest_mgr(j_compress_ptr cinfo, std::ostream& os) {
|
||||
pango_jpeg_destination_mgr* dest;
|
||||
|
||||
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
|
||||
cinfo->dest = (struct jpeg_destination_mgr *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
sizeof(pango_jpeg_destination_mgr));
|
||||
}
|
||||
|
||||
dest = (pango_jpeg_destination_mgr*)cinfo->dest;
|
||||
dest->pub.init_destination = pango_jpeg_init_destination;
|
||||
dest->pub.empty_output_buffer = pango_jpeg_empty_output_buffer;
|
||||
dest->pub.term_destination = pango_jpeg_term_destination;
|
||||
dest->os = &os;
|
||||
}
|
||||
|
||||
#endif // HAVE_JPEG
|
||||
|
||||
TypedImage LoadJpg(std::istream& is) {
|
||||
#ifdef HAVE_JPEG
|
||||
TypedImage image;
|
||||
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
|
||||
// Setup decompression structure
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
jerr.error_exit = error_handler;
|
||||
jpeg_create_decompress(&cinfo);
|
||||
pango_jpeg_set_source_mgr(&cinfo, is);
|
||||
|
||||
// read info from header.
|
||||
int r = jpeg_read_header(&cinfo, TRUE);
|
||||
if (r != JPEG_HEADER_OK) {
|
||||
throw std::runtime_error("Failed to read JPEG header.");
|
||||
} else if (cinfo.num_components != 3 && cinfo.num_components != 1) {
|
||||
throw std::runtime_error("Unsupported number of color components");
|
||||
} else {
|
||||
jpeg_start_decompress(&cinfo);
|
||||
// resize storage if necessary
|
||||
PixelFormat fmt = PixelFormatFromString(cinfo.output_components == 3 ? "RGB24" : "GRAY8");
|
||||
image.Reinitialise(cinfo.output_width, cinfo.output_height, fmt);
|
||||
JSAMPARRAY imageBuffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE,
|
||||
cinfo.output_width*cinfo.output_components, 1);
|
||||
for (size_t y = 0; y < cinfo.output_height; y++) {
|
||||
jpeg_read_scanlines(&cinfo, imageBuffer, 1);
|
||||
uint8_t* dstRow = (uint8_t*)image.RowPtr(y);
|
||||
memcpy(dstRow, imageBuffer[0], cinfo.output_width*cinfo.output_components);
|
||||
}
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
}
|
||||
|
||||
// clean up.
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return image;
|
||||
#else
|
||||
PANGOLIN_UNUSED(is);
|
||||
throw std::runtime_error("Rebuild Pangolin for JPEG support.");
|
||||
#endif // HAVE_JPEG
|
||||
|
||||
}
|
||||
|
||||
TypedImage LoadJpg(const std::string& filename) {
|
||||
std::ifstream f(filename);
|
||||
return LoadJpg(f);
|
||||
}
|
||||
|
||||
void SaveJpg(const Image<unsigned char>& img, const PixelFormat& fmt, std::ostream& os, float quality) {
|
||||
#ifdef HAVE_JPEG
|
||||
const int iquality = (int)std::max(std::min(quality, 100.0f),0.0f);
|
||||
|
||||
struct jpeg_compress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
|
||||
if (fmt.channels != 1 && fmt.channels != 3) {
|
||||
throw std::runtime_error("Unsupported number of image channels.");
|
||||
}
|
||||
if (fmt.bpp != 8 && fmt.bpp != 24) {
|
||||
throw std::runtime_error("Unsupported image depth.");
|
||||
}
|
||||
|
||||
// set up compression structure
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
jpeg_create_compress(&cinfo);
|
||||
pango_jpeg_set_dest_mgr(&cinfo, os);
|
||||
|
||||
cinfo.image_width = img.w;
|
||||
cinfo.image_height = img.h;
|
||||
cinfo.input_components = fmt.channels;
|
||||
if (fmt.channels == 3) {
|
||||
cinfo.in_color_space = JCS_RGB;
|
||||
} else {
|
||||
cinfo.in_color_space = JCS_GRAYSCALE;
|
||||
}
|
||||
|
||||
jpeg_set_defaults(&cinfo);
|
||||
jpeg_set_quality(&cinfo, iquality, (boolean)true);
|
||||
jpeg_start_compress(&cinfo, (boolean)true);
|
||||
|
||||
JSAMPROW row;
|
||||
while (cinfo.next_scanline < cinfo.image_height) {
|
||||
row = (JSAMPROW)((char*)img.RowPtr(cinfo.next_scanline));
|
||||
jpeg_write_scanlines(&cinfo, &row, 1);
|
||||
}
|
||||
|
||||
jpeg_finish_compress(&cinfo);
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
#else
|
||||
PANGOLIN_UNUSED(img);
|
||||
PANGOLIN_UNUSED(fmt);
|
||||
PANGOLIN_UNUSED(os);
|
||||
PANGOLIN_UNUSED(quality);
|
||||
throw std::runtime_error("Rebuild Pangolin for JPEG support.");
|
||||
#endif // HAVE_JPEG
|
||||
}
|
||||
|
||||
void SaveJpg(const Image<unsigned char>& img, const PixelFormat& fmt, const std::string& filename, float quality) {
|
||||
std::ofstream f(filename);
|
||||
SaveJpg(img, fmt, f, quality);
|
||||
}
|
||||
|
||||
}
|
||||
86
thirdparty/Pangolin/src/image/image_io_lz4.cpp
vendored
Normal file
86
thirdparty/Pangolin/src/image/image_io_lz4.cpp
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
#include <pangolin/image/typed_image.h>
|
||||
|
||||
#ifdef HAVE_LZ4
|
||||
# include <lz4.h>
|
||||
#endif
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct lz4_image_header
|
||||
{
|
||||
char magic[3];
|
||||
char fmt[16];
|
||||
size_t w, h;
|
||||
int64_t compressed_size;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
void SaveLz4(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level)
|
||||
{
|
||||
#ifdef HAVE_LZ4
|
||||
const int64_t src_size = image.SizeBytes();
|
||||
const int64_t max_dst_size = LZ4_compressBound(src_size);
|
||||
std::unique_ptr<char[]> output_buffer(new char[max_dst_size]);
|
||||
|
||||
// Same as LZ4_compress_default(), but allows to select an "acceleration" factor.
|
||||
// The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
|
||||
// It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
|
||||
// An acceleration value of "1" is the same as regular LZ4_compress_default()
|
||||
// Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1.
|
||||
const int64_t compressed_data_size = LZ4_compress_fast((char*)image.ptr, output_buffer.get(), src_size, max_dst_size, compression_level);
|
||||
|
||||
if (compressed_data_size < 0)
|
||||
throw std::runtime_error("A negative result from LZ4_compress_default indicates a failure trying to compress the data.");
|
||||
if (compressed_data_size == 0)
|
||||
throw std::runtime_error("A result of 0 for LZ4 means compression worked, but was stopped because the destination buffer couldn't hold all the information.");
|
||||
|
||||
lz4_image_header header;
|
||||
strncpy(header.magic,"LZ4",3);
|
||||
strncpy(header.fmt, fmt.format.c_str(), sizeof(header.fmt));
|
||||
header.w = image.w;
|
||||
header.h = image.h;
|
||||
header.compressed_size = compressed_data_size;
|
||||
out.write((char*)&header, sizeof(header));
|
||||
|
||||
out.write(output_buffer.get(), compressed_data_size);
|
||||
|
||||
#else
|
||||
PANGOLIN_UNUSED(image);
|
||||
PANGOLIN_UNUSED(fmt);
|
||||
PANGOLIN_UNUSED(out);
|
||||
PANGOLIN_UNUSED(compression_level);
|
||||
throw std::runtime_error("Rebuild Pangolin for LZ4 support.");
|
||||
#endif // HAVE_LZ4
|
||||
}
|
||||
|
||||
TypedImage LoadLz4(std::istream& in)
|
||||
{
|
||||
#ifdef HAVE_LZ4
|
||||
// Read in header, uncompressed
|
||||
lz4_image_header header;
|
||||
in.read( (char*)&header, sizeof(header));
|
||||
|
||||
TypedImage img(header.w, header.h, PixelFormatFromString(header.fmt));
|
||||
std::unique_ptr<char[]> input_buffer(new char[header.compressed_size]);
|
||||
|
||||
in.read(input_buffer.get(), header.compressed_size);
|
||||
const int decompressed_size = LZ4_decompress_safe(input_buffer.get(), (char*)img.ptr, header.compressed_size, img.SizeBytes());
|
||||
if (decompressed_size < 0)
|
||||
throw std::runtime_error(FormatString("A negative result from LZ4_decompress_safe indicates a failure trying to decompress the data. See exit code (%) for value returned.", decompressed_size));
|
||||
if (decompressed_size == 0)
|
||||
throw std::runtime_error("I'm not sure this function can ever return 0. Documentation in lz4.h doesn't indicate so.");
|
||||
if (decompressed_size != (int)img.SizeBytes())
|
||||
throw std::runtime_error(FormatString("decompressed size % is not equal to predicted size %", decompressed_size, img.SizeBytes()));
|
||||
|
||||
return img;
|
||||
#else
|
||||
PANGOLIN_UNUSED(in);
|
||||
throw std::runtime_error("Rebuild Pangolin for LZ4 support.");
|
||||
#endif // HAVE_LZ4
|
||||
}
|
||||
|
||||
}
|
||||
85
thirdparty/Pangolin/src/image/image_io_packed12bit.cpp
vendored
Normal file
85
thirdparty/Pangolin/src/image/image_io_packed12bit.cpp
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
#include <pangolin/image/typed_image.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct packed12bit_image_header
|
||||
{
|
||||
char magic[4];
|
||||
char fmt[16];
|
||||
size_t w, h;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
void SavePacked12bit(const Image<uint8_t>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int /*compression_level*/)
|
||||
{
|
||||
|
||||
if (fmt.bpp != 16) {
|
||||
throw std::runtime_error("packed12bit currently only supported with 16bit input image");
|
||||
}
|
||||
|
||||
const size_t dest_pitch = (image.w*12)/ 8 + ((image.w*12) % 8 > 0? 1 : 0);
|
||||
const size_t dest_size = image.h*dest_pitch;
|
||||
std::unique_ptr<uint8_t[]> output_buffer(new uint8_t[dest_size]);
|
||||
|
||||
for(size_t r=0; r<image.h; ++r) {
|
||||
uint8_t* pout = output_buffer.get() + r*dest_pitch;
|
||||
uint16_t* pin = (uint16_t*)(image.ptr + r*image.pitch);
|
||||
const uint16_t* pin_end = (uint16_t*)(image.ptr + (r+1)*image.pitch);
|
||||
while(pin < pin_end) {
|
||||
uint32_t val = (*(pin++) & 0x00000FFF);
|
||||
val |= uint32_t(*(pin++) & 0x00000FFF) << 12;
|
||||
*(pout++) = uint8_t( val & 0x000000FF);
|
||||
*(pout++) = uint8_t((val & 0x0000FF00) >> 8);
|
||||
*(pout++) = uint8_t((val & 0x00FF0000) >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
packed12bit_image_header header;
|
||||
strncpy(header.magic,"P12B",4);
|
||||
strncpy(header.fmt, fmt.format.c_str(), sizeof(header.fmt));
|
||||
header.w = image.w;
|
||||
header.h = image.h;
|
||||
out.write((char*)&header, sizeof(header));
|
||||
out.write((char*)output_buffer.get(), dest_size);
|
||||
|
||||
}
|
||||
|
||||
TypedImage LoadPacked12bit(std::istream& in)
|
||||
{
|
||||
// Read in header, uncompressed
|
||||
packed12bit_image_header header;
|
||||
in.read((char*)&header, sizeof(header));
|
||||
|
||||
TypedImage img(header.w, header.h, PixelFormatFromString(header.fmt));
|
||||
|
||||
if (img.fmt.bpp != 16) {
|
||||
throw std::runtime_error("packed12bit currently only supported with 16bit input image");
|
||||
}
|
||||
|
||||
const size_t input_pitch = (img.w*12)/ 8 + ((img.w*12) % 8 > 0? 1 : 0);
|
||||
const size_t input_size = img.h*input_pitch;
|
||||
std::unique_ptr<uint8_t[]> input_buffer(new uint8_t[input_size]);
|
||||
|
||||
in.read((char*)input_buffer.get(), input_size);
|
||||
|
||||
for(size_t r=0; r<img.h; ++r) {
|
||||
uint16_t* pout = (uint16_t*)(img.ptr + r*img.pitch);
|
||||
uint8_t* pin = input_buffer.get() + r*input_pitch;
|
||||
const uint8_t* pin_end = input_buffer.get() + (r+1)*input_pitch;
|
||||
while(pin < pin_end) {
|
||||
uint32_t val = *(pin++);
|
||||
val |= uint32_t(*(pin++)) << 8;
|
||||
val |= uint32_t(*(pin++)) << 16;
|
||||
*(pout++) = uint16_t( val & 0x000FFF);
|
||||
*(pout++) = uint16_t((val & 0xFFF000) >> 12);
|
||||
}
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
}
|
||||
62
thirdparty/Pangolin/src/image/image_io_pango.cpp
vendored
Normal file
62
thirdparty/Pangolin/src/image/image_io_pango.cpp
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <pangolin/platform.h>
|
||||
|
||||
#include <pangolin/image/typed_image.h>
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
# include <pangolin/video/drivers/pango.h>
|
||||
# include <pangolin/video/drivers/pango_video_output.h>
|
||||
#endif
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
TypedImage LoadPango(const std::string& uri)
|
||||
{
|
||||
PANGOLIN_UNUSED(uri);
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
std::unique_ptr<VideoInterface> video = OpenVideo(uri);
|
||||
if(!video || video->Streams().size() != 1) {
|
||||
throw pangolin::VideoException("Wrong number of streams: exactly one expected.");
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> buffer( new uint8_t[video->SizeBytes()] );
|
||||
const StreamInfo& stream_info = video->Streams()[0];
|
||||
|
||||
// Grab first image from video
|
||||
if(!video->GrabNext(buffer.get(), true)) {
|
||||
throw pangolin::VideoException("Failed to grab image from stream");
|
||||
}
|
||||
|
||||
// Allocate storage for user image to return
|
||||
TypedImage image(stream_info.Width(), stream_info.Height(), stream_info.PixFormat());
|
||||
|
||||
// Copy image data into user buffer.
|
||||
const Image<unsigned char> img = stream_info.StreamImage(buffer.get());
|
||||
PANGO_ENSURE(image.pitch <= img.pitch);
|
||||
for(size_t y=0; y < image.h; ++y) {
|
||||
std::memcpy(image.RowPtr(y), img.RowPtr(y), image.pitch);
|
||||
}
|
||||
|
||||
return image;
|
||||
#else
|
||||
throw std::runtime_error("Video Support not enabled. Please rebuild Pangolin.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void SavePango(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& uri, bool /*top_line_first*/)
|
||||
{
|
||||
PANGOLIN_UNUSED(image);
|
||||
PANGOLIN_UNUSED(fmt);
|
||||
PANGOLIN_UNUSED(uri);
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
std::unique_ptr<VideoOutputInterface> video = OpenVideoOutput(uri);
|
||||
StreamInfo stream(fmt, image.w, image.h, image.pitch);
|
||||
video->SetStreams({stream});
|
||||
video->WriteStreams(image.ptr);
|
||||
#else
|
||||
throw std::runtime_error("Video Support not enabled. Please rebuild Pangolin.");
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
234
thirdparty/Pangolin/src/image/image_io_png.cpp
vendored
Normal file
234
thirdparty/Pangolin/src/image/image_io_png.cpp
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
#include <pangolin/platform.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <pangolin/image/image_io.h>
|
||||
#include <vector>
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
# include <png.h>
|
||||
#endif // HAVE_PNG
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
|
||||
PixelFormat PngFormat(png_structp png_ptr, png_infop info_ptr )
|
||||
{
|
||||
const png_byte colour = png_get_color_type(png_ptr, info_ptr);
|
||||
const png_byte depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||
|
||||
if( depth == 8 ) {
|
||||
if( colour == PNG_COLOR_MASK_COLOR ) {
|
||||
return PixelFormatFromString("RGB24");
|
||||
} else if( colour == (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) ) {
|
||||
return PixelFormatFromString("RGBA32");
|
||||
} else if( colour == PNG_COLOR_MASK_ALPHA ) {
|
||||
return PixelFormatFromString("Y400A");
|
||||
} else {
|
||||
return PixelFormatFromString("GRAY8");
|
||||
}
|
||||
}else if( depth == 16 ) {
|
||||
if( colour == 0 ) {
|
||||
return PixelFormatFromString("GRAY16LE");
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unsupported PNG format");
|
||||
}
|
||||
|
||||
void PNGAPI PngWarningsCallback(png_structp /*png_ptr*/, png_const_charp /*warning_message*/)
|
||||
{
|
||||
// Override default behaviour - don't do anything.
|
||||
}
|
||||
|
||||
#define PNGSIGSIZE 8
|
||||
bool pango_png_validate(std::istream& source)
|
||||
{
|
||||
png_byte pngsig[PNGSIGSIZE];
|
||||
source.read((char*)pngsig, PNGSIGSIZE);
|
||||
return source.good() && png_sig_cmp(pngsig, 0, PNGSIGSIZE) == 0;
|
||||
}
|
||||
|
||||
void pango_png_stream_read(png_structp pngPtr, png_bytep data, png_size_t length) {
|
||||
std::istream* s = (std::istream*)png_get_io_ptr(pngPtr);
|
||||
PANGO_ASSERT(s);
|
||||
s->read((char*)data, length);
|
||||
}
|
||||
|
||||
void pango_png_stream_write(png_structp pngPtr, png_bytep data, png_size_t length) {
|
||||
std::ostream* s = (std::ostream*)png_get_io_ptr(pngPtr);
|
||||
PANGO_ASSERT(s);
|
||||
s->write((char*)data, length);
|
||||
}
|
||||
|
||||
void pango_png_stream_write_flush(png_structp pngPtr)
|
||||
{
|
||||
std::ostream* s = (std::ostream*)png_get_io_ptr(pngPtr);
|
||||
PANGO_ASSERT(s);
|
||||
s->flush();
|
||||
}
|
||||
|
||||
#endif // HAVE_PNG
|
||||
|
||||
|
||||
TypedImage LoadPng(std::istream& source)
|
||||
{
|
||||
#ifdef HAVE_PNG
|
||||
//so First, we validate our stream with the validate function I just mentioned
|
||||
if (!pango_png_validate(source)) {
|
||||
throw std::runtime_error("Not valid PNG header");
|
||||
}
|
||||
|
||||
//set up initial png structs
|
||||
png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, &PngWarningsCallback);
|
||||
if (!png_ptr) {
|
||||
throw std::runtime_error( "PNG Init error 1" );
|
||||
}
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
|
||||
throw std::runtime_error( "PNG Init error 2" );
|
||||
}
|
||||
|
||||
png_infop end_info = png_create_info_struct(png_ptr);
|
||||
if (!end_info) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
throw std::runtime_error( "PNG Init error 3" );
|
||||
}
|
||||
|
||||
png_set_read_fn(png_ptr,(png_voidp)&source, pango_png_stream_read);
|
||||
|
||||
png_set_sig_bytes(png_ptr, PNGSIGSIZE);
|
||||
|
||||
// Setup transformation options
|
||||
if( png_get_bit_depth(png_ptr, info_ptr) == 1) {
|
||||
//Unpack bools to bytes to ease loading.
|
||||
png_set_packing(png_ptr);
|
||||
} else if( png_get_bit_depth(png_ptr, info_ptr) < 8) {
|
||||
//Expand nonbool colour depths up to 8bpp
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
}
|
||||
|
||||
//Get rid of palette, by transforming it to RGB
|
||||
if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
}
|
||||
|
||||
//read the file
|
||||
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_SWAP_ENDIAN, NULL);
|
||||
|
||||
if( png_get_interlace_type(png_ptr,info_ptr) != PNG_INTERLACE_NONE) {
|
||||
throw std::runtime_error( "Interlace not yet supported" );
|
||||
}
|
||||
|
||||
const size_t w = png_get_image_width(png_ptr,info_ptr);
|
||||
const size_t h = png_get_image_height(png_ptr,info_ptr);
|
||||
const size_t pitch = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
TypedImage img(w, h, PngFormat(png_ptr, info_ptr), pitch);
|
||||
|
||||
png_bytepp rows = png_get_rows(png_ptr, info_ptr);
|
||||
for( unsigned int r = 0; r < h; r++) {
|
||||
memcpy( img.ptr + pitch*r, rows[r], pitch );
|
||||
}
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
|
||||
return img;
|
||||
#else
|
||||
PANGOLIN_UNUSED(source);
|
||||
throw std::runtime_error("Rebuild Pangolin for PNG support.");
|
||||
#endif // HAVE_PNG
|
||||
}
|
||||
|
||||
TypedImage LoadPng(const std::string& filename)
|
||||
{
|
||||
std::ifstream f(filename);
|
||||
return LoadPng(f);
|
||||
}
|
||||
|
||||
void SavePng(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& stream, bool top_line_first, int zlib_compression_level)
|
||||
{
|
||||
#ifdef HAVE_PNG
|
||||
// Check image has supported bit depth
|
||||
for(unsigned int i=1; i < fmt.channels; ++i) {
|
||||
if( fmt.channel_bits[i] != fmt.channel_bits[0] ) {
|
||||
throw std::runtime_error("PNG Saving only supported for images where each channel has the same bit depth.");
|
||||
}
|
||||
}
|
||||
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
|
||||
// Initialize write structure
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (png_ptr == NULL) {
|
||||
throw std::runtime_error( "PNG Error: Could not allocate write struct." );
|
||||
}
|
||||
|
||||
// Initialize info structure
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||
throw std::runtime_error( "PNG Error: Could not allocate info struct." );
|
||||
}
|
||||
|
||||
// Setup Exception handling
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||
throw std::runtime_error( "PNG Error: Error during png creation." );
|
||||
}
|
||||
|
||||
png_set_compression_level(png_ptr, zlib_compression_level);
|
||||
|
||||
png_set_write_fn(png_ptr,(png_voidp)&stream, pango_png_stream_write, pango_png_stream_write_flush);
|
||||
|
||||
const int bit_depth = fmt.channel_bits[0];
|
||||
|
||||
int colour_type;
|
||||
switch (fmt.channels) {
|
||||
case 1: colour_type = PNG_COLOR_TYPE_GRAY; break;
|
||||
case 2: colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
|
||||
case 3: colour_type = PNG_COLOR_TYPE_RGB; break;
|
||||
case 4: colour_type = PNG_COLOR_TYPE_RGBA; break;
|
||||
default:
|
||||
throw std::runtime_error( "PNG Error: unexpected image channel number");
|
||||
}
|
||||
|
||||
// Write header
|
||||
png_set_IHDR(
|
||||
png_ptr, info_ptr, (png_uint_32)image.w, (png_uint_32)image.h, bit_depth, colour_type,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT
|
||||
);
|
||||
|
||||
// Setup rows to write:
|
||||
std::vector<png_bytep> rows(image.h);
|
||||
if(top_line_first) {
|
||||
for (unsigned int y = 0; y< image.h; y++) {
|
||||
rows[y] = image.ptr + y*image.pitch;
|
||||
}
|
||||
}else{
|
||||
for (unsigned int y = 0; y< image.h; y++) {
|
||||
rows[y] = image.ptr + (image.h-1-y)*image.pitch;
|
||||
}
|
||||
}
|
||||
png_set_rows(png_ptr,info_ptr, &rows[0]);
|
||||
|
||||
// Write image data: switch to little-endian byte order, to match host.
|
||||
png_write_png(png_ptr,info_ptr, PNG_TRANSFORM_SWAP_ENDIAN, 0);
|
||||
|
||||
// Free resources
|
||||
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||
#else
|
||||
PANGOLIN_UNUSED(image);
|
||||
PANGOLIN_UNUSED(fmt);
|
||||
PANGOLIN_UNUSED(stream);
|
||||
PANGOLIN_UNUSED(top_line_first);
|
||||
PANGOLIN_UNUSED(zlib_compression_level);
|
||||
throw std::runtime_error("Rebuild Pangolin for PNG support.");
|
||||
#endif // HAVE_PNG
|
||||
}
|
||||
|
||||
}
|
||||
104
thirdparty/Pangolin/src/image/image_io_ppm.cpp
vendored
Normal file
104
thirdparty/Pangolin/src/image/image_io_ppm.cpp
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
#include <fstream>
|
||||
#include <pangolin/image/typed_image.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
PixelFormat PpmFormat(const std::string& strType, int num_colours)
|
||||
{
|
||||
if(strType == "P5") {
|
||||
if(num_colours < 256) {
|
||||
return PixelFormatFromString("GRAY8");
|
||||
} else {
|
||||
return PixelFormatFromString("GRAY16LE");
|
||||
}
|
||||
}else if(strType == "P6") {
|
||||
return PixelFormatFromString("RGB24");
|
||||
}else{
|
||||
throw std::runtime_error("Unsupported PPM/PGM format");
|
||||
}
|
||||
}
|
||||
|
||||
void PpmConsumeWhitespaceAndComments(std::istream& in)
|
||||
{
|
||||
// TODO: Make a little more general / more efficient
|
||||
while( in.peek() == ' ' ) in.get();
|
||||
while( in.peek() == '\n' ) in.get();
|
||||
while( in.peek() == '#' ) in.ignore(4096, '\n');
|
||||
}
|
||||
|
||||
TypedImage LoadPpm(std::istream& in)
|
||||
{
|
||||
// Parse header
|
||||
std::string ppm_type = "";
|
||||
int num_colors = 0;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
|
||||
in >> ppm_type;
|
||||
PpmConsumeWhitespaceAndComments(in);
|
||||
in >> w;
|
||||
PpmConsumeWhitespaceAndComments(in);
|
||||
in >> h;
|
||||
PpmConsumeWhitespaceAndComments(in);
|
||||
in >> num_colors;
|
||||
in.ignore(1,'\n');
|
||||
|
||||
if(!in.fail() && w > 0 && h > 0) {
|
||||
TypedImage img(w, h, PpmFormat(ppm_type, num_colors) );
|
||||
|
||||
// Read in data
|
||||
for(size_t r=0; r<img.h; ++r) {
|
||||
in.read( (char*)img.ptr + r*img.pitch, img.pitch );
|
||||
}
|
||||
if(!in.fail()) {
|
||||
return img;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unable to load PPM file.");
|
||||
}
|
||||
|
||||
void SavePpm(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, bool top_line_first)
|
||||
{
|
||||
// Setup header variables
|
||||
std::string ppm_type = "";
|
||||
int num_colors = 0;
|
||||
int w = (int)image.w;
|
||||
int h = (int)image.h;
|
||||
|
||||
if(fmt.format == "GRAY8") {
|
||||
ppm_type = "P5";
|
||||
num_colors = 255;
|
||||
}else if(fmt.format == "GRAY16LE") {
|
||||
ppm_type = "P5";
|
||||
num_colors = 65535;
|
||||
}else if(fmt.format == "RGB24") {
|
||||
ppm_type = "P6";
|
||||
num_colors = 255;
|
||||
}else{
|
||||
throw std::runtime_error("Unsupported pixel format");
|
||||
}
|
||||
|
||||
// Write header
|
||||
out << ppm_type;
|
||||
out << " ";
|
||||
out << w;
|
||||
out << " ";
|
||||
out << h;
|
||||
out << " ";
|
||||
out << num_colors;
|
||||
out << "\n";
|
||||
|
||||
// Write out data
|
||||
if(top_line_first) {
|
||||
for(size_t r=0; r<image.h; ++r) {
|
||||
out.write( (char*)image.ptr + r*image.pitch, image.pitch );
|
||||
}
|
||||
}else{
|
||||
for(size_t r=0; r<image.h; ++r) {
|
||||
out.write( (char*)image.ptr + (image.h-1-r)*image.pitch, image.pitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
25
thirdparty/Pangolin/src/image/image_io_raw.cpp
vendored
Normal file
25
thirdparty/Pangolin/src/image/image_io_raw.cpp
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <fstream>
|
||||
#include <pangolin/image/typed_image.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
TypedImage LoadImage(
|
||||
const std::string& filename,
|
||||
const PixelFormat& raw_fmt,
|
||||
size_t raw_width, size_t raw_height, size_t raw_pitch
|
||||
) {
|
||||
TypedImage img(raw_width, raw_height, raw_fmt, raw_pitch);
|
||||
|
||||
// Read from file, row at a time.
|
||||
std::ifstream bFile( filename.c_str(), std::ios::in | std::ios::binary );
|
||||
for(size_t r=0; r<img.h; ++r) {
|
||||
bFile.read( (char*)img.ptr + r*img.pitch, img.pitch );
|
||||
if(bFile.fail()) {
|
||||
pango_print_warn("Unable to read raw image file to completion.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
}
|
||||
53
thirdparty/Pangolin/src/image/image_io_tga.cpp
vendored
Normal file
53
thirdparty/Pangolin/src/image/image_io_tga.cpp
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <pangolin/platform.h>
|
||||
|
||||
#include <pangolin/image/image_io.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
PixelFormat TgaFormat(int depth, int color_type, int color_map)
|
||||
{
|
||||
if(color_map == 0) {
|
||||
if(color_type == 2) {
|
||||
// Colour
|
||||
if(depth == 24) {
|
||||
return PixelFormatFromString("RGB24");
|
||||
}else if(depth == 32) {
|
||||
return PixelFormatFromString("RGBA32");
|
||||
}
|
||||
}else if(color_type == 3){
|
||||
// Greyscale
|
||||
if(depth == 8) {
|
||||
return PixelFormatFromString("GRAY8");
|
||||
}else if(depth == 16) {
|
||||
return PixelFormatFromString("Y400A");
|
||||
}
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("Unsupported TGA format");
|
||||
}
|
||||
|
||||
TypedImage LoadTga(std::istream& in)
|
||||
{
|
||||
unsigned char type[4];
|
||||
unsigned char info[6];
|
||||
|
||||
in.read((char*)type, 3*sizeof(char));
|
||||
in.seekg(12);
|
||||
in.read((char*)info,6*sizeof(char));
|
||||
|
||||
const int width = info[0] + (info[1] * 256);
|
||||
const int height = info[2] + (info[3] * 256);
|
||||
|
||||
if(in.good()) {
|
||||
TypedImage img(width, height, TgaFormat(info[4], type[2], type[1]) );
|
||||
|
||||
//read in image data
|
||||
const size_t data_size = img.h * img.pitch;
|
||||
in.read((char*)img.ptr, sizeof(char)*data_size);
|
||||
return img;
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unable to load TGA file");
|
||||
}
|
||||
|
||||
}
|
||||
125
thirdparty/Pangolin/src/image/image_io_zstd.cpp
vendored
Normal file
125
thirdparty/Pangolin/src/image/image_io_zstd.cpp
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
||||
#include <pangolin/image/typed_image.h>
|
||||
|
||||
#ifdef HAVE_ZSTD
|
||||
# include <zstd.h>
|
||||
#endif
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct zstd_image_header
|
||||
{
|
||||
char magic[4];
|
||||
char fmt[16];
|
||||
size_t w, h;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
void SaveZstd(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, std::ostream& out, int compression_level)
|
||||
{
|
||||
#ifdef HAVE_ZSTD
|
||||
// Write out header, uncompressed
|
||||
zstd_image_header header;
|
||||
strncpy(header.magic,"ZSTD",4);
|
||||
strncpy(header.fmt, fmt.format.c_str(), sizeof(header.fmt));
|
||||
header.w = image.w;
|
||||
header.h = image.h;
|
||||
out.write((char*)&header, sizeof(header));
|
||||
|
||||
// Write out image data
|
||||
const size_t output_buffer_size = ZSTD_CStreamOutSize();
|
||||
std::unique_ptr<char[]> output_buffer(new char[output_buffer_size]);
|
||||
|
||||
ZSTD_CStream* const cstream = ZSTD_createCStream();
|
||||
if (cstream==nullptr) {
|
||||
throw std::runtime_error("ZSTD_createCStream() error");
|
||||
}
|
||||
|
||||
size_t const initResult = ZSTD_initCStream(cstream, compression_level);
|
||||
if (ZSTD_isError(initResult)) {
|
||||
throw std::runtime_error(FormatString("ZSTD_initCStream() error : %", ZSTD_getErrorName(initResult)));
|
||||
}
|
||||
|
||||
const size_t row_size_bytes = (fmt.bpp * image.w)/8;
|
||||
|
||||
for(size_t y=0; y < image.h; ++y) {
|
||||
ZSTD_inBuffer input = { image.RowPtr(y), row_size_bytes, 0 };
|
||||
|
||||
while (input.pos < input.size) {
|
||||
ZSTD_outBuffer output = { output_buffer.get(), output_buffer_size, 0 };
|
||||
size_t left_to_read = ZSTD_compressStream(cstream, &output , &input);
|
||||
if (ZSTD_isError(left_to_read)) {
|
||||
throw std::runtime_error(FormatString("ZSTD_compressStream() error : %", ZSTD_getErrorName(left_to_read)));
|
||||
}
|
||||
out.write(output_buffer.get(), output.pos);
|
||||
}
|
||||
}
|
||||
|
||||
ZSTD_outBuffer output = { output_buffer.get(), output_buffer_size, 0 };
|
||||
size_t const remainingToFlush = ZSTD_endStream(cstream, &output); /* close frame */
|
||||
if (remainingToFlush) {
|
||||
throw std::runtime_error("not fully flushed");
|
||||
}
|
||||
out.write(output_buffer.get(), output.pos);
|
||||
|
||||
ZSTD_freeCStream(cstream);
|
||||
#else
|
||||
PANGOLIN_UNUSED(image);
|
||||
PANGOLIN_UNUSED(fmt);
|
||||
PANGOLIN_UNUSED(out);
|
||||
PANGOLIN_UNUSED(compression_level);
|
||||
throw std::runtime_error("Rebuild Pangolin for ZSTD support.");
|
||||
#endif // HAVE_ZSTD
|
||||
}
|
||||
|
||||
TypedImage LoadZstd(std::istream& in)
|
||||
{
|
||||
#ifdef HAVE_ZSTD
|
||||
// Read in header, uncompressed
|
||||
zstd_image_header header;
|
||||
in.read( (char*)&header, sizeof(header));
|
||||
|
||||
TypedImage img(header.w, header.h, PixelFormatFromString(header.fmt));
|
||||
|
||||
const size_t input_buffer_size = ZSTD_DStreamInSize();
|
||||
std::unique_ptr<char[]> input_buffer(new char[input_buffer_size]);
|
||||
|
||||
ZSTD_DStream* dstream = ZSTD_createDStream();
|
||||
if(!dstream) {
|
||||
throw std::runtime_error("ZSTD_createDStream() error");
|
||||
}
|
||||
|
||||
size_t read_size_hint = ZSTD_initDStream(dstream);
|
||||
if (ZSTD_isError(read_size_hint)) {
|
||||
throw std::runtime_error(FormatString("ZSTD_initDStream() error : % \n", ZSTD_getErrorName(read_size_hint)));
|
||||
}
|
||||
|
||||
// Image represents our fixed buffer.
|
||||
ZSTD_outBuffer output = { img.ptr, img.SizeBytes(), 0 };
|
||||
|
||||
while(read_size_hint)
|
||||
{
|
||||
const size_t read = in.readsome(input_buffer.get(), read_size_hint);
|
||||
ZSTD_inBuffer input = { input_buffer.get(), read, 0 };
|
||||
while (input.pos < input.size) {
|
||||
read_size_hint = ZSTD_decompressStream(dstream, &output , &input);
|
||||
if (ZSTD_isError(read_size_hint)) {
|
||||
throw std::runtime_error(FormatString("ZSTD_decompressStream() error : %", ZSTD_getErrorName(read_size_hint)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZSTD_freeDStream(dstream);
|
||||
|
||||
return img;
|
||||
#else
|
||||
PANGOLIN_UNUSED(in);
|
||||
throw std::runtime_error("Rebuild Pangolin for ZSTD support.");
|
||||
#endif // HAVE_ZSTD
|
||||
}
|
||||
|
||||
}
|
||||
70
thirdparty/Pangolin/src/image/pixel_format.cpp
vendored
Normal file
70
thirdparty/Pangolin/src/image/pixel_format.cpp
vendored
Normal 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/image/pixel_format.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
// Not to exceed 8 byte Format code.
|
||||
const PixelFormat SupportedPixelFormats[] =
|
||||
{
|
||||
{"GRAY8", 1, {8}, 8, 8, false},
|
||||
{"GRAY10", 1, {10}, 10, 10, false},
|
||||
{"GRAY12", 1, {12}, 12, 12, false},
|
||||
{"GRAY16LE", 1, {16}, 16, 16, false},
|
||||
{"GRAY32", 1, {32}, 32, 32, false},
|
||||
{"Y400A", 2, {8,8}, 16, 8, false},
|
||||
{"RGB24", 3, {8,8,8}, 24, 8, false},
|
||||
{"BGR24", 3, {8,8,8}, 24, 8, false},
|
||||
{"RGB48", 3, {16,16,16}, 48, 16, false},
|
||||
{"BGR48", 3, {16,16,16}, 48, 16, false},
|
||||
{"YUYV422", 3, {4,2,2}, 16, 8, false},
|
||||
{"UYVY422", 3, {4,2,2}, 16, 8, false},
|
||||
{"RGBA32", 4, {8,8,8,8}, 32, 8, false},
|
||||
{"BGRA32", 4, {8,8,8,8}, 32, 8, false},
|
||||
{"RGBA64", 4, {16,16,16,16}, 64, 16, false},
|
||||
{"BGRA64", 4, {16,16,16,16}, 64, 16, false},
|
||||
{"GRAY32F", 1, {32}, 32, 32, false},
|
||||
{"GRAY64F", 1, {64}, 64, 64, false},
|
||||
{"RGB96F", 3, {32,32,32}, 96, 32, false},
|
||||
{"RGBA128F", 4, {32,32,32,32}, 128, 32, false},
|
||||
{"",0,{0,0,0,0},0,0,0}
|
||||
};
|
||||
|
||||
PixelFormat PixelFormatFromString(const std::string& format)
|
||||
{
|
||||
for(int i=0; !SupportedPixelFormats[i].format.empty(); ++i)
|
||||
if(!format.compare(SupportedPixelFormats[i].format))
|
||||
return SupportedPixelFormats[i];
|
||||
throw std::runtime_error( std::string("Unknown Format: ") + format);
|
||||
}
|
||||
|
||||
}
|
||||
49
thirdparty/Pangolin/src/ios/PangolinAppDelegate.mm
vendored
Normal file
49
thirdparty/Pangolin/src/ios/PangolinAppDelegate.mm
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// GlTestAppDelegate.m
|
||||
// gltest
|
||||
//
|
||||
// Created by Steven Lovegrove on 30/01/2014.
|
||||
// Copyright (c) 2014 Steven Lovegrove. All rights reserved.
|
||||
//
|
||||
|
||||
#import <pangolin/ios/PangolinAppDelegate.h>
|
||||
#import <pangolin/ios/PangolinUIView.h>
|
||||
|
||||
@implementation PangolinAppDelegate
|
||||
|
||||
@synthesize window=_window;
|
||||
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application
|
||||
{
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application
|
||||
{
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application
|
||||
{
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application
|
||||
{
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application
|
||||
{
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
@end
|
||||
202
thirdparty/Pangolin/src/ios/PangolinUIView.mm
vendored
Normal file
202
thirdparty/Pangolin/src/ios/PangolinUIView.mm
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
/* 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 <QuartzCore/QuartzCore.h>
|
||||
|
||||
#import <pangolin/ios/PangolinUIView.h>
|
||||
#import <pangolin/ios/PangolinAppDelegate.h>
|
||||
|
||||
#include <pangolin/factory/factory_registry.h>
|
||||
#include <pangolin/pangolin.h>
|
||||
#include <pangolin/platform.h>
|
||||
#include <pangolin/gl/glinclude.h>
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/display_internal.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
extern __thread PangolinGl* context;
|
||||
}
|
||||
|
||||
|
||||
@implementation PangolinUIView
|
||||
|
||||
+ (Class)layerClass {
|
||||
return [CAEAGLLayer class];
|
||||
}
|
||||
|
||||
- (void)setupLayer {
|
||||
_eaglLayer = (CAEAGLLayer*) self.layer;
|
||||
_eaglLayer.opaque = YES;
|
||||
}
|
||||
|
||||
- (void)setupContext {
|
||||
EAGLRenderingAPI api = kEAGLRenderingAPIOpenGLES2;
|
||||
_context = [[EAGLContext alloc] initWithAPI:api];
|
||||
if (!_context) {
|
||||
NSLog(@"Failed to initialize OpenGLES 2.0 context");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (![EAGLContext setCurrentContext:_context]) {
|
||||
NSLog(@"Failed to set current OpenGL context");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupRenderBuffer {
|
||||
glGenRenderbuffers(1, &_colorRenderBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
|
||||
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer];
|
||||
}
|
||||
|
||||
- (void)setupDepthBuffer {
|
||||
glGenRenderbuffers(1, &_depthRenderBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);
|
||||
const int w = self.frame.size.width * self.contentScaleFactor;
|
||||
const int h = self.frame.size.height * self.contentScaleFactor;
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, w, h);
|
||||
}
|
||||
|
||||
- (void)setupFrameBuffer {
|
||||
GLuint framebuffer;
|
||||
glGenFramebuffers(1, &framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBuffer);
|
||||
}
|
||||
|
||||
- (void)render:(CADisplayLink*)displayLink {
|
||||
pangolin::glEngine().prog_fixed.Bind();
|
||||
|
||||
if(pangolin::context->user_app) {
|
||||
pangolin::context->user_app->Render();
|
||||
}
|
||||
|
||||
pangolin::RenderViews();
|
||||
pangolin::PostRender();
|
||||
|
||||
[_context presentRenderbuffer:GL_RENDERBUFFER];
|
||||
}
|
||||
|
||||
- (void)setupDisplayLink {
|
||||
CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render:)];
|
||||
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
}
|
||||
|
||||
- (void)setup
|
||||
{
|
||||
self.contentScaleFactor = 2;
|
||||
|
||||
[self setupLayer];
|
||||
[self setupContext];
|
||||
[self setupDepthBuffer];
|
||||
[self setupRenderBuffer];
|
||||
[self setupFrameBuffer];
|
||||
[self setupDisplayLink];
|
||||
|
||||
pangolin::PangolinCommonInit();
|
||||
|
||||
const int w = self.frame.size.width * self.contentScaleFactor;
|
||||
const int h = self.frame.size.height * self.contentScaleFactor;
|
||||
pangolin::process::Resize(w,h);
|
||||
|
||||
if(pangolin::context->user_app) {
|
||||
pangolin::context->user_app->Init();
|
||||
}
|
||||
}
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
|
||||
if (self) {
|
||||
[self setup];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[self setup];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
_context = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
int LaunchUserApp(UserApp& app)
|
||||
{
|
||||
// Create new context
|
||||
BindToContext("UserApp");
|
||||
|
||||
// Reference user application
|
||||
context->user_app = &app;
|
||||
|
||||
// Start IOS Window containing GL Context from which we'll receive events
|
||||
// These events will be communicated to pangolin::process::... and the UserApp app.
|
||||
int argc = 1;
|
||||
char* argv[] = { (char*)"dummy" };
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([PangolinAppDelegate class]));
|
||||
}
|
||||
}
|
||||
|
||||
// Implement platform agnostic version
|
||||
void CreateIosWindowAndBind(std::string window_title, int w, int h )
|
||||
{
|
||||
throw std::runtime_error("pangolin::CreateWindowAndBind(...) Not supported on this platform");
|
||||
}
|
||||
|
||||
// Implement platform agnostic version
|
||||
void FinishFrame()
|
||||
{
|
||||
throw std::runtime_error("pangolin::FinishFrame() Not supported on this platform");
|
||||
}
|
||||
|
||||
PANGOLIN_REGISTER_FACTORY(IosWindow)
|
||||
{
|
||||
struct IosWindowFactory : public FactoryInterface<WindowInterface> {
|
||||
std::unique_ptr<WindowInterface> Open(const Uri& uri) override {
|
||||
|
||||
const std::string window_title = uri.Get<std::string>("window_title", "window");
|
||||
CreateIosWindowAndBind(window_title, 0, 0);
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
auto factory = std::make_shared<IosWindowFactory>();
|
||||
FactoryRegistry<WindowInterface>::I().RegisterFactory(factory, 10, "ioswindow");
|
||||
}
|
||||
}
|
||||
|
||||
79
thirdparty/Pangolin/src/log/packet.cpp
vendored
Normal file
79
thirdparty/Pangolin/src/log/packet.cpp
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <pangolin/log/packet.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
|
||||
Packet::Packet(PacketStream& s, std::unique_lock<std::recursive_mutex>&& lock, std::vector<PacketStreamSource>& srcs)
|
||||
: _stream(s), lock(std::move(lock))
|
||||
{
|
||||
ParsePacketHeader(s, srcs);
|
||||
}
|
||||
|
||||
Packet::Packet(Packet&& o)
|
||||
: src(o.src), time(o.time), size(o.size), sequence_num(o.sequence_num),
|
||||
meta(std::move(o.meta)), frame_streampos(o.frame_streampos), _stream(o._stream),
|
||||
lock(std::move(o.lock)), data_streampos(o.data_streampos), _data_len(o._data_len)
|
||||
{
|
||||
o._data_len = 0;
|
||||
}
|
||||
|
||||
Packet::~Packet()
|
||||
{
|
||||
ReadRemaining();
|
||||
}
|
||||
|
||||
size_t Packet::BytesRead() const
|
||||
{
|
||||
return _stream.tellg() - data_streampos;
|
||||
}
|
||||
|
||||
int Packet::BytesRemaining() const
|
||||
{
|
||||
if(_data_len) {
|
||||
return (int)_data_len - (int)BytesRead();
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Packet::ParsePacketHeader(PacketStream& s, std::vector<PacketStreamSource>& srcs)
|
||||
{
|
||||
size_t json_src = -1;
|
||||
|
||||
frame_streampos = s.tellg();
|
||||
if (s.peekTag() == TAG_SRC_JSON)
|
||||
{
|
||||
s.readTag(TAG_SRC_JSON);
|
||||
json_src = s.readUINT();
|
||||
picojson::parse(meta, s);
|
||||
}
|
||||
|
||||
s.readTag(TAG_SRC_PACKET);
|
||||
time = s.readTimestamp();
|
||||
|
||||
src = s.readUINT();
|
||||
PANGO_ENSURE(json_src == size_t(-1) || json_src == src, "Frame preceded by metadata for a mismatched source. Stream may be corrupt.");
|
||||
|
||||
PacketStreamSource& src_packet = srcs[src];
|
||||
|
||||
size = src_packet.data_size_bytes;
|
||||
if (!size) {
|
||||
size = s.readUINT();
|
||||
}
|
||||
sequence_num = src_packet.next_packet_id++;
|
||||
|
||||
_data_len = size;
|
||||
data_streampos = s.tellg();
|
||||
}
|
||||
|
||||
void Packet::ReadRemaining()
|
||||
{
|
||||
int bytes_left = BytesRemaining();
|
||||
|
||||
while(bytes_left > 0 && Stream().good()) {
|
||||
Stream().skip(bytes_left);
|
||||
bytes_left = BytesRemaining();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
146
thirdparty/Pangolin/src/log/packetstream.cpp
vendored
Normal file
146
thirdparty/Pangolin/src/log/packetstream.cpp
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
#include <pangolin/log/packetstream.h>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
size_t PacketStream::readUINT()
|
||||
{
|
||||
size_t n = 0;
|
||||
size_t v = get();
|
||||
uint32_t shift = 0;
|
||||
while (good() && (v & 0x80))
|
||||
{
|
||||
n |= (v & 0x7F) << shift;
|
||||
shift += 7;
|
||||
v = get();
|
||||
}
|
||||
if (!good())
|
||||
return static_cast<size_t>(-1);
|
||||
return n | (v & 0x7F) << shift;
|
||||
}
|
||||
|
||||
int64_t PacketStream::readTimestamp()
|
||||
{
|
||||
int64_t time_us;
|
||||
read(reinterpret_cast<char*>(&time_us), sizeof(int64_t));
|
||||
return time_us;
|
||||
}
|
||||
|
||||
pangoTagType PacketStream::readTag()
|
||||
{
|
||||
auto r = peekTag();
|
||||
_tag = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
pangoTagType PacketStream::readTag(pangoTagType x)
|
||||
{
|
||||
auto r = readTag();
|
||||
if (r != x)
|
||||
throw std::runtime_error(("Tag mismatch error: expected tag '" + tagName(r) + "' does not match found tag '" + tagName(x) + "'").c_str());
|
||||
return r;
|
||||
}
|
||||
|
||||
pangoTagType PacketStream::peekTag()
|
||||
{
|
||||
if (!_tag)
|
||||
{
|
||||
_tag = 0;
|
||||
Base::read(reinterpret_cast<char*>(&_tag), TAG_LENGTH);
|
||||
if (!good())
|
||||
_tag = TAG_END;
|
||||
}
|
||||
return _tag;
|
||||
}
|
||||
|
||||
char PacketStream::get()
|
||||
{
|
||||
_tag = 0;
|
||||
return Base::get();
|
||||
}
|
||||
|
||||
size_t PacketStream::read(char* target, size_t len)
|
||||
{
|
||||
_tag = 0;
|
||||
Base::read(target, len);
|
||||
return gcount();
|
||||
}
|
||||
|
||||
size_t PacketStream::skip(size_t len)
|
||||
{
|
||||
if (seekable()) {
|
||||
Base::seekg(len, std::ios_base::cur);
|
||||
} else {
|
||||
Base::ignore(len);
|
||||
}
|
||||
cclear();
|
||||
return len;
|
||||
}
|
||||
|
||||
std::streampos PacketStream::tellg()
|
||||
{
|
||||
if (_tag) {
|
||||
return Base::tellg() - std::streamoff(TAG_LENGTH);
|
||||
}else{
|
||||
return Base::tellg();
|
||||
}
|
||||
}
|
||||
|
||||
void PacketStream::seekg(std::streampos target)
|
||||
{
|
||||
if (seekable()) {
|
||||
cclear();
|
||||
Base::seekg(target);
|
||||
}
|
||||
}
|
||||
|
||||
void PacketStream::seekg(std::streamoff off, std::ios_base::seekdir way)
|
||||
{
|
||||
if (seekable()) {
|
||||
cclear();
|
||||
Base::seekg(off, way);
|
||||
}
|
||||
}
|
||||
|
||||
static bool valid(pangoTagType t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case TAG_PANGO_SYNC:
|
||||
case TAG_ADD_SOURCE:
|
||||
case TAG_SRC_JSON:
|
||||
case TAG_SRC_PACKET:
|
||||
case TAG_PANGO_STATS:
|
||||
case TAG_PANGO_FOOTER:
|
||||
case TAG_END:
|
||||
case TAG_PANGO_HDR:
|
||||
case TAG_PANGO_MAGIC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
pangoTagType PacketStream::syncToTag() //scan through chars one by one until the last three look like a tag
|
||||
{
|
||||
peekTag();
|
||||
char * buffer = reinterpret_cast<char*>(&_tag);
|
||||
|
||||
buffer[3] = 0;
|
||||
|
||||
do
|
||||
{
|
||||
buffer[0] = buffer[1];
|
||||
buffer[1] = buffer[2];
|
||||
buffer[2] = get();
|
||||
}
|
||||
while (good() && !valid(_tag));
|
||||
|
||||
if (!good())
|
||||
_tag = TAG_END;
|
||||
|
||||
return _tag;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
425
thirdparty/Pangolin/src/log/packetstream_reader.cpp
vendored
Normal file
425
thirdparty/Pangolin/src/log/packetstream_reader.cpp
vendored
Normal file
@@ -0,0 +1,425 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/log/packetstream_reader.h>
|
||||
#include <pangolin/log/packetstream_writer.h>
|
||||
|
||||
using std::string;
|
||||
using std::istream;
|
||||
using std::ios;
|
||||
using std::lock_guard;
|
||||
using std::runtime_error;
|
||||
using std::ios_base;
|
||||
using std::streampos;
|
||||
using std::streamoff;
|
||||
|
||||
#include <thread>
|
||||
|
||||
#ifndef _WIN_
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
PacketStreamReader::PacketStreamReader()
|
||||
: _pipe_fd(-1)
|
||||
{
|
||||
}
|
||||
|
||||
PacketStreamReader::PacketStreamReader(const std::string& filename)
|
||||
: _pipe_fd(-1)
|
||||
{
|
||||
Open(filename);
|
||||
}
|
||||
|
||||
PacketStreamReader::~PacketStreamReader()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void PacketStreamReader::Open(const std::string& filename)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lg(_mutex);
|
||||
|
||||
Close();
|
||||
|
||||
_filename = filename;
|
||||
_is_pipe = IsPipe(filename);
|
||||
_stream.open(filename);
|
||||
|
||||
if (!_stream.is_open())
|
||||
throw runtime_error("Cannot open stream.");
|
||||
|
||||
for (auto i : PANGO_MAGIC)
|
||||
{
|
||||
if (_stream.get() != i)
|
||||
throw runtime_error("Unrecognised file header.");
|
||||
if (!_stream.good())
|
||||
throw runtime_error("Bad stream");
|
||||
}
|
||||
|
||||
|
||||
ParseHeader();
|
||||
|
||||
while (_stream.peekTag() == TAG_ADD_SOURCE) {
|
||||
ParseNewSource();
|
||||
}
|
||||
|
||||
if(!SetupIndex()) {
|
||||
FixFileIndex();
|
||||
}
|
||||
}
|
||||
|
||||
void PacketStreamReader::Close() {
|
||||
std::lock_guard<std::recursive_mutex> lg(_mutex);
|
||||
|
||||
_stream.close();
|
||||
_sources.clear();
|
||||
|
||||
#ifndef _WIN_
|
||||
if (_pipe_fd != -1) {
|
||||
close(_pipe_fd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PacketStreamReader::ParseHeader()
|
||||
{
|
||||
_stream.readTag(TAG_PANGO_HDR);
|
||||
|
||||
picojson::value json_header;
|
||||
picojson::parse(json_header, _stream);
|
||||
|
||||
// File timestamp
|
||||
const int64_t start_us = json_header["time_us"].get<int64_t>();
|
||||
packet_stream_start = SyncTime::TimePoint() + std::chrono::microseconds(start_us);
|
||||
|
||||
_stream.get(); // consume newline
|
||||
}
|
||||
|
||||
void PacketStreamReader::ParseNewSource()
|
||||
{
|
||||
_stream.readTag(TAG_ADD_SOURCE);
|
||||
picojson::value json;
|
||||
picojson::parse(json, _stream);
|
||||
_stream.get(); // consume newline
|
||||
|
||||
|
||||
const size_t src_id = json[pss_src_id].get<int64_t>();
|
||||
|
||||
if(_sources.size() <= src_id) {
|
||||
_sources.resize(src_id+1);
|
||||
}
|
||||
|
||||
PacketStreamSource& pss = _sources[src_id];
|
||||
pss.id = src_id;
|
||||
pss.driver = json[pss_src_driver].get<string>();
|
||||
pss.uri = json[pss_src_uri].get<string>();
|
||||
pss.info = json[pss_src_info];
|
||||
pss.version = json[pss_src_version].get<int64_t>();
|
||||
pss.data_alignment_bytes = json[pss_src_packet][pss_pkt_alignment_bytes].get<int64_t>();
|
||||
pss.data_definitions = json[pss_src_packet][pss_pkt_definitions].get<string>();
|
||||
pss.data_size_bytes = json[pss_src_packet][pss_pkt_size_bytes].get<int64_t>();
|
||||
}
|
||||
|
||||
bool PacketStreamReader::SetupIndex()
|
||||
{
|
||||
bool index_good = false;
|
||||
|
||||
if (_stream.seekable())
|
||||
{
|
||||
// Save current position
|
||||
std::streampos pos = _stream.tellg();
|
||||
|
||||
// Look for footer at end of file (TAG_PANGO_FOOTER + index position).
|
||||
_stream.seekg(-(static_cast<istream::off_type>(sizeof(uint64_t)) + TAG_LENGTH), ios_base::end);
|
||||
if (_stream.peekTag() == TAG_PANGO_FOOTER)
|
||||
{
|
||||
//parsing the footer returns the index position
|
||||
_stream.seekg(ParseFooter());
|
||||
if (_stream.peekTag() == TAG_PANGO_STATS) {
|
||||
// Read the pre-build index from the file
|
||||
index_good = ParseIndex();
|
||||
}
|
||||
}
|
||||
|
||||
// Restore previous location
|
||||
_stream.clear();
|
||||
_stream.seekg(pos);
|
||||
}
|
||||
|
||||
return index_good;
|
||||
}
|
||||
|
||||
streampos PacketStreamReader::ParseFooter() //returns position of index.
|
||||
{
|
||||
_stream.readTag(TAG_PANGO_FOOTER);
|
||||
uint64_t index=0;
|
||||
size_t bytes_read = _stream.read(reinterpret_cast<char*>(&index), sizeof(index));
|
||||
PANGO_ENSURE(bytes_read == sizeof(index));
|
||||
return index;
|
||||
}
|
||||
|
||||
bool PacketStreamReader::ParseIndex()
|
||||
{
|
||||
_stream.readTag(TAG_PANGO_STATS);
|
||||
picojson::value json;
|
||||
picojson::parse(json, _stream);
|
||||
|
||||
const bool index_good = json.contains("src_packet_index") && json.contains("src_packet_times");
|
||||
|
||||
if (index_good)
|
||||
{
|
||||
// This is a two-dimensional serialized array, [source id][sequence number] ---> packet position in stream
|
||||
const auto& json_index = json["src_packet_index"].get<picojson::array>();
|
||||
const auto& json_times = json["src_packet_times"].get<picojson::array>();
|
||||
|
||||
// We shouldn't have seen more sources than exist in the index
|
||||
PANGO_ENSURE(_sources.size() <= json_index.size());
|
||||
PANGO_ENSURE(json_index.size() == json_times.size());
|
||||
|
||||
_sources.resize(json_index.size());
|
||||
|
||||
// Populate index
|
||||
for(size_t i=0; i < _sources.size(); ++i) {
|
||||
PANGO_ENSURE(json_index[i].size() == json_times[i].size());
|
||||
_sources[i].index.resize(json_index[i].size());
|
||||
for(size_t f=0; f < json_index[i].size(); ++f) {
|
||||
_sources[i].index[f].pos = json_index[i][f].get<int64_t>();
|
||||
_sources[i].index[f].capture_time = json_times[i][f].get<int64_t>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index_good;
|
||||
}
|
||||
|
||||
bool PacketStreamReader::GoodToRead()
|
||||
{
|
||||
if(!_stream.good()) {
|
||||
#ifndef _WIN_
|
||||
if (_is_pipe)
|
||||
{
|
||||
if (_pipe_fd == -1) {
|
||||
_pipe_fd = ReadablePipeFileDescriptor(_filename);
|
||||
}
|
||||
|
||||
if (_pipe_fd != -1) {
|
||||
// Test whether the pipe has data to be read. If so, open the
|
||||
// file stream and start reading. After this point, the file
|
||||
// descriptor is owned by the reader.
|
||||
if (PipeHasDataToRead(_pipe_fd))
|
||||
{
|
||||
close(_pipe_fd);
|
||||
_pipe_fd = -1;
|
||||
Open(_filename);
|
||||
return _stream.good();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
Packet PacketStreamReader::NextFrame()
|
||||
{
|
||||
std::unique_lock<std::recursive_mutex> lock(_mutex);
|
||||
|
||||
while (GoodToRead())
|
||||
{
|
||||
const pangoTagType t = _stream.peekTag();
|
||||
|
||||
switch (t)
|
||||
{
|
||||
case TAG_PANGO_SYNC:
|
||||
SkipSync();
|
||||
break;
|
||||
case TAG_ADD_SOURCE:
|
||||
ParseNewSource();
|
||||
break;
|
||||
case TAG_SRC_JSON: //frames are sometimes preceded by metadata, but metadata must ALWAYS be followed by a frame from the same source.
|
||||
case TAG_SRC_PACKET:
|
||||
return Packet(_stream, std::move(lock), _sources);
|
||||
case TAG_PANGO_STATS:
|
||||
ParseIndex();
|
||||
break;
|
||||
case TAG_PANGO_FOOTER: //end of frames
|
||||
case TAG_END:
|
||||
throw std::runtime_error("PacketStreamReader: end of stream");
|
||||
case TAG_PANGO_HDR: //shoudln't encounter this
|
||||
ParseHeader();
|
||||
break;
|
||||
case TAG_PANGO_MAGIC: //or this
|
||||
SkipSync();
|
||||
break;
|
||||
default: //or anything else
|
||||
pango_print_warn("Unexpected packet type: \"%s\". Resyncing()\n", tagName(t).c_str());
|
||||
ReSync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No frame
|
||||
throw std::runtime_error("PacketStreamReader: no frame");
|
||||
}
|
||||
|
||||
Packet PacketStreamReader::NextFrame(PacketStreamSourceId src)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
// This will throw if nothing is left.
|
||||
auto fi = NextFrame();
|
||||
if (fi.src == src) {
|
||||
return fi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PacketStreamReader::RebuildIndex()
|
||||
{
|
||||
lock_guard<decltype(_mutex)> lg(_mutex);
|
||||
|
||||
if(_stream.seekable()) {
|
||||
pango_print_warn("Index for '%s' bad / outdated. Rebuilding.\n", _filename.c_str());
|
||||
|
||||
// Save current position
|
||||
std::streampos pos = _stream.tellg();
|
||||
|
||||
// Clear existing index
|
||||
for(PacketStreamSource& s : _sources) {
|
||||
s.index.clear();
|
||||
s.next_packet_id = 0;
|
||||
}
|
||||
|
||||
// Read through entire file, updating index
|
||||
try{
|
||||
while (1)
|
||||
{
|
||||
// This will throw if we've run out of frames
|
||||
auto fi = NextFrame();
|
||||
PacketStreamSource& s = _sources[fi.src];
|
||||
PANGO_ENSURE(s.index.size() == fi.sequence_num);
|
||||
s.index.push_back({fi.frame_streampos, fi.time});
|
||||
}
|
||||
}catch(...){
|
||||
}
|
||||
|
||||
// Reset Packet id's
|
||||
for(PacketStreamSource& s : _sources) {
|
||||
s.next_packet_id = 0;
|
||||
}
|
||||
|
||||
// Restore previous location
|
||||
_stream.clear();
|
||||
_stream.seekg(pos);
|
||||
}
|
||||
}
|
||||
|
||||
void PacketStreamReader::AppendIndex()
|
||||
{
|
||||
lock_guard<decltype(_mutex)> lg(_mutex);
|
||||
|
||||
if(_stream.seekable()) {
|
||||
// Open file again for append
|
||||
std::ofstream of(_filename, std::ios::app | std::ios::binary);
|
||||
if(of.is_open()) {
|
||||
pango_print_warn("Appending new index to '%s'.\n", _filename.c_str());
|
||||
uint64_t indexpos = (uint64_t)of.tellp();
|
||||
writeTag(of, TAG_PANGO_STATS);
|
||||
SourceStats(_sources).serialize(std::ostream_iterator<char>(of), false);
|
||||
writeTag(of, TAG_PANGO_FOOTER);
|
||||
of.write(reinterpret_cast<char*>(&indexpos), sizeof(uint64_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PacketStreamReader::FixFileIndex()
|
||||
{
|
||||
if(_stream.seekable())
|
||||
{
|
||||
RebuildIndex();
|
||||
AppendIndex();
|
||||
}
|
||||
}
|
||||
|
||||
size_t PacketStreamReader::Seek(PacketStreamSourceId src, size_t framenum)
|
||||
{
|
||||
lock_guard<decltype(_mutex)> lg(_mutex);
|
||||
|
||||
PANGO_ASSERT(_stream.seekable());
|
||||
PANGO_ASSERT(src < _sources.size());
|
||||
PacketStreamSource& source = _sources[src];
|
||||
PANGO_ASSERT(framenum < source.index.size());
|
||||
|
||||
if(source.index[framenum].pos > 0) {
|
||||
_stream.clear();
|
||||
_stream.seekg(source.index[framenum].pos);
|
||||
source.next_packet_id = framenum;
|
||||
}
|
||||
return source.next_packet_id;
|
||||
}
|
||||
|
||||
// Jumps to the first packet with time >= time
|
||||
size_t PacketStreamReader::Seek(PacketStreamSourceId src, SyncTime::TimePoint time)
|
||||
{
|
||||
PacketStreamSource& source = _sources[src];
|
||||
|
||||
PacketStreamSource::PacketInfo v = {
|
||||
0, std::chrono::duration_cast<std::chrono::microseconds>(time.time_since_epoch()).count()
|
||||
};
|
||||
|
||||
// Find time in indextime
|
||||
auto lb = std::lower_bound(
|
||||
source.index.begin(), source.index.end(), v,
|
||||
[](const PacketStreamSource::PacketInfo& a, const PacketStreamSource::PacketInfo& b){
|
||||
return a.capture_time < b.capture_time;
|
||||
}
|
||||
);
|
||||
|
||||
if(lb != source.index.end()) {
|
||||
const size_t frame_num = lb - source.index.begin();
|
||||
return Seek(src, frame_num);
|
||||
}else{
|
||||
return source.next_packet_id;
|
||||
}
|
||||
}
|
||||
|
||||
void PacketStreamReader::SkipSync()
|
||||
{
|
||||
//Assume we have just read PAN, read GO
|
||||
if (_stream.get() != 'G' && _stream.get() != 'O')
|
||||
throw std::runtime_error("Unknown packet type.");
|
||||
|
||||
while (_stream.peekTag() != TAG_SRC_PACKET && _stream.peekTag() != TAG_END)
|
||||
_stream.readTag();
|
||||
}
|
||||
|
||||
}
|
||||
156
thirdparty/Pangolin/src/log/packetstream_writer.cpp
vendored
Normal file
156
thirdparty/Pangolin/src/log/packetstream_writer.cpp
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include <pangolin/log/packetstream_writer.h>
|
||||
#include <pangolin/utils/file_utils.h>
|
||||
#include <pangolin/utils/timer.h>
|
||||
|
||||
using std::ios;
|
||||
using std::lock_guard;
|
||||
|
||||
#define SCOPED_LOCK lock_guard<decltype(_lock)> lg(_lock)
|
||||
|
||||
//#define SCOPED_LOCK
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
static inline const std::string CurrentTimeStr()
|
||||
{
|
||||
time_t time_now = time(0);
|
||||
struct tm time_struct = *localtime(&time_now);
|
||||
char buffer[80];
|
||||
strftime(buffer, sizeof(buffer), "%Y-%m-%d %X", &time_struct);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void PacketStreamWriter::WriteHeader()
|
||||
{
|
||||
SCOPED_LOCK;
|
||||
_stream.write(PANGO_MAGIC.c_str(), PANGO_MAGIC.size());
|
||||
picojson::value pango;
|
||||
pango["pangolin_version"] = PANGOLIN_VERSION_STRING;
|
||||
pango["time_us"] = Time_us(TimeNow());
|
||||
pango["date_created"] = CurrentTimeStr();
|
||||
pango["endian"] = "little_endian";
|
||||
|
||||
writeTag(_stream, TAG_PANGO_HDR);
|
||||
pango.serialize(std::ostream_iterator<char>(_stream), true);
|
||||
|
||||
for (const auto& source : _sources)
|
||||
Write(source);
|
||||
}
|
||||
|
||||
void PacketStreamWriter::Write(const PacketStreamSource& source)
|
||||
{
|
||||
SCOPED_LOCK;
|
||||
picojson::value serialize;
|
||||
serialize[pss_src_driver] = source.driver;
|
||||
serialize[pss_src_id] = source.id;
|
||||
serialize[pss_src_uri] = source.uri;
|
||||
serialize[pss_src_info] = source.info;
|
||||
serialize[pss_src_version] = source.version;
|
||||
serialize[pss_src_packet][pss_pkt_alignment_bytes] = source.data_alignment_bytes;
|
||||
serialize[pss_src_packet][pss_pkt_definitions] = source.data_definitions;
|
||||
serialize[pss_src_packet][pss_pkt_size_bytes] = source.data_size_bytes;
|
||||
|
||||
writeTag(_stream, TAG_ADD_SOURCE);
|
||||
serialize.serialize(std::ostream_iterator<char>(_stream), true);
|
||||
}
|
||||
|
||||
|
||||
PacketStreamSourceId PacketStreamWriter::AddSource(PacketStreamSource& source)
|
||||
{
|
||||
SCOPED_LOCK;
|
||||
source.id = AddSource(const_cast<const PacketStreamSource&>(source));
|
||||
return source.id;
|
||||
}
|
||||
|
||||
PacketStreamSourceId PacketStreamWriter::AddSource(const PacketStreamSource& source)
|
||||
{
|
||||
SCOPED_LOCK;
|
||||
PacketStreamSourceId r = _sources.size(); //source id is by vector position, so we must reassign.
|
||||
_sources.push_back(source);
|
||||
_sources.back().id = r;
|
||||
|
||||
if (_open) //we might be a pipe, in which case we may not be open
|
||||
Write(_sources.back());
|
||||
|
||||
return _sources.back().id;
|
||||
}
|
||||
|
||||
void PacketStreamWriter::WriteMeta(PacketStreamSourceId src, const picojson::value& data)
|
||||
{
|
||||
SCOPED_LOCK;
|
||||
writeTag(_stream, TAG_SRC_JSON);
|
||||
writeCompressedUnsignedInt(_stream, src);
|
||||
data.serialize(std::ostream_iterator<char>(_stream), false);
|
||||
}
|
||||
|
||||
void PacketStreamWriter::WriteSourcePacket(PacketStreamSourceId src, const char* source, const int64_t receive_time_us, size_t sourcelen, const picojson::value& meta)
|
||||
{
|
||||
|
||||
SCOPED_LOCK;
|
||||
_sources[src].index.push_back({_stream.tellp(), receive_time_us});
|
||||
|
||||
if (!meta.is<picojson::null>())
|
||||
WriteMeta(src, meta);
|
||||
|
||||
writeTag(_stream, TAG_SRC_PACKET);
|
||||
writeTimestamp(_stream, receive_time_us);
|
||||
writeCompressedUnsignedInt(_stream, src);
|
||||
|
||||
if (_sources[src].data_size_bytes) {
|
||||
if (sourcelen != static_cast<size_t>(_sources[src].data_size_bytes))
|
||||
throw std::runtime_error("oPacketStream::writePacket --> Tried to write a fixed-size packet with bad size.");
|
||||
} else {
|
||||
writeCompressedUnsignedInt(_stream, sourcelen);
|
||||
}
|
||||
|
||||
_stream.write(source, sourcelen);
|
||||
_bytes_written += sourcelen;
|
||||
}
|
||||
|
||||
void PacketStreamWriter::WriteSync()
|
||||
{
|
||||
SCOPED_LOCK;
|
||||
for (unsigned i = 0; i < 10; ++i)
|
||||
writeTag(_stream, TAG_PANGO_SYNC);
|
||||
}
|
||||
|
||||
void PacketStreamWriter::WriteEnd()
|
||||
{
|
||||
SCOPED_LOCK;
|
||||
if (!_indexable)
|
||||
return;
|
||||
|
||||
auto indexpos = _stream.tellp();
|
||||
writeTag(_stream, TAG_PANGO_STATS);
|
||||
SourceStats(_sources).serialize(std::ostream_iterator<char>(_stream), false);
|
||||
writeTag(_stream, TAG_PANGO_FOOTER);
|
||||
_stream.write(reinterpret_cast<char*>(&indexpos), sizeof(uint64_t));
|
||||
}
|
||||
|
||||
}
|
||||
26
thirdparty/Pangolin/src/log/playback_session.cpp
vendored
Normal file
26
thirdparty/Pangolin/src/log/playback_session.cpp
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <pangolin/log/playback_session.h>
|
||||
#include <pangolin/utils/params.h>
|
||||
|
||||
namespace pangolin {
|
||||
|
||||
std::shared_ptr<PlaybackSession> PlaybackSession::Default()
|
||||
{
|
||||
static std::shared_ptr<PlaybackSession> instance = std::make_shared<PlaybackSession>();
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::shared_ptr<PlaybackSession> PlaybackSession::ChooseFromParams(const Params& params)
|
||||
{
|
||||
bool use_ordered_playback = params.Get<bool>("OrderedPlayback", false);
|
||||
std::shared_ptr<pangolin::PlaybackSession> playback_session;
|
||||
if(use_ordered_playback)
|
||||
{
|
||||
return Default();
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::make_shared<PlaybackSession>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
287
thirdparty/Pangolin/src/plot/datalog.cpp
vendored
Normal file
287
thirdparty/Pangolin/src/plot/datalog.cpp
vendored
Normal file
@@ -0,0 +1,287 @@
|
||||
/* 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/plot/datalog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
void DataLogBlock::AddSamples(size_t num_samples, size_t dimensions, const float* data_dim_major )
|
||||
{
|
||||
if(nextBlock) {
|
||||
// If next block exists, add to it instead
|
||||
nextBlock->AddSamples(num_samples, dimensions, data_dim_major);
|
||||
}else{
|
||||
if(dimensions > dim) {
|
||||
// If dimensions is too high for this block, start a new bigger one
|
||||
nextBlock = std::unique_ptr<DataLogBlock>(new DataLogBlock(dimensions, max_samples, start_id + samples));
|
||||
nextBlock->AddSamples(num_samples,dimensions,data_dim_major);
|
||||
}else{
|
||||
// Try to copy samples to this block
|
||||
const size_t samples_to_copy = std::min(num_samples, SampleSpaceLeft());
|
||||
|
||||
if(dimensions == dim) {
|
||||
// Copy entire block all together
|
||||
std::copy(data_dim_major, data_dim_major + samples_to_copy*dim, sample_buffer.get()+samples*dim);
|
||||
samples += samples_to_copy;
|
||||
data_dim_major += samples_to_copy*dim;
|
||||
}else{
|
||||
// Copy sample at a time, filling with NaN's where needed.
|
||||
float* dst = sample_buffer.get();
|
||||
for(size_t i=0; i< samples_to_copy; ++i) {
|
||||
std::copy(data_dim_major, data_dim_major + dimensions, dst);
|
||||
for(size_t ii = dimensions; ii < dim; ++ii) {
|
||||
dst[ii] = std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
dst += dimensions;
|
||||
data_dim_major += dimensions;
|
||||
}
|
||||
samples += samples_to_copy;
|
||||
}
|
||||
|
||||
// // Update Stats
|
||||
// for(size_t s=0; s < samples_to_copy; ++s) {
|
||||
// for(size_t d = 0; d < dimensions; ++d) {
|
||||
// stats[d].Add(data_dim_major[s*dim + d]);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Copy remaining data to next block (this one is full)
|
||||
if(samples_to_copy < num_samples) {
|
||||
nextBlock = std::unique_ptr<DataLogBlock>(new DataLogBlock(dim, max_samples, start_id + Samples()));
|
||||
nextBlock->AddSamples(num_samples-samples_to_copy, dimensions, data_dim_major);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataLog::DataLog(unsigned int buffer_size)
|
||||
: block_samples_alloc(buffer_size), block0(nullptr), blockn(nullptr), record_stats(true)
|
||||
{
|
||||
}
|
||||
|
||||
DataLog::~DataLog()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void DataLog::SetLabels(const std::vector<std::string> & new_labels)
|
||||
{
|
||||
std::lock_guard<std::mutex> l(access_mutex);
|
||||
|
||||
// Create new labels if needed
|
||||
for( size_t i= labels.size(); i < new_labels.size(); ++i )
|
||||
labels.push_back( std::string() );
|
||||
|
||||
// Add data to existing plots
|
||||
for( unsigned int i=0; i<labels.size(); ++i )
|
||||
labels[i] = new_labels[i];
|
||||
}
|
||||
|
||||
const std::vector<std::string>& DataLog::Labels() const
|
||||
{
|
||||
return labels;
|
||||
}
|
||||
|
||||
void DataLog::Log(size_t dimension, const float* vals, unsigned int samples )
|
||||
{
|
||||
if(!block0) {
|
||||
// Create first block
|
||||
block0 = std::unique_ptr<DataLogBlock>(new DataLogBlock(dimension, block_samples_alloc, 0));
|
||||
blockn = block0.get();
|
||||
}
|
||||
|
||||
if(record_stats) {
|
||||
while(stats.size() < dimension) {
|
||||
stats.push_back( DimensionStats() );
|
||||
}
|
||||
for(unsigned int d=0; d<dimension; ++d) {
|
||||
DimensionStats& ds = stats[d];
|
||||
for(unsigned int s=0; s<samples; ++s) {
|
||||
ds.Add(vals[s*dimension+d]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blockn->AddSamples(samples,dimension,vals);
|
||||
|
||||
// Update pointer to most recent block.
|
||||
while(blockn->NextBlock()) {
|
||||
blockn = blockn->NextBlock();
|
||||
}
|
||||
}
|
||||
|
||||
void DataLog::Log(float v)
|
||||
{
|
||||
const float vs[] = {v};
|
||||
Log(1,vs);
|
||||
}
|
||||
|
||||
void DataLog::Log(float v1, float v2)
|
||||
{
|
||||
const float vs[] = {v1,v2};
|
||||
Log(2,vs);
|
||||
}
|
||||
|
||||
void DataLog::Log(float v1, float v2, float v3)
|
||||
{
|
||||
const float vs[] = {v1,v2,v3};
|
||||
Log(3,vs);
|
||||
}
|
||||
void DataLog::Log(float v1, float v2, float v3, float v4)
|
||||
{
|
||||
const float vs[] = {v1,v2,v3,v4};
|
||||
Log(4,vs);
|
||||
}
|
||||
void DataLog::Log(float v1, float v2, float v3, float v4, float v5)
|
||||
{
|
||||
const float vs[] = {v1,v2,v3,v4,v5};
|
||||
Log(5,vs);
|
||||
}
|
||||
void DataLog::Log(float v1, float v2, float v3, float v4, float v5, float v6)
|
||||
{
|
||||
const float vs[] = {v1,v2,v3,v4,v5,v6};
|
||||
Log(6,vs);
|
||||
}
|
||||
|
||||
void DataLog::Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7)
|
||||
{
|
||||
const float vs[] = {v1,v2,v3,v4,v5,v6,v7};
|
||||
Log(7,vs);
|
||||
}
|
||||
|
||||
void DataLog::Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8)
|
||||
{
|
||||
const float vs[] = {v1,v2,v3,v4,v5,v6,v7,v8};
|
||||
Log(8,vs);
|
||||
}
|
||||
|
||||
void DataLog::Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8, float v9)
|
||||
{
|
||||
const float vs[] = {v1,v2,v3,v4,v5,v6,v7,v8,v9};
|
||||
Log(9,vs);
|
||||
}
|
||||
|
||||
void DataLog::Log(float v1, float v2, float v3, float v4, float v5, float v6, float v7, float v8, float v9, float v10)
|
||||
{
|
||||
const float vs[] = {v1,v2,v3,v4,v5,v6,v7,v8,v9,v10};
|
||||
Log(10,vs);
|
||||
}
|
||||
|
||||
void DataLog::Log(const std::vector<float> & vals)
|
||||
{
|
||||
Log(vals.size(), &vals[0]);
|
||||
}
|
||||
|
||||
void DataLog::Clear()
|
||||
{
|
||||
std::lock_guard<std::mutex> l(access_mutex);
|
||||
|
||||
blockn = nullptr;
|
||||
block0 = nullptr;
|
||||
|
||||
stats.clear();
|
||||
}
|
||||
|
||||
void DataLog::Save(std::string filename)
|
||||
{
|
||||
std::ofstream csvStream(filename);
|
||||
|
||||
if (!Labels().empty()) {
|
||||
csvStream << Labels()[0];
|
||||
|
||||
for (size_t i = 1; i < Labels().size(); ++i) {
|
||||
csvStream << "," << Labels()[i];
|
||||
}
|
||||
|
||||
csvStream << std::endl;
|
||||
|
||||
}
|
||||
|
||||
const DataLogBlock * block = FirstBlock();
|
||||
|
||||
while (block) {
|
||||
|
||||
for (size_t i = 0; i < block->Samples(); ++i) {
|
||||
|
||||
csvStream << block->Sample(i)[0];
|
||||
|
||||
for (size_t d = 1; d < block->Dimensions(); ++d) {
|
||||
|
||||
csvStream << "," << block->Sample(i)[d];
|
||||
|
||||
}
|
||||
|
||||
csvStream << std::endl;
|
||||
|
||||
}
|
||||
|
||||
block = block->NextBlock();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const DataLogBlock* DataLog::FirstBlock() const
|
||||
{
|
||||
return block0.get();
|
||||
}
|
||||
|
||||
const DataLogBlock* DataLog::LastBlock() const
|
||||
{
|
||||
return blockn;
|
||||
}
|
||||
|
||||
const DimensionStats& DataLog::Stats(size_t dim) const
|
||||
{
|
||||
return stats[dim];
|
||||
}
|
||||
|
||||
size_t DataLog::Samples() const
|
||||
{
|
||||
if(blockn) {
|
||||
return blockn->StartId() + blockn->Samples();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const float* DataLog::Sample(int n) const
|
||||
{
|
||||
if(block0) {
|
||||
return block0->Sample(n);
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1171
thirdparty/Pangolin/src/plot/plotter.cpp
vendored
Normal file
1171
thirdparty/Pangolin/src/plot/plotter.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
239
thirdparty/Pangolin/src/python/pyinterpreter.cpp
vendored
Normal file
239
thirdparty/Pangolin/src/python/pyinterpreter.cpp
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
/* 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 <Python.h>
|
||||
|
||||
#include <pangolin/python/pypangolin_init.h>
|
||||
#include <pangolin/python/pyinterpreter.h>
|
||||
#include <pangolin/python/pyuniqueobj.h>
|
||||
#include <pangolin/python/pypangoio.h>
|
||||
#include <pangolin/utils/file_utils.h>
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
void PyInterpreter::AttachPrefix(void* data, const std::string& name, VarValueGeneric& /*var*/, bool /*brand_new*/ )
|
||||
{
|
||||
PyInterpreter* self = (PyInterpreter*)data;
|
||||
|
||||
const size_t dot = name.find_first_of('.');
|
||||
if(dot != std::string::npos) {
|
||||
const std::string base_prefix = name.substr(0,dot);
|
||||
if( self->base_prefixes.find(base_prefix) == self->base_prefixes.end() ) {
|
||||
self->base_prefixes.insert(base_prefix);
|
||||
std::string cmd =
|
||||
base_prefix + std::string(" = pypangolin.Var('") +
|
||||
base_prefix + std::string("')\n");
|
||||
PyRun_SimpleString(cmd.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyInterpreter::PyInterpreter()
|
||||
: pycompleter(0), pycomplete(0)
|
||||
{
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyImport_AppendInittab("pypangolin", InitPyPangolinModule);
|
||||
Py_Initialize();
|
||||
#else
|
||||
Py_Initialize();
|
||||
InitPyPangolinModule();
|
||||
#endif
|
||||
|
||||
// Hook stdout, stderr to this interpreter
|
||||
PyObject* mod_sys = PyImport_ImportModule("sys");
|
||||
if (mod_sys) {
|
||||
PyModule_AddObject(mod_sys, "stdout", (PyObject*)new PyPangoIO(
|
||||
&PyPangoIO::Py_type, line_queue, ConsoleLineTypeStdout
|
||||
));
|
||||
PyModule_AddObject(mod_sys, "stderr", (PyObject*)new PyPangoIO(
|
||||
&PyPangoIO::Py_type, line_queue, ConsoleLineTypeStderr
|
||||
));
|
||||
} else {
|
||||
pango_print_error("Couldn't import module sys.\n");
|
||||
}
|
||||
|
||||
// Attempt to setup readline completion
|
||||
PyRun_SimpleString(
|
||||
"import pypangolin\n"
|
||||
"try:\n"
|
||||
" import readline\n"
|
||||
"except ImportError:\n"
|
||||
" import pyreadline as readline\n"
|
||||
"\n"
|
||||
"import rlcompleter\n"
|
||||
"pypangolin.completer = rlcompleter.Completer()\n"
|
||||
);
|
||||
CheckPrintClearError();
|
||||
|
||||
// Get reference to rlcompleter.Completer() for tab-completion
|
||||
PyObject* mod_pangolin = PyImport_ImportModule("pypangolin");
|
||||
if(mod_pangolin) {
|
||||
pycompleter = PyObject_GetAttrString(mod_pangolin,"completer");
|
||||
if(pycompleter) {
|
||||
pycomplete = PyObject_GetAttrString(pycompleter,"complete");
|
||||
}
|
||||
} else {
|
||||
pango_print_error("PyInterpreter: Unable to load module pangolin.\n");
|
||||
}
|
||||
|
||||
// Hook namespace prefixes into Python
|
||||
RegisterNewVarCallback(&PyInterpreter::AttachPrefix, (void*)this, "");
|
||||
ProcessHistoricCallbacks(&PyInterpreter::AttachPrefix, (void*)this, "");
|
||||
|
||||
CheckPrintClearError();
|
||||
}
|
||||
|
||||
PyInterpreter::~PyInterpreter()
|
||||
{
|
||||
Py_Finalize();
|
||||
}
|
||||
|
||||
std::string PyInterpreter::ToString(PyObject* py)
|
||||
{
|
||||
PyUniqueObj pystr = PyObject_Repr(py);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return std::string(PyUnicode_AsUTF8(pystr));
|
||||
#else
|
||||
return std::string(PyString_AsString(pystr));
|
||||
#endif
|
||||
}
|
||||
|
||||
void PyInterpreter::CheckPrintClearError()
|
||||
{
|
||||
if(PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
||||
PyUniqueObj PyInterpreter::EvalExec(const std::string& cmd)
|
||||
{
|
||||
PyObject* globals = PyModule_GetDict(PyImport_AddModule("__main__"));
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject* builtin = PyImport_AddModule("builtins");
|
||||
#else
|
||||
PyObject* builtin = PyImport_AddModule("__builtin__");
|
||||
#endif
|
||||
|
||||
if(globals && builtin) {
|
||||
PyUniqueObj compile = PyObject_GetAttrString(builtin, "compile");
|
||||
PyUniqueObj eval = PyObject_GetAttrString(builtin, "eval");
|
||||
|
||||
if(compile && eval)
|
||||
{
|
||||
PyErr_Clear();
|
||||
PyUniqueObj compile_eval_args = Py_BuildValue("(sss)", cmd.c_str(), "<string>", "eval" );
|
||||
if(compile_eval_args)
|
||||
{
|
||||
PyUniqueObj code = PyObject_Call(compile, compile_eval_args, 0);
|
||||
if(code) {
|
||||
PyUniqueObj eval_args = Py_BuildValue("(OOO)", *code, globals, globals );
|
||||
if(eval_args) {
|
||||
PyUniqueObj ret = PyObject_Call(eval, eval_args, 0);
|
||||
CheckPrintClearError();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
PyUniqueObj compile_exec_args = Py_BuildValue("(sss)", cmd.c_str(), "<string>", "exec" );
|
||||
if(compile_exec_args)
|
||||
{
|
||||
PyUniqueObj code = PyObject_Call(compile, compile_exec_args, 0);
|
||||
if(code) {
|
||||
PyUniqueObj eval_args = Py_BuildValue("(OOO)", *code, globals, globals );
|
||||
if(eval_args) {
|
||||
PyUniqueObj ret = PyObject_Call(eval, eval_args, 0);
|
||||
CheckPrintClearError();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckPrintClearError();
|
||||
return PyUniqueObj();
|
||||
}
|
||||
|
||||
std::vector<std::string> PyInterpreter::Complete(const std::string& cmd, int max_options)
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
PyErr_Clear();
|
||||
|
||||
if(pycomplete) {
|
||||
for(int i=0; i < max_options; ++i) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyUniqueObj args = PyTuple_Pack( 2, PyUnicode_FromString(cmd.c_str()), PyLong_FromSize_t(i) );
|
||||
PyUniqueObj result = PyObject_CallObject(pycomplete, args);
|
||||
if (result && PyUnicode_Check(result)) {
|
||||
std::string res_str(PyUnicode_AsUTF8(result));
|
||||
#else
|
||||
PyUniqueObj args = PyTuple_Pack(2, PyString_FromString(cmd.c_str()), PyInt_FromSize_t(i));
|
||||
PyUniqueObj result = PyObject_CallObject(pycomplete, args);
|
||||
if (result && PyString_Check(result)) {
|
||||
std::string res_str(PyString_AsString(result));
|
||||
#endif
|
||||
if( res_str.find("__")==std::string::npos ||
|
||||
cmd.find("__")!=std::string::npos ||
|
||||
(cmd.size() > 0 && cmd[cmd.size()-1] == '_')
|
||||
) {
|
||||
ret.push_back( res_str );
|
||||
}
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PyInterpreter::PushCommand(const std::string& cmd)
|
||||
{
|
||||
PyUniqueObj obj = EvalExec(cmd);
|
||||
if(obj && obj != Py_None) {
|
||||
const std::string output = ToString(obj);
|
||||
line_queue.push(
|
||||
ConsoleLine(output, ConsoleLineTypeOutput)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool PyInterpreter::PullLine(ConsoleLine& line)
|
||||
{
|
||||
if(line_queue.size()) {
|
||||
line = line_queue.front();
|
||||
line_queue.pop();
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
48
thirdparty/Pangolin/src/python/pypangolin/attach.cpp
vendored
Normal file
48
thirdparty/Pangolin/src/python/pypangolin/attach.cpp
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "attach.hpp"
|
||||
#include <pangolin/gl/glinclude.h>
|
||||
#include <pangolin/display/attach.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
void bind_attach(pybind11::module &m){
|
||||
pybind11::enum_<pangolin::Unit>(m, "Unit")
|
||||
.value("Fraction", pangolin::Unit::Fraction)
|
||||
.value("Pixel", pangolin::Unit::Pixel)
|
||||
.value("ReversePixel", pangolin::Unit::ReversePixel)
|
||||
.export_values();
|
||||
|
||||
pybind11::class_<pangolin::Attach>(m, "Attach")
|
||||
.def(pybind11::init<>())
|
||||
.def(pybind11::init<pangolin::Unit, GLfloat>())
|
||||
.def(pybind11::init<GLfloat>())
|
||||
.def_static("Pix", &pangolin::Attach::Pix)
|
||||
.def_static("ReversePix", &pangolin::Attach::ReversePix)
|
||||
.def_static("Frac", &pangolin::Attach::Frac);
|
||||
}
|
||||
}
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/attach.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/attach.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_attach(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
48
thirdparty/Pangolin/src/python/pypangolin/colour.cpp
vendored
Normal file
48
thirdparty/Pangolin/src/python/pypangolin/colour.cpp
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "colour.hpp"
|
||||
#include <pangolin/gl/colour.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_colour(pybind11::module& m){
|
||||
pybind11::class_<pangolin::Colour> (m, "Colour")
|
||||
.def(pybind11::init<>())
|
||||
.def(pybind11::init<const float, const float, const float, const float>(), pybind11::arg("red"), pybind11::arg("green"), pybind11::arg("blue"), pybind11::arg("alpha")=1.0f)
|
||||
// .def(pybind11::init<float[4]>())
|
||||
.def("Get", &pangolin::Colour::Get)
|
||||
.def_static("White", &pangolin::Colour::White)
|
||||
.def_static("Black", &pangolin::Colour::Black)
|
||||
.def_static("Red", &pangolin::Colour::Red)
|
||||
.def_static("Green", &pangolin::Colour::Green)
|
||||
.def_static("Blue", &pangolin::Colour::Blue)
|
||||
.def_static("Hsv", &pangolin::Colour::Hsv)
|
||||
.def("WithAlpha", &pangolin::Colour::WithAlpha);
|
||||
}
|
||||
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/colour.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/colour.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_colour(pybind11::module& m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
86
thirdparty/Pangolin/src/python/pypangolin/datalog.cpp
vendored
Normal file
86
thirdparty/Pangolin/src/python/pypangolin/datalog.cpp
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "datalog.hpp"
|
||||
|
||||
#include <pybind11/stl.h>
|
||||
#include <pangolin/plot/datalog.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_datalog(pybind11::module& m){
|
||||
pybind11::class_<pangolin::DimensionStats >(m, "DimensionStats")
|
||||
.def(pybind11::init<>())
|
||||
.def("Reset", &pangolin::DimensionStats::Reset)
|
||||
.def("Add", &pangolin::DimensionStats::Add)
|
||||
.def_readwrite("isMonotonic", &pangolin::DimensionStats::isMonotonic)
|
||||
.def_readwrite("sum", &pangolin::DimensionStats::sum)
|
||||
.def_readwrite("sum_sq", &pangolin::DimensionStats::sum_sq)
|
||||
.def_readwrite("min", &pangolin::DimensionStats::min)
|
||||
.def_readwrite("max", &pangolin::DimensionStats::max);
|
||||
|
||||
pybind11::class_<pangolin::DataLogBlock>(m, "DataLogBlock")
|
||||
.def(pybind11::init<size_t,size_t,size_t>())
|
||||
.def("Samples", &pangolin::DataLogBlock::Samples)
|
||||
.def("MaxSamples", &pangolin::DataLogBlock::MaxSamples)
|
||||
.def("SampleSpaceLeft", &pangolin::DataLogBlock::SampleSpaceLeft)
|
||||
.def("IsFull", &pangolin::DataLogBlock::IsFull)
|
||||
.def("AddSamples", &pangolin::DataLogBlock::AddSamples)
|
||||
.def("ClearLinked", &pangolin::DataLogBlock::ClearLinked)
|
||||
.def("NextBlock", &pangolin::DataLogBlock::NextBlock)
|
||||
.def("StartId", &pangolin::DataLogBlock::StartId)
|
||||
.def("DimData", &pangolin::DataLogBlock::DimData)
|
||||
.def("Dimensions", &pangolin::DataLogBlock::Dimensions)
|
||||
.def("Sample", &pangolin::DataLogBlock::Sample)
|
||||
.def("StartId", &pangolin::DataLogBlock::StartId);
|
||||
|
||||
pybind11::class_<pangolin::DataLog>(m, "DataLog")
|
||||
.def(pybind11::init<unsigned int>(), pybind11::arg("block_samples_alloc")=10000)
|
||||
.def("SetLabels", &pangolin::DataLog::SetLabels)
|
||||
.def("Labels", &pangolin::DataLog::Labels)
|
||||
.def("Log", (void (pangolin::DataLog::*)(size_t, const float*, unsigned int))&pangolin::DataLog::Log, pybind11::arg("dimension"), pybind11::arg("vals"), pybind11::arg("samples")=1)
|
||||
.def("Log", (void (pangolin::DataLog::*)(float))&pangolin::DataLog::Log)
|
||||
.def("Log", (void (pangolin::DataLog::*)(float, float))&pangolin::DataLog::Log)
|
||||
.def("Log", (void (pangolin::DataLog::*)(float, float, float))&pangolin::DataLog::Log)
|
||||
.def("Log", (void (pangolin::DataLog::*)(float, float, float, float))&pangolin::DataLog::Log)
|
||||
.def("Log", (void (pangolin::DataLog::*)(float, float, float, float, float))&pangolin::DataLog::Log)
|
||||
.def("Log", (void (pangolin::DataLog::*)(float, float, float, float, float, float))&pangolin::DataLog::Log)
|
||||
.def("Log", (void (pangolin::DataLog::*)(float, float, float, float, float, float, float))&pangolin::DataLog::Log)
|
||||
.def("Log", (void (pangolin::DataLog::*)(float, float, float, float, float, float, float, float))&pangolin::DataLog::Log)
|
||||
.def("Log", (void (pangolin::DataLog::*)(float, float, float, float, float, float, float, float, float))&pangolin::DataLog::Log)
|
||||
.def("Log", (void (pangolin::DataLog::*)(float, float, float, float, float, float, float, float, float, float))&pangolin::DataLog::Log)
|
||||
.def("Log", (void (pangolin::DataLog::*)(const std::vector<float>&))&pangolin::DataLog::Log)
|
||||
.def("Clear", &pangolin::DataLog::Clear)
|
||||
.def("Save", &pangolin::DataLog::Save)
|
||||
.def("FirstBlock", &pangolin::DataLog::FirstBlock)
|
||||
.def("LastBlock", &pangolin::DataLog::LastBlock)
|
||||
.def("Samples", &pangolin::DataLog::Samples)
|
||||
.def("Sample", &pangolin::DataLog::Sample)
|
||||
.def("Stats", &pangolin::DataLog::Stats);
|
||||
}
|
||||
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/datalog.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/datalog.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_datalog(pybind11::module& m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
81
thirdparty/Pangolin/src/python/pypangolin/display.cpp
vendored
Normal file
81
thirdparty/Pangolin/src/python/pypangolin/display.cpp
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "display.hpp"
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/view.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_display(pybind11::module &m) {
|
||||
m.def("CreateWindowAndBind",
|
||||
&pangolin::CreateWindowAndBind,
|
||||
pybind11::return_value_policy::reference,
|
||||
pybind11::arg("window_title"),
|
||||
pybind11::arg("w") = 640,
|
||||
pybind11::arg("h") = 480,
|
||||
pybind11::arg("params") = pangolin::Params());
|
||||
|
||||
m.def("DestroyWindow",
|
||||
&pangolin::DestroyWindow,
|
||||
pybind11::arg("window_title"));
|
||||
|
||||
m.def("CreateDisplay",
|
||||
&pangolin::CreateDisplay,
|
||||
pybind11::return_value_policy::reference);
|
||||
|
||||
m.def("ShouldQuit",
|
||||
&pangolin::ShouldQuit);
|
||||
|
||||
m.def("FinishFrame",
|
||||
&pangolin::FinishFrame);
|
||||
|
||||
m.def("ToggleFullscreen",
|
||||
&pangolin::ToggleFullscreen);
|
||||
|
||||
m.def("ToggleConsole",
|
||||
&pangolin::ToggleConsole);
|
||||
|
||||
m.def("RegisterKeyPressCallback",
|
||||
[](int v, const std::function<void()>& f){
|
||||
pangolin::RegisterKeyPressCallback(v, f);
|
||||
}
|
||||
);
|
||||
|
||||
m.def("DisplayBase",
|
||||
&pangolin::DisplayBase,
|
||||
pybind11::return_value_policy::reference);
|
||||
|
||||
m.def("Display",
|
||||
&pangolin::Display,
|
||||
pybind11::return_value_policy::reference,
|
||||
pybind11::arg("name"));
|
||||
|
||||
}
|
||||
|
||||
} // Py_pangolin
|
||||
36
thirdparty/Pangolin/src/python/pypangolin/display.hpp
vendored
Normal file
36
thirdparty/Pangolin/src/python/pypangolin/display.hpp
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_display(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
102
thirdparty/Pangolin/src/python/pypangolin/gl.cpp
vendored
Normal file
102
thirdparty/Pangolin/src/python/pypangolin/gl.cpp
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "gl.hpp"
|
||||
#include <pangolin/gl/gl.h>
|
||||
#include <pybind11/numpy.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
bool is_packed(const pybind11::buffer_info & info) {
|
||||
int next_expected_stride = info.itemsize;
|
||||
for (int i = info.ndim-1; i >= 0; --i) {
|
||||
if (!(info.strides[i] == next_expected_stride)) {
|
||||
return false;
|
||||
}
|
||||
next_expected_stride *= info.shape[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void bind_gl(pybind11::module &m) {
|
||||
|
||||
pybind11::class_<pangolin::GlTexture>(m, "GlTexture")
|
||||
.def(pybind11::init<>())
|
||||
.def(pybind11::init<GLint, GLint, GLint, bool, int, GLenum, GLenum>(), pybind11::arg("width"), pybind11::arg("height"), pybind11::arg("internal_format") = GL_RGBA8, pybind11::arg("sampling_linear") = true, pybind11::arg("border") = 0, pybind11::arg("glformat") = GL_RGBA, pybind11::arg("gltype") = GL_UNSIGNED_BYTE)
|
||||
.def("Upload", [](pangolin::GlTexture & texture, pybind11::buffer b, GLenum data_format, GLenum type){
|
||||
pybind11::buffer_info info = b.request();
|
||||
texture.Upload(info.ptr, data_format, type);
|
||||
})
|
||||
.def("Download", [](pangolin::GlTexture & texture, pybind11::buffer b, GLenum data_layout, GLenum data_type) {
|
||||
pybind11::buffer_info info = b.request();
|
||||
if (!is_packed(info)) {
|
||||
throw std::runtime_error("cannot Download into non-packed buffer");
|
||||
}
|
||||
texture.Download(info.ptr, data_layout, data_type);
|
||||
})
|
||||
.def("Save", &pangolin::GlTexture::Save, pybind11::arg("filename"), pybind11::arg("top_line_first")=true)
|
||||
.def("RenderToViewport", (void (pangolin::GlTexture::*)() const)&pangolin::GlTexture::RenderToViewport)
|
||||
.def("RenderToViewportFlipY", &pangolin::GlTexture::RenderToViewportFlipY)
|
||||
.def("SetNearestNeighbour", &pangolin::GlTexture::SetNearestNeighbour);
|
||||
|
||||
pybind11::class_<pangolin::GlRenderBuffer>(m, "GlRenderBuffer")
|
||||
.def(pybind11::init<GLint, GLint, GLint>(), pybind11::arg("width")=0, pybind11::arg("height")=0, pybind11::arg("internal_format") = GL_DEPTH_COMPONENT24)
|
||||
.def("Reinitialise", &pangolin::GlRenderBuffer::Reinitialise);
|
||||
|
||||
pybind11::class_<pangolin::GlFramebuffer>(m, "GlFramebuffer")
|
||||
.def(pybind11::init<pangolin::GlTexture &, pangolin::GlRenderBuffer &>())
|
||||
.def("Bind", &pangolin::GlFramebuffer::Bind)
|
||||
.def("Unbind", &pangolin::GlFramebuffer::Unbind);
|
||||
|
||||
pybind11::enum_<pangolin::GlBufferType>(m, "GlBufferType")
|
||||
.value("GlUndefined", pangolin::GlBufferType::GlUndefined)
|
||||
.value("GlArrayBuffer", pangolin::GlBufferType::GlArrayBuffer)
|
||||
.value("GlElementArrayBuffer", pangolin::GlBufferType::GlElementArrayBuffer)
|
||||
#ifndef HAVE_GLES
|
||||
.value("GlPixelPackBuffer", pangolin::GlBufferType::GlPixelPackBuffer)
|
||||
.value("GlPixelUnpackBuffer", pangolin::GlBufferType::GlPixelUnpackBuffer)
|
||||
.value("GlShaderStorageBuffer", pangolin::GlBufferType::GlShaderStorageBuffer)
|
||||
#endif
|
||||
.export_values();
|
||||
|
||||
pybind11::class_<pangolin::GlBufferData>(m, "GlBufferData")
|
||||
.def(pybind11::init<>())
|
||||
.def("Reinitialise", [](pangolin::GlBufferData & gl_buffer, pangolin::GlBufferType buffer_type, GLuint size_bytes, GLenum gl_use) {
|
||||
gl_buffer.Reinitialise(buffer_type, size_bytes, gl_use);
|
||||
})
|
||||
.def("Bind", &pangolin::GlBufferData::Bind)
|
||||
.def("Unbind", &pangolin::GlBufferData::Unbind)
|
||||
.def("Upload", [](pangolin::GlBufferData & gl_buffer, pybind11::buffer b, GLsizeiptr size_bytes, GLintptr offset) {
|
||||
pybind11::buffer_info info = b.request();
|
||||
gl_buffer.Upload(info.ptr, size_bytes, offset);
|
||||
}, pybind11::arg("data"), pybind11::arg("size_bytes"), pybind11::arg("offset")=0)
|
||||
.def_readwrite("size_bytes", &pangolin::GlBufferData::size_bytes);
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace py_pangolin
|
||||
36
thirdparty/Pangolin/src/python/pypangolin/gl.hpp
vendored
Normal file
36
thirdparty/Pangolin/src/python/pypangolin/gl.hpp
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_gl(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
71
thirdparty/Pangolin/src/python/pypangolin/gl_draw.cpp
vendored
Normal file
71
thirdparty/Pangolin/src/python/pypangolin/gl_draw.cpp
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "gl_draw.hpp"
|
||||
#include <pangolin/gl/gldraw.h>
|
||||
#include <pybind11/eigen.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_gl_draw(pybind11::module &m){
|
||||
|
||||
m.def("glDrawAxis",
|
||||
(void (*)(float))&pangolin::glDrawAxis);
|
||||
|
||||
m.def("glDrawColouredCube",
|
||||
&pangolin::glDrawColouredCube,
|
||||
pybind11::arg("axis_min") = -0.5f,
|
||||
pybind11::arg("axis_max") = +0.5f);
|
||||
|
||||
m.def("glDraw_x0",
|
||||
&pangolin::glDraw_x0);
|
||||
m.def("glDraw_y0",
|
||||
&pangolin::glDraw_y0);
|
||||
m.def("glDraw_z0",
|
||||
&pangolin::glDraw_z0);
|
||||
|
||||
m.def("glDrawFrustum", (void (*)(GLfloat, GLfloat, GLfloat, GLfloat, int, int, GLfloat)) &pangolin::glDrawFrustum);
|
||||
m.def("glDrawFrustum", (void (*)(const Eigen::Matrix3f &, int, int, GLfloat)) &pangolin::glDrawFrustum<float>);
|
||||
m.def("glDrawFrustum", (void (*)(const Eigen::Matrix3d &, int, int, GLfloat)) &pangolin::glDrawFrustum<double>);
|
||||
m.def("glDrawFrustum", (void (*)(const Eigen::Matrix3f &, int, int, const Eigen::Matrix4f &, float)) &pangolin::glDrawFrustum<float>);
|
||||
m.def("glDrawFrustum", (void (*)(const Eigen::Matrix3d &, int, int, const Eigen::Matrix4d &, double)) &pangolin::glDrawFrustum<double>);
|
||||
|
||||
m.def("glDrawAxis", (void (*)(float)) &pangolin::glDrawAxis);
|
||||
m.def("glDrawAxis", (void (*)(const Eigen::Matrix4f &, float)) &pangolin::glDrawAxis<Eigen::Matrix4f, float>);
|
||||
m.def("glDrawAxis", (void (*)(const Eigen::Matrix4d &, float)) &pangolin::glDrawAxis<Eigen::Matrix4d, float>);
|
||||
|
||||
m.def("glSetFrameOfReference", (void (*)(const Eigen::Matrix4f &)) &pangolin::glSetFrameOfReference);
|
||||
m.def("glSetFrameOfReference", (void (*)(const Eigen::Matrix4d &)) &pangolin::glSetFrameOfReference);
|
||||
|
||||
m.def("glUnsetFrameOfReference", &pangolin::glUnsetFrameOfReference);
|
||||
|
||||
m.def("glDrawAlignedBox", (void (*)(const Eigen::AlignedBox2f &, GLenum)) &pangolin::glDrawAlignedBox<float>, pybind11::arg("box"), pybind11::arg("mode") = GL_TRIANGLE_FAN);
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/gl_draw.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/gl_draw.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_gl_draw(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
72
thirdparty/Pangolin/src/python/pypangolin/glsl.cpp
vendored
Normal file
72
thirdparty/Pangolin/src/python/pypangolin/glsl.cpp
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "glsl.hpp"
|
||||
#include <pangolin/gl/glsl.h>
|
||||
#include <pybind11/eigen.h>
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_glsl(pybind11::module &m) {
|
||||
|
||||
pybind11::enum_<pangolin::GlSlShaderType>(m, "GlSlShaderType")
|
||||
.value("GlSlAnnotatedShader", pangolin::GlSlShaderType::GlSlAnnotatedShader)
|
||||
.value("GlSlFragmentShader", pangolin::GlSlShaderType::GlSlFragmentShader)
|
||||
.value("GlSlVertexShader", pangolin::GlSlShaderType::GlSlVertexShader)
|
||||
.value("GlSlGeometryShader", pangolin::GlSlShaderType::GlSlGeometryShader)
|
||||
.value("GlSlComputeShader", pangolin::GlSlShaderType::GlSlComputeShader)
|
||||
.export_values();
|
||||
|
||||
pybind11::class_<pangolin::GlSlProgram>(m, "GlSlProgram")
|
||||
.def(pybind11::init<>())
|
||||
.def("AddShader", &pangolin::GlSlProgram::AddShader, pybind11::arg("shader_type"), pybind11::arg("filename"), pybind11::arg("program_defines")=std::map<std::string,std::string>(), pybind11::arg("search_path")=std::vector<std::string>())
|
||||
.def("AddShaderFromFile", &pangolin::GlSlProgram::AddShaderFromFile)
|
||||
.def("Link", &pangolin::GlSlProgram::Link)
|
||||
.def("GetAttributeHandle", &pangolin::GlSlProgram::GetAttributeHandle)
|
||||
.def("GetUniformHandle", &pangolin::GlSlProgram::GetUniformHandle)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, int))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, int, int))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, int, int, int))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, int, int, int, int))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, float))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, float, float))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, float, float, float))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, float, float, float, float))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, const pangolin::OpenGlMatrix &))&pangolin::GlSlProgram::SetUniform)
|
||||
#ifdef HAVE_EIGEN
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, const Eigen::Matrix3f &))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, const Eigen::Matrix4f &))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, const Eigen::Matrix3d &))&pangolin::GlSlProgram::SetUniform)
|
||||
.def("SetUniform", (void (pangolin::GlSlProgram::*)(const std::string &, const Eigen::Matrix4d &))&pangolin::GlSlProgram::SetUniform)
|
||||
#endif
|
||||
.def("Bind", &pangolin::GlSlProgram::Bind)
|
||||
.def("Unbind", &pangolin::GlSlProgram::Unbind);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
36
thirdparty/Pangolin/src/python/pypangolin/glsl.hpp
vendored
Normal file
36
thirdparty/Pangolin/src/python/pypangolin/glsl.hpp
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_glsl(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
58
thirdparty/Pangolin/src/python/pypangolin/handler.cpp
vendored
Normal file
58
thirdparty/Pangolin/src/python/pypangolin/handler.cpp
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "handler.hpp"
|
||||
#include <pangolin/handler/handler.h>
|
||||
#include <pangolin/display/opengl_render_state.h>
|
||||
#include <pangolin/plot/plotter.h>
|
||||
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_handler(pybind11::module &m) {
|
||||
|
||||
pybind11::class_<pangolin::Handler, PyHandler> handler(m, "Handler");
|
||||
handler
|
||||
.def(pybind11::init<>())
|
||||
.def("Keyboard", &pangolin::Handler::Keyboard)
|
||||
.def("Mouse", &pangolin::Handler::Mouse)
|
||||
.def("MouseMotion", &pangolin::Handler::MouseMotion)
|
||||
.def("PassiveMouseMotion", &pangolin::Handler::PassiveMouseMotion)
|
||||
.def("Special", &pangolin::Handler::Special);
|
||||
|
||||
pybind11::class_<pangolin::Handler3D>(m, "Handler3D", handler)
|
||||
.def(pybind11::init<pangolin::OpenGlRenderState&, pangolin::AxisDirection, float, float>(), pybind11::arg("state"), pybind11::arg("enforce_up") = pangolin::AxisNone, pybind11::arg("trans_scale")=0.01f, pybind11::arg("zoom_factor")=PANGO_DFLT_HANDLER3D_ZF)
|
||||
.def("ValidWinDepth", &pangolin::Handler3D::ValidWinDepth)
|
||||
.def("PixelUnproject", &pangolin::Handler3D::PixelUnproject)
|
||||
.def("GetPosNormal", &pangolin::Handler3D::GetPosNormal)
|
||||
.def("Keyboard", &pangolin::Handler3D::Keyboard)
|
||||
.def("Mouse", &pangolin::Handler3D::Mouse)
|
||||
.def("MouseMotion", &pangolin::Handler3D::MouseMotion)
|
||||
.def("Special", &pangolin::Handler3D::Special);
|
||||
|
||||
}
|
||||
} // py_pangolin
|
||||
62
thirdparty/Pangolin/src/python/pypangolin/handler.hpp
vendored
Normal file
62
thirdparty/Pangolin/src/python/pypangolin/handler.hpp
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
#include <pangolin/handler/handler.h>
|
||||
#include <pangolin/display/view.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
class PyHandler : public pangolin::Handler {
|
||||
public:
|
||||
using pangolin::Handler::Handler;
|
||||
|
||||
void Keyboard(pangolin::View& v, unsigned char key, int x, int y, bool pressed) override {
|
||||
PYBIND11_OVERLOAD(void, pangolin::Handler, Keyboard, v, key, x, y, pressed);
|
||||
}
|
||||
void Mouse(pangolin::View& v, pangolin::MouseButton button, int x, int y, bool pressed, int button_state) override {
|
||||
PYBIND11_OVERLOAD(void, pangolin::Handler, Mouse, v, button, x, y, pressed, button_state);
|
||||
}
|
||||
|
||||
void MouseMotion(pangolin::View& v, int x, int y, int button_state) override {
|
||||
PYBIND11_OVERLOAD(void, pangolin::Handler, MouseMotion, v, x, y, button_state);
|
||||
}
|
||||
void PassiveMouseMotion(pangolin::View& v, int x, int y, int button_state) override {
|
||||
PYBIND11_OVERLOAD(void, pangolin::Handler, PassiveMouseMotion, v, x, y, button_state);
|
||||
}
|
||||
|
||||
void Special(pangolin::View& v, pangolin::InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state) override{
|
||||
PYBIND11_OVERLOAD(void, pangolin::Handler, Special, v, inType, x, y, p1, p2, p3, p4, button_state);
|
||||
}
|
||||
};
|
||||
|
||||
void bind_handler(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
34
thirdparty/Pangolin/src/python/pypangolin/image.cpp
vendored
Normal file
34
thirdparty/Pangolin/src/python/pypangolin/image.cpp
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "image.hpp"
|
||||
#include <pangolin/image/image.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
67
thirdparty/Pangolin/src/python/pypangolin/image.hpp
vendored
Normal file
67
thirdparty/Pangolin/src/python/pypangolin/image.hpp
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
#include <pangolin/image/image.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
template<typename T>
|
||||
void bind_image(pybind11::module& m, const std::string& pyname){
|
||||
pybind11::class_<pangolin::Image<T> >(m, pyname.c_str())
|
||||
.def(pybind11::init<>())
|
||||
.def(pybind11::init<T*, size_t, size_t, size_t>())
|
||||
.def("SizeBytes", &pangolin::Image<T>::SizeBytes)
|
||||
.def("Area", &pangolin::Image<T>::Area)
|
||||
.def("IsValid", &pangolin::Image<T>::IsValid)
|
||||
.def("IsContiguous", &pangolin::Image<T>::IsContiguous)
|
||||
.def("begin", (unsigned char* (pangolin::Image<T>::*)())&pangolin::Image<T>::begin)
|
||||
.def("end", (unsigned char* (pangolin::Image<T>::*)())&pangolin::Image<T>::end)
|
||||
.def("begin", (const unsigned char* (pangolin::Image<T>::*)() const )&pangolin::Image<T>::begin)
|
||||
.def("end", (const unsigned char* (pangolin::Image<T>::*)() const )&pangolin::Image<T>::end)
|
||||
.def("size", &pangolin::Image<T>::size)
|
||||
.def("Fill", &pangolin::Image<T>::Fill)
|
||||
.def("Replace", &pangolin::Image<T>::Replace)
|
||||
.def("Memset", &pangolin::Image<T>::Memset)
|
||||
.def("CopyFrom", &pangolin::Image<T>::CopyFrom)
|
||||
.def("MinMax", &pangolin::Image<T>::MinMax)
|
||||
// .def("Sum", [](pangolin::Image<T>& v){ return v.Sum();})
|
||||
// .def("Mean", [](pangolin::Image<T>& v){ return v.Mean();})
|
||||
.def("RowPtr", (T* (pangolin::Image<T>::*)(size_t))&pangolin::Image<T>::RowPtr)
|
||||
.def("RowPtr", (const T* (pangolin::Image<T>::*)(size_t) const )&pangolin::Image<T>::RowPtr)
|
||||
.def("InImage", &pangolin::Image<T>::InImage)
|
||||
.def("InBounds", (bool (pangolin::Image<T>::*)(int, int) const)&pangolin::Image<T>::InBounds)
|
||||
.def("InBounds", (bool (pangolin::Image<T>::*)(float, float, float) const)&pangolin::Image<T>::InBounds)
|
||||
// .def("SubImage", (pangolin::Image<T> (pangolin::Image<T>::*)(size_t, size_t, size_t, size_t))&pangolin::Image<T>::SubImage)
|
||||
// .def("Row", &pangolin::Image<T>::Row)
|
||||
// .def("Col", &pangolin::Image<T>::Col)
|
||||
.def("InImage", &pangolin::Image<T>::InImage);
|
||||
}
|
||||
|
||||
} // py_pangolin
|
||||
50
thirdparty/Pangolin/src/python/pypangolin/image_view.cpp
vendored
Normal file
50
thirdparty/Pangolin/src/python/pypangolin/image_view.cpp
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) 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 "image_view.hpp"
|
||||
#include <pangolin/display/image_view.h>
|
||||
#include <pybind11/numpy.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_image_view(pybind11::module &m) {
|
||||
using namespace pangolin;
|
||||
pybind11::class_<ImageView, View>(m, "ImageView")
|
||||
.def(pybind11::init<>())
|
||||
.def("SetImage", [](ImageView& view, pybind11::array_t<float>& img) -> ImageView&{
|
||||
if(img.ndim() == 2) {
|
||||
Image<uint8_t> wrapper((uint8_t*)img.mutable_data(0,0), img.shape(1), img.shape(0), img.shape(1) * sizeof(float));
|
||||
return view.SetImage(wrapper, GlPixFormat(PixelFormatFromString("GRAY32F")) );
|
||||
}else if(img.ndim() == 3 && img.shape()[2] == 3) {
|
||||
Image<uint8_t> wrapper((uint8_t*)img.mutable_data(0,0), img.shape(1), img.shape(0), 3 * img.shape(1) * sizeof(float));
|
||||
return view.SetImage(wrapper, GlPixFormat(PixelFormatFromString("RGB96F")) );
|
||||
}else{
|
||||
throw std::runtime_error("Unsupported format for now.");
|
||||
}
|
||||
});
|
||||
}
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/image_view.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/image_view.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) 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 <pybind11/pybind11.h>
|
||||
|
||||
|
||||
namespace py_pangolin{
|
||||
|
||||
void bind_image_view(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
116
thirdparty/Pangolin/src/python/pypangolin/opengl_render_state.cpp
vendored
Normal file
116
thirdparty/Pangolin/src/python/pypangolin/opengl_render_state.cpp
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "opengl_render_state.hpp"
|
||||
#include <pangolin/display/opengl_render_state.h>
|
||||
#include <pybind11/eigen.h>
|
||||
#include <pybind11/operators.h>
|
||||
#include <pybind11/numpy.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_opengl_render_state(pybind11::module &m){
|
||||
pybind11::enum_<pangolin::AxisDirection>(m, "AxisDirection")
|
||||
.value("AxisNone", pangolin::AxisDirection::AxisNone)
|
||||
.value("AxisNegX", pangolin::AxisDirection::AxisNegX)
|
||||
.value("AxisNegY", pangolin::AxisDirection::AxisNegY)
|
||||
.value("AxisNegZ", pangolin::AxisDirection::AxisNegZ)
|
||||
.value("AxisX", pangolin::AxisDirection::AxisX)
|
||||
.value("AxisY", pangolin::AxisDirection::AxisY)
|
||||
.value("AxisZ", pangolin::AxisDirection::AxisZ)
|
||||
.export_values();
|
||||
|
||||
pybind11::enum_<pangolin::OpenGlStack>(m, "OpenGlStack")
|
||||
.value("GlModelViewStack", pangolin::OpenGlStack::GlModelViewStack)
|
||||
.value("GlProjectionStack", pangolin::OpenGlStack::GlProjectionStack)
|
||||
.value("GlTextureStack", pangolin::OpenGlStack::GlTextureStack)
|
||||
.export_values();
|
||||
|
||||
pybind11::class_<pangolin::OpenGlMatrix>(m, "OpenGlMatrix")
|
||||
.def("Translate", &pangolin::OpenGlMatrix::Translate)
|
||||
.def("Scale", &pangolin::OpenGlMatrix::Scale)
|
||||
.def("RotateX", &pangolin::OpenGlMatrix::RotateX)
|
||||
.def("RotateY", &pangolin::OpenGlMatrix::RotateY)
|
||||
.def("RotateZ", &pangolin::OpenGlMatrix::RotateZ)
|
||||
.def(pybind11::init<>())
|
||||
.def(pybind11::init<const Eigen::Matrix<float, 4, 4> >())
|
||||
.def(pybind11::init<const Eigen::Matrix<double, 4, 4> >())
|
||||
.def("Load", &pangolin::OpenGlMatrix::Load)
|
||||
.def("Multiply", &pangolin::OpenGlMatrix::Multiply)
|
||||
.def("SetIdentity", &pangolin::OpenGlMatrix::SetIdentity)
|
||||
.def("Transpose", &pangolin::OpenGlMatrix::Transpose)
|
||||
.def("Inverse", &pangolin::OpenGlMatrix::Inverse)
|
||||
.def("Matrix", [](pangolin::OpenGlMatrix& mat){
|
||||
using T = pangolin::GLprecision;
|
||||
return pybind11::array_t<T>( {4, 4 }, {1*sizeof(T), 4*sizeof(T)}, mat.m );
|
||||
})
|
||||
.def(pybind11::self * pybind11::self);
|
||||
|
||||
pybind11::class_<pangolin::OpenGlMatrixSpec, pangolin::OpenGlMatrix>(m, "OpenGlMatrixSpec")
|
||||
.def(pybind11::init<>());
|
||||
|
||||
m.def("ProjectionMatrixRUB_BottomLeft", &pangolin::ProjectionMatrixRUB_BottomLeft);
|
||||
m.def("ProjectionMatrixRUB_TopLeft", &pangolin::ProjectionMatrixRUB_TopLeft);
|
||||
m.def("ProjectionMatrixRDF_BottomLeft", &pangolin::ProjectionMatrixRDF_BottomLeft);
|
||||
m.def("ProjectionMatrixRDF_TopLeft", &pangolin::ProjectionMatrixRDF_TopLeft);
|
||||
m.def("ProjectionMatrix", &pangolin::ProjectionMatrix);
|
||||
m.def("ProjectionMatrixOrthographic", &pangolin::ProjectionMatrixOrthographic);
|
||||
m.def("ModelViewLookAtRUB", &pangolin::ModelViewLookAtRUB);
|
||||
m.def("ModelViewLookAtRDF", &pangolin::ModelViewLookAtRDF);
|
||||
m.def("ModelViewLookAt", (pangolin::OpenGlMatrix (*)(pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision, pangolin::AxisDirection))&pangolin::ModelViewLookAt);
|
||||
m.def("ModelViewLookAt", (pangolin::OpenGlMatrix (*)(pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision, pangolin::GLprecision))&pangolin::ModelViewLookAt);
|
||||
m.def("IdentityMatrix", (pangolin::OpenGlMatrix (*)())&pangolin::IdentityMatrix);
|
||||
m.def("IdentityMatrix", (pangolin::OpenGlMatrixSpec (*)(pangolin::OpenGlStack))&pangolin::IdentityMatrix);
|
||||
m.def("negIdentityMatrix", &pangolin::negIdentityMatrix);
|
||||
|
||||
pybind11::class_<pangolin::OpenGlRenderState>(m, "OpenGlRenderState")
|
||||
.def(pybind11::init<const pangolin::OpenGlMatrix&>())
|
||||
.def(pybind11::init<const pangolin::OpenGlMatrix&, const pangolin::OpenGlMatrix&>())
|
||||
.def(pybind11::init<>())
|
||||
.def("ApplyIdentity", &pangolin::OpenGlRenderState::ApplyIdentity)
|
||||
.def("Apply", &pangolin::OpenGlRenderState::Apply)
|
||||
.def("SetProjectionMatrix", &pangolin::OpenGlRenderState::SetProjectionMatrix)
|
||||
.def("SetModelViewMatrix", &pangolin::OpenGlRenderState::SetModelViewMatrix)
|
||||
.def("GetProjectionMatrix", (pangolin::OpenGlMatrix& (pangolin::OpenGlRenderState::*)())&pangolin::OpenGlRenderState::GetProjectionMatrix)
|
||||
.def("GetProjectionMatrix", (pangolin::OpenGlMatrix (pangolin::OpenGlRenderState::*)() const)&pangolin::OpenGlRenderState::GetProjectionMatrix)
|
||||
.def("GetModelViewMatrix", (pangolin::OpenGlMatrix& (pangolin::OpenGlRenderState::*)())&pangolin::OpenGlRenderState::GetModelViewMatrix)
|
||||
.def("GetModelViewMatrix", (pangolin::OpenGlMatrix (pangolin::OpenGlRenderState::*)() const)&pangolin::OpenGlRenderState::GetModelViewMatrix)
|
||||
.def("GetProjectionModelViewMatrix", &pangolin::OpenGlRenderState::GetProjectionModelViewMatrix)
|
||||
.def("GetProjectiveTextureMatrix", &pangolin::OpenGlRenderState::GetProjectiveTextureMatrix)
|
||||
.def("EnableProjectiveTexturing", &pangolin::OpenGlRenderState::EnableProjectiveTexturing)
|
||||
.def("DisableProjectiveTexturing", &pangolin::OpenGlRenderState::DisableProjectiveTexturing)
|
||||
.def("Follow", &pangolin::OpenGlRenderState::Follow, pybind11::arg("T_wc"), pybind11::arg("follow")=true)
|
||||
.def("Unfollow", &pangolin::OpenGlRenderState::Unfollow)
|
||||
.def("GetProjectionMatrix", (pangolin::OpenGlMatrix& (pangolin::OpenGlRenderState::*)(unsigned int))&pangolin::OpenGlRenderState::GetProjectionMatrix)
|
||||
.def("GetProjectionMatrix", (pangolin::OpenGlMatrix (pangolin::OpenGlRenderState::*)(unsigned int) const)&pangolin::OpenGlRenderState::GetProjectionMatrix)
|
||||
.def("GetViewOffset", (pangolin::OpenGlMatrix& (pangolin::OpenGlRenderState::*)(unsigned int))&pangolin::OpenGlRenderState::GetViewOffset)
|
||||
.def("GetViewOffset", (pangolin::OpenGlMatrix (pangolin::OpenGlRenderState::*)(unsigned int) const)&pangolin::OpenGlRenderState::GetViewOffset)
|
||||
.def("GetModelViewMatrix", (pangolin::OpenGlMatrix (pangolin::OpenGlRenderState::*)(int) const)&pangolin::OpenGlRenderState::GetModelViewMatrix)
|
||||
.def("ApplyNView", &pangolin::OpenGlRenderState::ApplyNView);
|
||||
}
|
||||
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/opengl_render_state.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/opengl_render_state.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_opengl_render_state(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
43
thirdparty/Pangolin/src/python/pypangolin/params.cpp
vendored
Normal file
43
thirdparty/Pangolin/src/python/pypangolin/params.cpp
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "params.hpp"
|
||||
#include <pangolin/utils/params.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_params(pybind11::module &m) {
|
||||
pybind11::class_<pangolin::Params>(m, "Params")
|
||||
.def(pybind11::init<>())
|
||||
.def("Contains", &pangolin::Params::Contains)
|
||||
.def("Set", &pangolin::Params::Set<int>)
|
||||
.def("Get", &pangolin::Params::Get<int>)
|
||||
.def("Set", &pangolin::Params::Set<std::string>)
|
||||
.def("Get", &pangolin::Params::Get<std::string>);
|
||||
}
|
||||
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/params.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/params.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_params(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
43
thirdparty/Pangolin/src/python/pypangolin/pixel_format.cpp
vendored
Normal file
43
thirdparty/Pangolin/src/python/pypangolin/pixel_format.cpp
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "pixel_format.hpp"
|
||||
#include <pangolin/image/pixel_format.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_pixel_format(pybind11::module& m){
|
||||
pybind11::class_<pangolin::PixelFormat>(m, "PixelFormat")
|
||||
.def_readwrite("format", &pangolin::PixelFormat::format)
|
||||
.def_readwrite("channels", &pangolin::PixelFormat::channels)
|
||||
// .def_readwrite("channel_bits", &pangolin::PixelFormat::channel_bits) //channel_bits[4]
|
||||
.def_readwrite("bpp", &pangolin::PixelFormat::bpp)
|
||||
.def_readwrite("planar", &pangolin::PixelFormat::planar);
|
||||
|
||||
m.def("PixelFormatFromString", &pangolin::PixelFormatFromString);
|
||||
}
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/pixel_format.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/pixel_format.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_pixel_format(pybind11::module& m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
131
thirdparty/Pangolin/src/python/pypangolin/plotter.cpp
vendored
Normal file
131
thirdparty/Pangolin/src/python/pypangolin/plotter.cpp
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov, 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 "view.hpp"
|
||||
#include "plotter.hpp"
|
||||
#include "handler.hpp"
|
||||
#include <pangolin/plot/plotter.h>
|
||||
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
//extern pybind11::class_<pangolin::Handler, PyHandler> handler;
|
||||
|
||||
void bind_plotter(pybind11::module& m){
|
||||
// pybind11::class_<pangolin::Handler, PyHandler> handler1(m, "Handler1");
|
||||
// handler1
|
||||
// .def(pybind11::init<>())
|
||||
// .def("Keyboard", &pangolin::Handler::Keyboard)
|
||||
// .def("Mouse", &pangolin::Handler::Mouse)
|
||||
// .def("MouseMotion", &pangolin::Handler::MouseMotion)
|
||||
// .def("PassiveMouseMotion", &pangolin::Handler::PassiveMouseMotion)
|
||||
// .def("Special", &pangolin::Handler::Special);
|
||||
|
||||
pybind11::enum_<pangolin::DrawingMode>(m, "DrawingMode")
|
||||
.value("DrawingModePoints", pangolin::DrawingMode::DrawingModePoints)
|
||||
.value("DrawingModeDashed", pangolin::DrawingMode::DrawingModeDashed)
|
||||
.value("DrawingModeLine", pangolin::DrawingMode::DrawingModeLine)
|
||||
.value("DrawingModeNone", pangolin::DrawingMode::DrawingModeNone)
|
||||
.export_values();
|
||||
|
||||
pybind11::class_<pangolin::Marker> marker(m, "Marker");
|
||||
|
||||
pybind11::enum_<pangolin::Marker::Direction>(marker, "Direction")
|
||||
.value("Horizontal", pangolin::Marker::Direction::Horizontal)
|
||||
.value("Vertical", pangolin::Marker::Direction::Vertical)
|
||||
.export_values();
|
||||
|
||||
pybind11::enum_<pangolin::Marker::Equality>(marker, "Equality")
|
||||
.value("LessThan", pangolin::Marker::Equality::LessThan)
|
||||
.value("Equal", pangolin::Marker::Equality::Equal)
|
||||
.value("GreaterThan", pangolin::Marker::Equality::GreaterThan)
|
||||
.export_values();
|
||||
|
||||
marker.def(pybind11::init<pangolin::Marker::Direction, float, pangolin::Marker::Equality, pangolin::Colour>(), pybind11::arg("d"), pybind11::arg("value"), pybind11::arg("leg") = pangolin::Marker::Equality::Equal, pybind11::arg("c")=pangolin::Colour())
|
||||
.def(pybind11::init<const pangolin::XYRangef&, const pangolin::Colour&>(), pybind11::arg("range"), pybind11::arg("c")=pangolin::Colour())
|
||||
.def_readwrite("range", &pangolin::Marker::range)
|
||||
.def_readwrite("colour", &pangolin::Marker::colour);
|
||||
|
||||
pybind11::class_<pangolin::Plotter,pangolin::View>(m, "Plotter")
|
||||
.def(pybind11::init<pangolin::DataLog*, float, float, float, float, float, float, pangolin::Plotter*, pangolin::Plotter*>(),
|
||||
pybind11::arg("default_log"),
|
||||
pybind11::arg("left")=0,
|
||||
pybind11::arg("right")=600,
|
||||
pybind11::arg("bottom")=-1,
|
||||
pybind11::arg("top")=1,
|
||||
pybind11::arg("tickx")=30,
|
||||
pybind11::arg("ticky")=0.5,
|
||||
pybind11::arg("linked_plotter_x")=NULL,
|
||||
pybind11::arg("linked_plotter_y")=NULL)
|
||||
.def(pybind11::init([](pangolin::DataLog* log, float left, float right, float bottom, float top, float tickx, float ticky){return new pangolin::Plotter(log, left, right, bottom, top,tickx, ticky);}),
|
||||
pybind11::arg("default_log"),
|
||||
pybind11::arg("left")=0,
|
||||
pybind11::arg("right")=600,
|
||||
pybind11::arg("bottom")=-1,
|
||||
pybind11::arg("top")=1,
|
||||
pybind11::arg("// TODO: ickx")=30,
|
||||
pybind11::arg("ticky")=0.5)
|
||||
|
||||
.def("Render", &pangolin::Plotter::Render)
|
||||
.def("GetSelection", &pangolin::Plotter::GetSelection)
|
||||
.def("GetDefaultView", &pangolin::Plotter::GetDefaultView)
|
||||
.def("SetDefaultView", &pangolin::Plotter::SetDefaultView)
|
||||
.def("GetView", &pangolin::Plotter::GetView)
|
||||
.def("SetView", &pangolin::Plotter::SetView)
|
||||
.def("SetViewSmooth", &pangolin::Plotter::SetViewSmooth)
|
||||
.def("ScrollView", &pangolin::Plotter::ScrollView)
|
||||
.def("ScrollViewSmooth", &pangolin::Plotter::ScrollViewSmooth)
|
||||
.def("ScaleView", &pangolin::Plotter::ScaleView)
|
||||
.def("ScaleViewSmooth", &pangolin::Plotter::ScaleViewSmooth)
|
||||
.def("SetTicks", &pangolin::Plotter::SetTicks)
|
||||
.def("Track", &pangolin::Plotter::Track, pybind11::arg("x")="$i", pybind11::arg("y")="")
|
||||
.def("ToggleTracking", &pangolin::Plotter::ToggleTracking)
|
||||
.def("Trigger", &pangolin::Plotter::Trigger, pybind11::arg("x")="$0", pybind11::arg("edge")=-1, pybind11::arg("value")=0.0f)
|
||||
.def("ToggleTrigger", &pangolin::Plotter::ToggleTrigger)
|
||||
.def("SetBackgroundColour", &pangolin::Plotter::SetBackgroundColour)
|
||||
.def("SetAxisColour", &pangolin::Plotter::SetAxisColour)
|
||||
.def("SetTickColour", &pangolin::Plotter::SetTickColour)
|
||||
.def("Keyboard", &pangolin::Plotter::Keyboard)
|
||||
.def("Mouse", &pangolin::Plotter::Mouse)
|
||||
.def("MouseMotion", &pangolin::Plotter::MouseMotion)
|
||||
.def("PassiveMouseMotion", &pangolin::Plotter::PassiveMouseMotion)
|
||||
.def("Special", &pangolin::Plotter::Special)
|
||||
.def("ClearSeries", &pangolin::Plotter::ClearSeries)
|
||||
.def("AddSeries", &pangolin::Plotter::AddSeries)
|
||||
.def("PlotTitleFromExpr", &pangolin::Plotter::PlotTitleFromExpr)
|
||||
.def("ClearMarkers", &pangolin::Plotter::ClearMarkers)
|
||||
.def("AddMarker", (pangolin::Marker& (pangolin::Plotter::*)(pangolin::Marker::Direction, float, pangolin::Marker::Equality, pangolin::Colour))&pangolin::Plotter::AddMarker, pybind11::arg("d"), pybind11::arg("value"), pybind11::arg("leg") = pangolin::Marker::Equality::Equal, pybind11::arg("c")=pangolin::Colour())
|
||||
.def("AddMarker", (pangolin::Marker& (pangolin::Plotter::*)(const pangolin::Marker&))&pangolin::Plotter::AddMarker)
|
||||
// .def("ClearImplicitPlots", &pangolin::Plotter::ClearImplicitPlots);
|
||||
// .def("AddImplicitPlot", &pangolin::Plotter::AddImplicitPlot);
|
||||
.def("SetBounds", (pangolin::View& (pangolin::Plotter::*)(pangolin::Attach, pangolin::Attach, pangolin::Attach, pangolin::Attach))&pangolin::Plotter::SetBounds)
|
||||
.def("SetBounds", (pangolin::View& (pangolin::Plotter::*)(pangolin::Attach, pangolin::Attach, pangolin::Attach, pangolin::Attach, bool))&pangolin::Plotter::SetBounds)
|
||||
.def("SetBounds", (pangolin::View& (pangolin::Plotter::*)(pangolin::Attach, pangolin::Attach, pangolin::Attach, pangolin::Attach, double))&pangolin::Plotter::SetBounds);
|
||||
|
||||
}
|
||||
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/plotter.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/plotter.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_plotter(pybind11::module& m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
83
thirdparty/Pangolin/src/python/pypangolin/pypangolin.h
vendored
Normal file
83
thirdparty/Pangolin/src/python/pypangolin/pypangolin.h
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) 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 <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/embed.h>
|
||||
|
||||
#include "attach.hpp"
|
||||
#include "colour.hpp"
|
||||
#include "datalog.hpp"
|
||||
#include "display.hpp"
|
||||
#include "gl.hpp"
|
||||
#include "glsl.hpp"
|
||||
#include "gl_draw.hpp"
|
||||
#include "handler.hpp"
|
||||
#include "image.hpp"
|
||||
#include "opengl_render_state.hpp"
|
||||
#include "params.hpp"
|
||||
#include "pixel_format.hpp"
|
||||
#include "plotter.hpp"
|
||||
#include "var.hpp"
|
||||
#include "video.hpp"
|
||||
#include "view.hpp"
|
||||
#include "viewport.hpp"
|
||||
#include "widget.hpp"
|
||||
#include "window.hpp"
|
||||
#include "image_view.hpp"
|
||||
|
||||
namespace pypangolin {
|
||||
|
||||
inline void PopulateModule(pybind11::module& m)
|
||||
{
|
||||
m.doc() = "pypangolin python wrapper for Pangolin rapid prototyping graphics and video library.";
|
||||
|
||||
py_pangolin::bind_var(m);
|
||||
py_pangolin::bind_params(m);
|
||||
py_pangolin::bind_viewport(m);
|
||||
py_pangolin::bind_view(m);
|
||||
py_pangolin::bind_window(m);
|
||||
py_pangolin::bind_display(m);
|
||||
py_pangolin::bind_opengl_render_state(m);
|
||||
py_pangolin::bind_attach(m);
|
||||
py_pangolin::bind_colour(m);
|
||||
py_pangolin::bind_datalog(m);
|
||||
py_pangolin::bind_plotter(m);
|
||||
py_pangolin::bind_handler(m);
|
||||
py_pangolin::bind_gl(m);
|
||||
py_pangolin::bind_glsl(m);
|
||||
py_pangolin::bind_gl_draw(m);
|
||||
py_pangolin::bind_widget(m);
|
||||
py_pangolin::bind_pixel_format(m);
|
||||
py_pangolin::bind_image<unsigned char>(m, "Image");
|
||||
py_pangolin::bind_video(m);
|
||||
py_pangolin::bind_image_view(m);
|
||||
}
|
||||
|
||||
}
|
||||
157
thirdparty/Pangolin/src/python/pypangolin/var.cpp
vendored
Normal file
157
thirdparty/Pangolin/src/python/pypangolin/var.cpp
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "var.hpp"
|
||||
#include <functional>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
var_t::var_t(const std::string& ns_){
|
||||
if(ns_==""){
|
||||
throw std::invalid_argument("not support empty argument");
|
||||
}
|
||||
ns=ns_+".";
|
||||
}
|
||||
|
||||
var_t::~var_t() noexcept{}
|
||||
|
||||
var_t::var_t(const var_t &/*other*/){}
|
||||
|
||||
var_t::var_t(var_t &&/*other*/) noexcept{}
|
||||
|
||||
var_t& var_t::operator=(const var_t &/*other*/){
|
||||
return *this;
|
||||
}
|
||||
|
||||
var_t& var_t::operator=(var_t &&/*other*/) noexcept{
|
||||
return *this;
|
||||
}
|
||||
|
||||
pybind11::object var_t::get_attr(const std::string &name){
|
||||
pangolin::VarState::VarStoreContainer::iterator i = pangolin::VarState::I().vars.find(ns+name);
|
||||
if (i != pangolin::VarState::I().vars.end()) {
|
||||
pangolin::VarValueGeneric* var = i->second;
|
||||
if (!strcmp(var->TypeId(), typeid(bool).name())) {
|
||||
const bool val = pangolin::Var<bool>(*var).Get();
|
||||
return pybind11::bool_(val);
|
||||
} else if (!strcmp(var->TypeId(), typeid(short).name()) ||
|
||||
!strcmp(var->TypeId(), typeid(int).name()) ||
|
||||
!strcmp(var->TypeId(), typeid(long).name())) {
|
||||
const long val = pangolin::Var<long>(*var).Get();
|
||||
return pybind11::int_(val);
|
||||
} else if (!strcmp(var->TypeId(), typeid(double).name()) ||
|
||||
!strcmp(var->TypeId(), typeid(float).name())) {
|
||||
const double val = pangolin::Var<double>(*var).Get();
|
||||
return pybind11::float_(val);
|
||||
} else {
|
||||
const std::string val = var->str->Get();
|
||||
return pybind11::str(val);
|
||||
}
|
||||
}
|
||||
return pybind11::none();
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void var_t::set_attr_(const std::string& name, T val, const PyVarMeta & meta){
|
||||
pangolin::VarState::VarStoreContainer::iterator i = pangolin::VarState::I().vars.find(ns+name);
|
||||
if (i != pangolin::VarState::I().vars.end()) {
|
||||
pangolin::VarValueGeneric* var = i->second;
|
||||
pangolin::Var<T> v(*var);
|
||||
v = val;
|
||||
} else {
|
||||
int flags = pangolin::META_FLAG_NONE;
|
||||
if (meta.toggle) flags |= pangolin::META_FLAG_TOGGLE;
|
||||
if (meta.read_only) flags |= pangolin::META_FLAG_READONLY;
|
||||
pangolin::Var<T> pango_var(ns+name, val, flags);
|
||||
pango_var.Meta().gui_changed = true;
|
||||
pango_var.Meta().range[0] = meta.low;
|
||||
pango_var.Meta().range[1] = meta.high;
|
||||
pango_var.Meta().logscale = meta.logscale;
|
||||
pangolin::FlagVarChanged();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string>& var_t::get_members(){
|
||||
const int nss = ns.size();
|
||||
members.clear();
|
||||
for (const std::string& s : pangolin::VarState::I().var_adds) {
|
||||
if (!s.compare(0, nss, ns)) {
|
||||
size_t dot = s.find_first_of('.', nss);
|
||||
members.push_back((dot != std::string::npos) ? s.substr(nss, dot - nss) : s.substr(nss));
|
||||
}
|
||||
}
|
||||
return members;
|
||||
}
|
||||
|
||||
template <typename ... Ts>
|
||||
struct VarBinder {
|
||||
|
||||
static inline void Bind(pybind11::class_<var_t> & varClass) {}
|
||||
|
||||
};
|
||||
|
||||
template <typename Head, typename ... Tail>
|
||||
struct VarBinder<Head, Tail...> {
|
||||
|
||||
static inline void Bind(pybind11::class_<var_t> & varClass) {
|
||||
|
||||
varClass.def("__setattr__", [](var_t& v, const std::string& name, Head val) {
|
||||
v.set_attr_<Head>(name, val);
|
||||
}).def("__setattr__", [](var_t& v, const std::string& name, const std::tuple<Head, PyVarMeta> & valMeta) {
|
||||
v.set_attr_<Head>(name, std::get<0>(valMeta), std::get<1>(valMeta));
|
||||
});
|
||||
|
||||
VarBinder<Tail...>::Bind(varClass);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void bind_var(pybind11::module& m){
|
||||
|
||||
pybind11::class_<PyVarMeta>(m, "VarMeta")
|
||||
.def(pybind11::init<double, double, bool, bool, bool>(),
|
||||
pybind11::arg("low") = 0.0,
|
||||
pybind11::arg("high") = 1.0,
|
||||
pybind11::arg("logscale") = false,
|
||||
pybind11::arg("toggle") = false,
|
||||
pybind11::arg("read_only") = false);
|
||||
|
||||
pybind11::class_<py_pangolin::var_t> varClass(m, "Var");
|
||||
varClass.def(pybind11::init<const std::string &>())
|
||||
.def("__members__", &py_pangolin::var_t::get_members)
|
||||
.def("__getattr__", &py_pangolin::var_t::get_attr);
|
||||
|
||||
VarBinder<bool, int, double, std::string, std::function<void(void)> >::Bind(varClass);
|
||||
|
||||
}
|
||||
|
||||
} // py_pangolin
|
||||
67
thirdparty/Pangolin/src/python/pypangolin/var.hpp
vendored
Normal file
67
thirdparty/Pangolin/src/python/pypangolin/var.hpp
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
#include <pangolin/var/var.h>
|
||||
#include <Python.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
struct PyVarMeta {
|
||||
double low;
|
||||
double high;
|
||||
bool logscale;
|
||||
bool toggle;
|
||||
bool read_only;
|
||||
};
|
||||
|
||||
void bind_var(pybind11::module& m);
|
||||
|
||||
class var_t
|
||||
{
|
||||
public:
|
||||
var_t(const std::string& ns);
|
||||
virtual ~var_t() noexcept;
|
||||
pybind11::object get_attr(const std::string &name);
|
||||
|
||||
template <typename T>
|
||||
void set_attr_(const std::string& name, T val, const PyVarMeta & meta = {});
|
||||
|
||||
std::vector<std::string>& get_members();
|
||||
protected:
|
||||
var_t(const var_t &other);
|
||||
var_t(var_t &&other) noexcept;
|
||||
var_t& operator=(const var_t &other);
|
||||
var_t& operator=(var_t &&other) noexcept;
|
||||
private:
|
||||
std::vector<std::string> members;
|
||||
std::string ns;
|
||||
};
|
||||
|
||||
} // py_pangolin
|
||||
645
thirdparty/Pangolin/src/python/pypangolin/video.cpp
vendored
Normal file
645
thirdparty/Pangolin/src/python/pypangolin/video.cpp
vendored
Normal file
@@ -0,0 +1,645 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "video.hpp"
|
||||
#include <pangolin/video/video_interface.h>
|
||||
#include <pangolin/video/video_input.h>
|
||||
|
||||
#include <pybind11/numpy.h>
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
class PyVideoInterface: public pangolin::VideoInterface{
|
||||
public:
|
||||
using pangolin::VideoInterface::VideoInterface;
|
||||
|
||||
size_t SizeBytes() const override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
size_t,
|
||||
pangolin::VideoInterface,
|
||||
SizeBytes);
|
||||
}
|
||||
|
||||
const std::vector<pangolin::StreamInfo>& Streams() const override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
const std::vector<pangolin::StreamInfo>&,
|
||||
pangolin::VideoInterface,
|
||||
Streams);
|
||||
}
|
||||
|
||||
void Start() override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
void,
|
||||
pangolin::VideoInterface,
|
||||
Start);
|
||||
}
|
||||
|
||||
void Stop() override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
void,
|
||||
pangolin::VideoInterface,
|
||||
Stop);
|
||||
}
|
||||
|
||||
bool GrabNext(unsigned char* image, bool wait = true) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
bool,
|
||||
pangolin::VideoInterface,
|
||||
GrabNext,
|
||||
image,
|
||||
wait);
|
||||
}
|
||||
|
||||
bool GrabNewest(unsigned char* image, bool wait = true) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
bool,
|
||||
pangolin::VideoInterface,
|
||||
GrabNewest,
|
||||
image,
|
||||
wait);
|
||||
}
|
||||
};
|
||||
|
||||
class PyGenicamVideoInterface: public pangolin::GenicamVideoInterface{
|
||||
public:
|
||||
using pangolin::GenicamVideoInterface::GenicamVideoInterface;
|
||||
|
||||
bool GetParameter(const std::string& name, std::string& result) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
bool,
|
||||
pangolin::GenicamVideoInterface,
|
||||
GetParameter,
|
||||
name,
|
||||
result);
|
||||
}
|
||||
|
||||
bool SetParameter(const std::string& name, const std::string& value) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
bool,
|
||||
pangolin::GenicamVideoInterface,
|
||||
SetParameter,
|
||||
name,
|
||||
value);
|
||||
}
|
||||
size_t CameraCount() const override
|
||||
{
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
size_t,
|
||||
pangolin::GenicamVideoInterface,
|
||||
CameraCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
class PyBufferAwareVideoInterface: public pangolin::BufferAwareVideoInterface{
|
||||
public:
|
||||
using pangolin::BufferAwareVideoInterface::BufferAwareVideoInterface;
|
||||
|
||||
uint32_t AvailableFrames() const override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
uint32_t,
|
||||
pangolin::BufferAwareVideoInterface,
|
||||
AvailableFrames);
|
||||
}
|
||||
|
||||
bool DropNFrames(uint32_t n) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
bool,
|
||||
pangolin::BufferAwareVideoInterface,
|
||||
DropNFrames,
|
||||
n);
|
||||
}
|
||||
};
|
||||
|
||||
class PyVideoPropertiesInterface: public pangolin::VideoPropertiesInterface{
|
||||
public:
|
||||
using pangolin::VideoPropertiesInterface::VideoPropertiesInterface;
|
||||
|
||||
const picojson::value& DeviceProperties() const override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
const picojson::value&,
|
||||
pangolin::VideoPropertiesInterface,
|
||||
DeviceProperties);
|
||||
}
|
||||
|
||||
const picojson::value& FrameProperties() const override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
const picojson::value&,
|
||||
pangolin::VideoPropertiesInterface,
|
||||
FrameProperties);
|
||||
}
|
||||
};
|
||||
|
||||
class PyVideoFilterInterface: public pangolin::VideoFilterInterface{
|
||||
public:
|
||||
using pangolin::VideoFilterInterface::VideoFilterInterface;
|
||||
|
||||
// template <typename T>
|
||||
// std::vector<T*> FindMatchingStreams() override {
|
||||
// PYBIND11_OVERLOAD(
|
||||
// std::vector<T*>,
|
||||
// pangolin::VideoFilterInterface,
|
||||
// FindMatchingStreams);
|
||||
// }
|
||||
|
||||
std::vector<pangolin::VideoInterface*>& InputStreams() override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
std::vector<pangolin::VideoInterface*>&,
|
||||
pangolin::VideoFilterInterface,
|
||||
InputStreams);
|
||||
}
|
||||
};
|
||||
|
||||
class PyVideoUvcInterface: public pangolin::VideoUvcInterface{
|
||||
public:
|
||||
using pangolin::VideoUvcInterface::VideoUvcInterface;
|
||||
|
||||
int IoCtrl(uint8_t unit, uint8_t ctrl, unsigned char* data, int len, pangolin::UvcRequestCode req_code) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
int,
|
||||
pangolin::VideoUvcInterface,
|
||||
IoCtrl,
|
||||
unit,
|
||||
ctrl,
|
||||
data,
|
||||
len,
|
||||
req_code);
|
||||
}
|
||||
|
||||
bool GetExposure(int& exp_us) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
bool,
|
||||
pangolin::VideoUvcInterface,
|
||||
GetExposure,
|
||||
exp_us);
|
||||
}
|
||||
|
||||
bool SetExposure(int exp_us) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
bool,
|
||||
pangolin::VideoUvcInterface,
|
||||
SetExposure,
|
||||
exp_us);
|
||||
}
|
||||
|
||||
bool GetGain(float& gain) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
bool,
|
||||
pangolin::VideoUvcInterface,
|
||||
GetGain,
|
||||
gain);
|
||||
}
|
||||
|
||||
bool SetGain(float gain) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
bool,
|
||||
pangolin::VideoUvcInterface,
|
||||
SetGain,
|
||||
gain);
|
||||
}
|
||||
};
|
||||
|
||||
class PyVideoPlaybackInterface: public pangolin::VideoPlaybackInterface{
|
||||
public:
|
||||
using pangolin::VideoPlaybackInterface::VideoPlaybackInterface;
|
||||
|
||||
size_t GetCurrentFrameId() const override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
size_t,
|
||||
pangolin::VideoPlaybackInterface,
|
||||
GetCurrentFrameId);
|
||||
}
|
||||
|
||||
size_t GetTotalFrames() const override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
size_t,
|
||||
pangolin::VideoPlaybackInterface,
|
||||
GetTotalFrames);
|
||||
}
|
||||
|
||||
size_t Seek(size_t frameid) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
size_t,
|
||||
pangolin::VideoPlaybackInterface,
|
||||
Seek,
|
||||
frameid);
|
||||
}
|
||||
};
|
||||
|
||||
class PyVideoOutputInterface: public pangolin::VideoOutputInterface{
|
||||
public:
|
||||
using pangolin::VideoOutputInterface::VideoOutputInterface;
|
||||
|
||||
const std::vector<pangolin::StreamInfo>& Streams() const override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
const std::vector<pangolin::StreamInfo>&,
|
||||
pangolin::VideoOutputInterface,
|
||||
Streams);
|
||||
}
|
||||
|
||||
void SetStreams(const std::vector<pangolin::StreamInfo>& streams, const std::string& uri, const picojson::value& properties) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
void,
|
||||
pangolin::VideoOutputInterface,
|
||||
SetStreams,
|
||||
streams,
|
||||
uri,
|
||||
properties);
|
||||
}
|
||||
|
||||
int WriteStreams(const unsigned char* data, const picojson::value& frame_properties) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
int,
|
||||
pangolin::VideoOutputInterface,
|
||||
WriteStreams,
|
||||
data,
|
||||
frame_properties);
|
||||
}
|
||||
|
||||
bool IsPipe() const override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
bool,
|
||||
pangolin::VideoOutputInterface,
|
||||
IsPipe);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
pybind11::list VideoInputGrab(pangolin::VideoInput& vi, bool wait, bool newest){
|
||||
unsigned char *buffer = new unsigned char[vi.SizeBytes()];
|
||||
|
||||
std::vector<pangolin::Image<unsigned char>> imgs;
|
||||
pybind11::list imgsList;
|
||||
|
||||
if(vi.Grab(buffer,imgs,wait,newest)) {
|
||||
for(size_t s=0; s < vi.Streams().size(); ++s) {
|
||||
// Let's just return the first stream for the moment
|
||||
const pangolin::StreamInfo& si = vi.Streams()[s];
|
||||
const pangolin::Image<uint8_t> img = si.StreamImage(buffer);
|
||||
|
||||
const int c = si.PixFormat().channels;
|
||||
const std::string fmt = si.PixFormat().format;
|
||||
const int Bpp = si.PixFormat().bpp / (8);
|
||||
const int Bpc = Bpp / c;
|
||||
const int bpc = si.PixFormat().bpp / c;
|
||||
PANGO_ASSERT(bpc == 8 || bpc == 16 || bpc == 32, "only support 8, 16, 32 bits channel");
|
||||
|
||||
pangolin::Image<uint8_t> dstImage(
|
||||
new unsigned char[img.h * img.w * Bpp],
|
||||
img.w, img.h, img.w*Bpp
|
||||
);
|
||||
|
||||
pangolin::PitchedCopy((char*)dstImage.ptr, dstImage.pitch, (char*)img.ptr, img.pitch, img.w * Bpp, img.h);
|
||||
|
||||
// Create a Python object that will free the allocated memory
|
||||
pybind11::capsule free_when_done(dstImage.ptr,[](void* f) {
|
||||
unsigned char* buffer = (unsigned char*)f;
|
||||
delete[] buffer;
|
||||
});
|
||||
|
||||
if (bpc == 8) {
|
||||
imgsList.append(
|
||||
pybind11::array_t<uint8_t>(
|
||||
{(int)dstImage.h, (int)dstImage.w, c },
|
||||
{(int)dstImage.pitch, Bpp, Bpc},
|
||||
(uint8_t*)dstImage.ptr,
|
||||
free_when_done)
|
||||
);
|
||||
}
|
||||
else if (bpc == 16){
|
||||
imgsList.append(
|
||||
pybind11::array_t<uint16_t>(
|
||||
{(int)dstImage.h, (int)dstImage.w, c },
|
||||
{(int)dstImage.pitch, Bpp, Bpc},
|
||||
(uint16_t*)dstImage.ptr,
|
||||
free_when_done)
|
||||
);
|
||||
}
|
||||
else if (bpc == 32){
|
||||
if (fmt == "GRAY32")
|
||||
{
|
||||
imgsList.append(
|
||||
pybind11::array_t<uint32_t>(
|
||||
{(int)dstImage.h, (int)dstImage.w, c },
|
||||
{(int)dstImage.pitch, Bpp, Bpc},
|
||||
(uint32_t*)dstImage.ptr,
|
||||
free_when_done)
|
||||
);
|
||||
}
|
||||
else if (fmt == "GRAY32F" ||
|
||||
fmt == "RGB96F" ||
|
||||
fmt == "RGBA128F")
|
||||
{
|
||||
imgsList.append(
|
||||
pybind11::array_t<float>(
|
||||
{(int)dstImage.h, (int)dstImage.w, c },
|
||||
{(int)dstImage.pitch, Bpp, Bpc},
|
||||
(float*)dstImage.ptr,
|
||||
free_when_done)
|
||||
);
|
||||
}
|
||||
else{
|
||||
PANGO_ASSERT(false, "unsupported 32 bpc format");
|
||||
}
|
||||
}
|
||||
else{
|
||||
PANGO_ASSERT(false, "incompatible bpc");
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] buffer;
|
||||
return imgsList;
|
||||
}
|
||||
|
||||
picojson::value PicojsonFromPyObject(pybind11::object& obj)
|
||||
{
|
||||
// convert frame_properties to std::string via json.dumps(...)
|
||||
pybind11::module pymodjson = pybind11::module::import("json");
|
||||
auto pydumps = pymodjson.attr("dumps");
|
||||
const std::string json = pydumps(obj).cast<pybind11::str>();
|
||||
std::stringstream ss(json);
|
||||
picojson::value pjson;
|
||||
picojson::parse(pjson, ss);
|
||||
return pjson;
|
||||
}
|
||||
|
||||
void bind_video(pybind11::module& m){
|
||||
pybind11::class_<pangolin::VideoInterface, PyVideoInterface > video_interface(m, "VideoInterface");
|
||||
video_interface
|
||||
.def(pybind11::init<>())
|
||||
.def("SizeBytes", &pangolin::VideoInterface::SizeBytes)
|
||||
.def("Streams", &pangolin::VideoInterface::Streams)
|
||||
.def("Start", &pangolin::VideoInterface::Start)
|
||||
.def("Stop", &pangolin::VideoInterface::Stop)
|
||||
.def("GrabNext", &pangolin::VideoInterface::GrabNext)
|
||||
.def("GrabNewest", &pangolin::VideoInterface::GrabNewest);
|
||||
|
||||
pybind11::class_<pangolin::GenicamVideoInterface, PyGenicamVideoInterface > genicam_video_interface(m, "GenicamVideoInterface");
|
||||
genicam_video_interface
|
||||
.def(pybind11::init<>())
|
||||
.def("GetParameter", &pangolin::GenicamVideoInterface::GetParameter)
|
||||
.def("SetParameter", &pangolin::GenicamVideoInterface::SetParameter);
|
||||
|
||||
pybind11::class_<pangolin::BufferAwareVideoInterface, PyBufferAwareVideoInterface > buffer_aware_video_interface(m, "BufferAwareVideoInterface");
|
||||
buffer_aware_video_interface
|
||||
.def(pybind11::init<>())
|
||||
.def("AvailableFrames", &pangolin::BufferAwareVideoInterface::AvailableFrames)
|
||||
.def("DropNFrames", &pangolin::BufferAwareVideoInterface::DropNFrames);
|
||||
|
||||
pybind11::class_<pangolin::VideoPropertiesInterface, PyVideoPropertiesInterface > video_properties_interface(m, "VideoPropertiesInterface");
|
||||
video_properties_interface
|
||||
.def(pybind11::init<>())
|
||||
.def("DeviceProperties", &pangolin::VideoPropertiesInterface::DeviceProperties)
|
||||
.def("FrameProperties", &pangolin::VideoPropertiesInterface::FrameProperties);
|
||||
|
||||
pybind11::class_<pangolin::VideoFilterInterface, PyVideoFilterInterface > video_filter_interface(m, "VideoFilterInterface");
|
||||
video_filter_interface
|
||||
.def(pybind11::init<>())
|
||||
// .def("FindMatchingStreams", &pangolin::VideoFilterInterface::FindMatchingStreams)
|
||||
.def("InputStreams", &pangolin::VideoFilterInterface::InputStreams);
|
||||
|
||||
pybind11::class_<pangolin::VideoUvcInterface, PyVideoUvcInterface > video_uvc_interface(m, "VideoUvcInterface");
|
||||
video_uvc_interface
|
||||
.def(pybind11::init<>())
|
||||
.def("IoCtrl", &pangolin::VideoUvcInterface::IoCtrl)
|
||||
.def("GetExposure", &pangolin::VideoUvcInterface::GetExposure)
|
||||
.def("SetExposure", &pangolin::VideoUvcInterface::SetExposure)
|
||||
.def("GetGain", &pangolin::VideoUvcInterface::GetGain)
|
||||
.def("SetGain", &pangolin::VideoUvcInterface::SetGain);
|
||||
|
||||
pybind11::class_<pangolin::VideoPlaybackInterface, PyVideoPlaybackInterface > video_playback_interface(m, "VideoPlaybackInterface");
|
||||
video_playback_interface
|
||||
.def(pybind11::init<>())
|
||||
.def("GetCurrentFrameId", &pangolin::VideoPlaybackInterface::GetCurrentFrameId)
|
||||
.def("GetTotalFrames", &pangolin::VideoPlaybackInterface::GetTotalFrames)
|
||||
.def("Seek", &pangolin::VideoPlaybackInterface::Seek);
|
||||
|
||||
pybind11::class_<pangolin::VideoOutputInterface, PyVideoOutputInterface > video_output_interface(m, "VideoOutputInterface");
|
||||
video_output_interface
|
||||
.def(pybind11::init<>())
|
||||
.def("Streams", &pangolin::VideoOutputInterface::Streams)
|
||||
.def("SetStreams", &pangolin::VideoOutputInterface::SetStreams)
|
||||
.def("WriteStreams", &pangolin::VideoOutputInterface::WriteStreams)
|
||||
.def("IsPipe", &pangolin::VideoOutputInterface::IsPipe);
|
||||
|
||||
pybind11::enum_<pangolin::UvcRequestCode>(m, "UvcRequestCode")
|
||||
.value("UVC_RC_UNDEFINED", pangolin::UvcRequestCode::UVC_RC_UNDEFINED)
|
||||
.value("UVC_SET_CUR", pangolin::UvcRequestCode::UVC_SET_CUR)
|
||||
.value("UVC_GET_CUR", pangolin::UvcRequestCode::UVC_GET_CUR)
|
||||
.value("UVC_GET_MIN", pangolin::UvcRequestCode::UVC_GET_MIN)
|
||||
.value("UVC_GET_MAX", pangolin::UvcRequestCode::UVC_GET_MAX)
|
||||
.value("UVC_GET_RES", pangolin::UvcRequestCode::UVC_GET_RES)
|
||||
.value("UVC_GET_LEN", pangolin::UvcRequestCode::UVC_GET_LEN)
|
||||
.value("UVC_GET_INFO", pangolin::UvcRequestCode::UVC_GET_INFO)
|
||||
.value("UVC_GET_DEF", pangolin::UvcRequestCode::UVC_GET_DEF)
|
||||
.export_values();
|
||||
|
||||
/// This iterator enable pythonic video iterations a la `for frame in video_input: ...`
|
||||
struct VideoInputIterator {
|
||||
VideoInputIterator(pangolin::VideoInput& vi, pybind11::object ref) : vi(vi), ref(ref) { }
|
||||
|
||||
pybind11::list next() {
|
||||
pybind11::list result = VideoInputGrab(vi, true, false);
|
||||
if(result.size()==0)
|
||||
throw pybind11::stop_iteration();
|
||||
return result;
|
||||
}
|
||||
pangolin::VideoInput& vi;
|
||||
pybind11::object ref; // keep a reference
|
||||
};
|
||||
pybind11::class_<VideoInputIterator>(m, "Iterator")
|
||||
.def("__iter__", [](VideoInputIterator &it) -> VideoInputIterator& { return it; })
|
||||
.def("__next__", &VideoInputIterator::next);
|
||||
|
||||
pybind11::class_<pangolin::VideoInput>(m, "VideoInput", video_interface)
|
||||
.def(pybind11::init<>())
|
||||
.def(pybind11::init<const std::string&, const std::string&>(), pybind11::arg("input_uri"), pybind11::arg("output_uri")="pango:[buffer_size_mb=100]//video_log.pango")
|
||||
.def("SizeBytes", &pangolin::VideoInput::SizeBytes)
|
||||
.def("Streams", &pangolin::VideoInput::Streams)
|
||||
.def("Start", &pangolin::VideoInput::Start)
|
||||
.def("Stop", &pangolin::VideoInput::Stop)
|
||||
.def("InputStreams", &pangolin::VideoInput::InputStreams)
|
||||
.def("Open", &pangolin::VideoInput::Open, pybind11::arg("input_uri"), pybind11::arg("output_uri")="pango:[buffer_size_mb=100]//video_log.pango")
|
||||
.def("Close", &pangolin::VideoInput::Close)
|
||||
.def("Grab", VideoInputGrab, pybind11::arg("wait")=true, pybind11::arg("newest")=false )
|
||||
.def("GetStreamsBitDepth", [](pangolin::VideoInput& vi){
|
||||
std::vector<int> bitDepthList;
|
||||
for(size_t s=0; s < vi.Streams().size(); ++s) {
|
||||
bitDepthList.push_back(vi.Streams()[s].PixFormat().channel_bit_depth);
|
||||
}
|
||||
return bitDepthList;
|
||||
})
|
||||
.def("GetNumStreams", [](pangolin::VideoInput& vi){
|
||||
return (int) vi.Streams().size();
|
||||
})
|
||||
.def("GetCurrentFrameId", [](pangolin::VideoInput& vi){
|
||||
return (int) vi.Cast<pangolin::VideoPlaybackInterface>()->GetCurrentFrameId();
|
||||
})
|
||||
.def("GetTotalFrames", [](pangolin::VideoInput& vi){
|
||||
return (int) vi.Cast<pangolin::VideoPlaybackInterface>()->GetTotalFrames();
|
||||
})
|
||||
.def("Seek", [](pangolin::VideoInput& vi, size_t frameid){
|
||||
vi.Cast<pangolin::VideoPlaybackInterface>()->Seek(frameid);
|
||||
return;
|
||||
})
|
||||
.def("DeviceProperties", [](pangolin::VideoInput& vi) -> pybind11::object {
|
||||
// Use std::string as an intermediate representation
|
||||
const std::string props = vi.template Cast<pangolin::VideoPropertiesInterface>()->DeviceProperties().serialize();
|
||||
pybind11::module pymodjson = pybind11::module::import("json");
|
||||
auto pyloads = pymodjson.attr("loads");
|
||||
auto json = pyloads(pybind11::str(props));
|
||||
return json;
|
||||
})
|
||||
.def("FrameProperties", [](pangolin::VideoInput& vi) -> pybind11::object {
|
||||
// Use std::string as an intermediate representation
|
||||
const std::string props = vi.template Cast<pangolin::VideoPropertiesInterface>()->FrameProperties().serialize();
|
||||
pybind11::module pymodjson = pybind11::module::import("json");
|
||||
auto pyloads = pymodjson.attr("loads");
|
||||
auto json = pyloads(pybind11::str(props));
|
||||
return json;
|
||||
})
|
||||
.def("Width", &pangolin::VideoInput::Width)
|
||||
.def("Height", &pangolin::VideoInput::Height)
|
||||
.def("PixFormat", &pangolin::VideoInput::PixFormat)
|
||||
.def("VideoUri", &pangolin::VideoInput::VideoUri)
|
||||
.def("Reset", &pangolin::VideoInput::Reset)
|
||||
.def("LogFilename", (const std::string& (pangolin::VideoInput::*)() const)&pangolin::VideoInput::LogFilename)
|
||||
.def("LogFilename", (std::string& (pangolin::VideoInput::*)())&pangolin::VideoInput::LogFilename)
|
||||
.def("Record", &pangolin::VideoInput::Record)
|
||||
.def("RecordOneFrame", &pangolin::VideoInput::RecordOneFrame)
|
||||
.def("SetTimelapse", &pangolin::VideoInput::SetTimelapse)
|
||||
.def("IsRecording", &pangolin::VideoInput::IsRecording)
|
||||
.def("__iter__", [](pybind11::object s) { return VideoInputIterator(s.cast<pangolin::VideoInput&>(), s);});
|
||||
|
||||
pybind11::class_<pangolin::VideoOutput>(m, "VideoOutput", video_output_interface)
|
||||
.def(pybind11::init<>())
|
||||
.def(pybind11::init<const std::string&>())
|
||||
.def("IsOpen", &pangolin::VideoOutput::IsOpen)
|
||||
.def("Open", &pangolin::VideoOutput::Open)
|
||||
.def("Close", &pangolin::VideoOutput::Close)
|
||||
.def("Streams", &pangolin::VideoOutput::Streams)
|
||||
.def("WriteStreams", [](pangolin::VideoOutput& vo, pybind11::list images, const std::vector<int> &streamsBitDepth, pybind11::object frame_properties, pybind11::object device_properties, const std::string& descriptive_uri){
|
||||
if(vo.SizeBytes()==0) {
|
||||
PANGO_ASSERT(streamsBitDepth.size() == images.size() || streamsBitDepth.size() == 0);
|
||||
|
||||
// Setup stream info
|
||||
for(size_t i = 0; i < images.size(); ++i){
|
||||
// num bits per channel
|
||||
auto arr = pybind11::array::ensure(images[i]);
|
||||
|
||||
// num channels
|
||||
PANGO_ASSERT(arr.ndim() == 2 || arr.ndim() == 3, "Method only accepts ndarrays of 2 or 3 dimensions.");
|
||||
const size_t channels = (arr.ndim() == 3) ? arr.shape(2) : 1;
|
||||
|
||||
std::string fmtStr;
|
||||
if(pybind11::isinstance<pybind11::array_t<std::uint8_t>>(arr)){
|
||||
if(channels == 1) fmtStr = "GRAY8";
|
||||
else if(channels == 3) fmtStr = "RGB24";
|
||||
else if(channels == 4) fmtStr = "RGBA32";
|
||||
else PANGO_ASSERT(false, "Only 1, 3 and 4 channel uint8_t formats are supported.");
|
||||
} else if (pybind11::isinstance<pybind11::array_t<std::uint16_t>>(arr)){
|
||||
if(channels == 1) fmtStr = "GRAY16LE";
|
||||
else if(channels == 3) fmtStr = "RGB48";
|
||||
else if(channels == 4) fmtStr = "RGBA64";
|
||||
else PANGO_ASSERT(false, "Only 1, 3 and 4 channel uint16_t formats are supported.");
|
||||
} else if (pybind11::isinstance<pybind11::array_t<std::float_t>>(arr)){
|
||||
if(channels == 1) fmtStr = "GRAY32F";
|
||||
else if(channels == 3) fmtStr = "RGB96F";
|
||||
else if(channels == 4) fmtStr = "RGBA128F";
|
||||
else PANGO_ASSERT(false, "Only 1, 3 and 4 channel float_t formats are supported.");
|
||||
} else if (pybind11::isinstance<pybind11::array_t<std::double_t>>(arr)){
|
||||
if(channels == 1) fmtStr = "GRAY64F";
|
||||
else PANGO_ASSERT(false, "Only 1 channel double_t format is supported.");
|
||||
} else {
|
||||
PANGO_ASSERT(false, "numpy dtype must be either uint8_t, uint16_t, float_t or double_t");
|
||||
}
|
||||
|
||||
pangolin::PixelFormat pf = pangolin::PixelFormatFromString(fmtStr);
|
||||
if(streamsBitDepth.size())
|
||||
pf.channel_bit_depth = (unsigned int) streamsBitDepth[i];
|
||||
|
||||
vo.AddStream(pf, arr.shape(1), arr.shape(0));
|
||||
}
|
||||
|
||||
picojson::value json_device_properties;
|
||||
if(device_properties) {
|
||||
json_device_properties = PicojsonFromPyObject(device_properties);
|
||||
}
|
||||
|
||||
vo.SetStreams(descriptive_uri, json_device_properties);
|
||||
}
|
||||
|
||||
picojson::value json_frame_properties;
|
||||
if(frame_properties) {
|
||||
json_frame_properties = PicojsonFromPyObject(frame_properties);
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> buffer(new uint8_t[vo.SizeBytes()]);
|
||||
std::vector<pangolin::Image<unsigned char>> bimgs = vo.GetOutputImages(buffer.get());
|
||||
PANGO_ASSERT(bimgs.size() == images.size(), "length of input streams not consistent");
|
||||
for(size_t i=0; i < images.size(); ++i) {
|
||||
const pangolin::StreamInfo& so = vo.Streams()[i];
|
||||
const unsigned int bpc = so.PixFormat().channel_bit_depth;
|
||||
const unsigned int Bpp = so.PixFormat().bpp / (8);
|
||||
if (bpc == 8){
|
||||
pybind11::array_t<uint8_t> arr = images[i].cast<pybind11::array_t<unsigned char, pybind11::array::c_style | pybind11::array::forcecast>>();
|
||||
pangolin::Image<uint8_t> srcImg(arr.mutable_data(0,0), bimgs[i].w, bimgs[i].h, bimgs[i].w * Bpp);
|
||||
pangolin::PitchedCopy((char*)bimgs[i].ptr, bimgs[i].pitch, (char*)srcImg.ptr,
|
||||
srcImg.pitch, srcImg.pitch, srcImg.h);
|
||||
}else if (bpc == 12 || bpc == 16){
|
||||
pybind11::array_t<uint16_t> arr = images[i].cast<pybind11::array_t<uint16_t, pybind11::array::c_style | pybind11::array::forcecast>>();
|
||||
pangolin::Image<uint16_t> srcImg(arr.mutable_data(0,0), bimgs[i].w, bimgs[i].h, bimgs[i].w * Bpp);
|
||||
pangolin::PitchedCopy((char*)bimgs[i].ptr, bimgs[i].pitch, (char*)srcImg.ptr,
|
||||
srcImg.pitch, srcImg.pitch, srcImg.h);
|
||||
}else if (bpc == 32){
|
||||
pybind11::array_t<float_t> arr = images[i].cast<pybind11::array_t<float_t, pybind11::array::c_style | pybind11::array::forcecast>>();
|
||||
pangolin::Image<float_t> srcImg(arr.mutable_data(0,0), bimgs[i].w, bimgs[i].h, bimgs[i].w * Bpp);
|
||||
pangolin::PitchedCopy((char*)bimgs[i].ptr, bimgs[i].pitch, (char*)srcImg.ptr,
|
||||
srcImg.pitch, srcImg.pitch, srcImg.h);
|
||||
}else if (bpc == 64){
|
||||
pybind11::array_t<double_t> arr = images[i].cast<pybind11::array_t<double_t, pybind11::array::c_style | pybind11::array::forcecast>>();
|
||||
pangolin::Image<double_t> srcImg(arr.mutable_data(0,0), bimgs[i].w, bimgs[i].h, bimgs[i].w * Bpp);
|
||||
pangolin::PitchedCopy((char*)bimgs[i].ptr, bimgs[i].pitch, (char*)srcImg.ptr,
|
||||
srcImg.pitch, srcImg.pitch, srcImg.h);
|
||||
}else{
|
||||
PANGO_ASSERT(false, "format must have 8, 12, 16, 32 or 64 bit depth");
|
||||
}
|
||||
}
|
||||
vo.WriteStreams(buffer.get(), json_frame_properties);
|
||||
}, pybind11::arg("images"), pybind11::arg("streamsBitDepth") = std::vector<int>(), pybind11::arg("frame_properties") = pybind11::none(), pybind11::arg("device_properties") = pybind11::none(), pybind11::arg("descriptive_uri") = "python://")
|
||||
.def("IsPipe", &pangolin::VideoOutput::IsPipe)
|
||||
.def("AddStream", (void (pangolin::VideoOutput::*)(const pangolin::PixelFormat&, size_t,size_t,size_t))&pangolin::VideoOutput::AddStream)
|
||||
.def("AddStream", (void (pangolin::VideoOutput::*)(const pangolin::PixelFormat&, size_t,size_t))&pangolin::VideoOutput::AddStream)
|
||||
.def("SizeBytes", &pangolin::VideoOutput::SizeBytes)
|
||||
.def("GetOutputImages", (std::vector<pangolin::Image<unsigned char>> (pangolin::VideoOutput::*)(unsigned char*) const)&pangolin::VideoOutput::GetOutputImages)
|
||||
.def("GetOutputImages", (std::vector<pangolin::Image<unsigned char>> (pangolin::VideoOutput::*)(std::vector<unsigned char>&) const)&pangolin::VideoOutput::GetOutputImages);
|
||||
|
||||
}
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/video.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/video.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_video(pybind11::module& m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
86
thirdparty/Pangolin/src/python/pypangolin/view.cpp
vendored
Normal file
86
thirdparty/Pangolin/src/python/pypangolin/view.cpp
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "view.hpp"
|
||||
#include <pangolin/display/view.h>
|
||||
#include <pangolin/display/opengl_render_state.h>
|
||||
#include <pangolin/handler/handler.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_view(pybind11::module &m) {
|
||||
pybind11::class_<pangolin::View>(m, "View")
|
||||
.def(pybind11::init<double>(), pybind11::arg("aspect") = 0.0)
|
||||
.def("Activate", (void(pangolin::View::*)() const)&pangolin::View::Activate)
|
||||
.def("Activate", (void(pangolin::View::*)(const pangolin::OpenGlRenderState&) const)&pangolin::View::Activate)
|
||||
.def("ActivateAndScissor", (void(pangolin::View::*)() const)&pangolin::View::ActivateAndScissor)
|
||||
.def("ActivateScissorAndClear", (void(pangolin::View::*)() const)&pangolin::View::ActivateScissorAndClear)
|
||||
.def("ActivateAndScissor", (void(pangolin::View::*)(const pangolin::OpenGlRenderState&) const)&pangolin::View::ActivateAndScissor)
|
||||
.def("ActivateScissorAndClear", (void(pangolin::View::*)(const pangolin::OpenGlRenderState&) const)&pangolin::View::ActivateScissorAndClear)
|
||||
.def("ActivatePixelOrthographic", &pangolin::View::ActivatePixelOrthographic)
|
||||
.def("ActivateIdentity", &pangolin::View::ActivateIdentity)
|
||||
.def("GetClosestDepth", &pangolin::View::GetClosestDepth)
|
||||
.def("GetCamCoordinates", &pangolin::View::GetCamCoordinates)
|
||||
.def("GetObjectCoordinates", &pangolin::View::GetObjectCoordinates)
|
||||
.def("Resize", &pangolin::View::Resize)
|
||||
.def("ResizeChildren", &pangolin::View::ResizeChildren)
|
||||
.def("Render", &pangolin::View::Render)
|
||||
.def("RenderChildren", &pangolin::View::RenderChildren)
|
||||
.def("SetFocus", &pangolin::View::SetFocus)
|
||||
.def("HasFocus", &pangolin::View::HasFocus)
|
||||
.def("SetBounds", (pangolin::View& (pangolin::View::*)(pangolin::Attach, pangolin::Attach, pangolin::Attach, pangolin::Attach))&pangolin::View::SetBounds)
|
||||
.def("SetBounds", (pangolin::View& (pangolin::View::*)(pangolin::Attach, pangolin::Attach, pangolin::Attach, pangolin::Attach, bool))&pangolin::View::SetBounds)
|
||||
.def("SetBounds", (pangolin::View& (pangolin::View::*)(pangolin::Attach, pangolin::Attach, pangolin::Attach, pangolin::Attach, double))&pangolin::View::SetBounds)
|
||||
.def("SetHandler", [](pangolin::View& v, pangolin::Handler& h) -> pangolin::View& {return v.SetHandler(&h);}, pybind11::return_value_policy::reference)
|
||||
.def("SetDrawFunction", &pangolin::View::SetDrawFunction)
|
||||
.def("SetAspect", &pangolin::View::SetAspect)
|
||||
.def("SetLock", &pangolin::View::SetLock)
|
||||
.def("SetLayout", &pangolin::View::SetLayout)
|
||||
.def("AddDisplay", &pangolin::View::AddDisplay)
|
||||
.def("Show", &pangolin::View::Show, pybind11::arg("show") = true)
|
||||
.def("ToggleShow", &pangolin::View::ToggleShow)
|
||||
.def("IsShown", &pangolin::View::IsShown)
|
||||
.def("GetBounds", &pangolin::View::GetBounds)
|
||||
.def("SaveOnRender", &pangolin::View::SaveOnRender)
|
||||
.def("RecordOnRender", &pangolin::View::RecordOnRender)
|
||||
.def("SaveRenderNow", &pangolin::View::SaveRenderNow)
|
||||
.def("NumChildren", &pangolin::View::NumChildren)
|
||||
.def("GetChild", [] (pangolin::View &v, size_t i) -> pangolin::View& { return v[i];}, pybind11::return_value_policy::reference)
|
||||
.def("VisibleChild", &pangolin::View::VisibleChild)
|
||||
.def("FindChild", &pangolin::View::FindChild)
|
||||
.def("NumVisibleChildren", &pangolin::View::NumVisibleChildren);
|
||||
|
||||
pybind11::enum_<pangolin::Layout>(m, "Layout")
|
||||
.value("Overlay", pangolin::LayoutOverlay)
|
||||
.value("Vertical", pangolin::LayoutVertical)
|
||||
.value("Horizontal", pangolin::LayoutHorizontal)
|
||||
.value("Equal", pangolin::LayoutEqual)
|
||||
.value("EqualVertical", pangolin::LayoutEqualVertical)
|
||||
.value("EqualHorizontal", pangolin::LayoutEqualHorizontal);
|
||||
|
||||
}
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/view.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/view.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_view(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
56
thirdparty/Pangolin/src/python/pypangolin/viewport.cpp
vendored
Normal file
56
thirdparty/Pangolin/src/python/pypangolin/viewport.cpp
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "viewport.hpp"
|
||||
#include <pangolin/display/viewport.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_viewport(pybind11::module &m) {
|
||||
pybind11::class_<pangolin::Viewport>(m, "Viewport")
|
||||
.def(pybind11::init<>())
|
||||
.def(pybind11::init<int, int, int, int>())
|
||||
.def("Activate", &pangolin::Viewport::Activate)
|
||||
.def("ActivateIdentity", &pangolin::Viewport::ActivateIdentity)
|
||||
.def("ActivatePixelOrthographic", &pangolin::Viewport::ActivatePixelOrthographic)
|
||||
.def("Scissor", &pangolin::Viewport::Scissor)
|
||||
.def("ActivateAndScissor", &pangolin::Viewport::ActivateAndScissor)
|
||||
.def("Contains", &pangolin::Viewport::Contains)
|
||||
.def("Inset", (pangolin::Viewport (pangolin::Viewport::*)(int)const)&pangolin::Viewport::Inset)
|
||||
.def("Inset", (pangolin::Viewport (pangolin::Viewport::*)(int, int)const)&pangolin::Viewport::Inset)
|
||||
.def("Insetsect", &pangolin::Viewport::Intersect)
|
||||
.def("DisableScissor", &pangolin::Viewport::DisableScissor)
|
||||
.def("r", &pangolin::Viewport::r)
|
||||
.def("t", &pangolin::Viewport::t)
|
||||
.def("aspect", &pangolin::Viewport::aspect)
|
||||
.def_readwrite("l", &pangolin::Viewport::l)
|
||||
.def_readwrite("b", &pangolin::Viewport::b)
|
||||
.def_readwrite("w", &pangolin::Viewport::w)
|
||||
.def_readwrite("h", &pangolin::Viewport::h);
|
||||
}
|
||||
|
||||
} // py_pangolin
|
||||
38
thirdparty/Pangolin/src/python/pypangolin/viewport.hpp
vendored
Normal file
38
thirdparty/Pangolin/src/python/pypangolin/viewport.hpp
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
|
||||
namespace py_pangolin{
|
||||
|
||||
void bind_viewport(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
36
thirdparty/Pangolin/src/python/pypangolin/widget.cpp
vendored
Normal file
36
thirdparty/Pangolin/src/python/pypangolin/widget.cpp
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 "widget.hpp"
|
||||
#include <pangolin/display/widgets/widgets.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_widget(pybind11::module &m){
|
||||
m.def("CreatePanel", &pangolin::CreatePanel, pybind11::return_value_policy::reference);
|
||||
}
|
||||
} // py_pangolin
|
||||
37
thirdparty/Pangolin/src/python/pypangolin/widget.hpp
vendored
Normal file
37
thirdparty/Pangolin/src/python/pypangolin/widget.hpp
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) Andrey Mnatsakanov
|
||||
*
|
||||
* 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 <pybind11/pybind11.h>
|
||||
|
||||
namespace py_pangolin {
|
||||
|
||||
void bind_widget(pybind11::module &m);
|
||||
|
||||
} // py_pangolin
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user